learn claude code S12 Worktree 任务隔离详解笔记
初学者允许你从同一个仓库创建多个工作目录,每个目录有自己的分支。它们共享同一个.git目录(节省磁盘空间),但文件系统完全隔离。主仓库: /project (branch: main)每个 worktree 像一个独立的克隆,但不需要重新 clone 整个仓库。创建 worktree 通常只需要几秒钟。
S12 Worktree 任务隔离详解笔记
基于
s12_worktree_task_isolation.py源码逐行分析,配合s12-worktree-task-isolation.md设计思路。
一、问题:多个任务共享一个工作目录,互相踩踏
前面 11 章的 agent 都在同一个工作目录下操作。当只有一个 agent 时没问题。但当 s09-s11 引入了多 agent 团队后:
- Alice 在改
utils.py,Bob 也在改utils.py→ 冲突 - Alice 跑了
pip install flask,Bob 跑了pip install django→ 全局环境污染 - Alice 的测试需要 Python 3.10,Bob 需要 3.8 → 不可能同时满足
共享文件系统是多 agent 并行的最大阻碍。 每个 agent 需要一个独立的工作空间,但又能共享代码基础。
s12 的解决方案:Git worktree。 每个任务分配一个独立的 worktree 目录,agent 在里面为所欲为——修改、装包、跑测试——不影响其他人。完成后,worktree 可以被保留(keep)或删除(remove)。
二、什么是 Git Worktree?
初学者:git worktree 允许你从同一个仓库创建多个工作目录,每个目录有自己的分支。它们共享同一个 .git 目录(节省磁盘空间),但文件系统完全隔离。
主仓库: /project (branch: main)
worktree: /project/.worktrees/auth (branch: wt/auth)
worktree: /project/.worktrees/api (branch: wt/api)
每个 worktree 像一个独立的克隆,但不需要重新 clone 整个仓库。创建 worktree 通常只需要几秒钟。
三、和 s11 相比,多了什么?
| 组件 | s11 | s12 |
|---|---|---|
| 执行隔离 | 无(共享目录) | Git worktree(目录级隔离) |
| 任务绑定 | 无 | task.worktree 字段 + bind_worktree() |
| 事件追踪 | 无 | EventBus:生命周期事件日志 |
| 新工具 | idle, claim_task |
worktree_create/list/status/run/keep/remove + worktree_events |
| 工具数量 | 14 | 16 |
四、EventBus:可观测性的基础设施
class EventBus:
def __init__(self, event_log_path: Path):
self.path = event_log_path
self.path.parent.mkdir(parents=True, exist_ok=True)
def emit(self, event: str, task=None, worktree=None, error=None):
payload = {
"event": event,
"ts": time.time(),
"task": task or {},
"worktree": worktree or {},
}
if error:
payload["error"] = error
with self.path.open("a") as f:
f.write(json.dumps(payload) + "\n")
def list_recent(self, limit: int = 20) -> str:
# 返回最近 N 条事件,用于调试和监控
EventBus 记录 worktree 和 task 的完整生命周期:
worktree.create.before → worktree.create.after (或 .failed)
worktree.remove.before → worktree.remove.after (或 .failed)
worktree.keep
task.completed
这不是给模型看的——是给开发者和运维工具看的。当系统出现异常(worktree 创建失败、任务卡住),事件日志是回溯问题的第一手资料。s12 是系列中第一个引入面向人类的可观测性的章节。
五、WorktreeManager:Git Worktree 的生命周期
5.1 初始化
class WorktreeManager:
def __init__(self, repo_root: Path, tasks: TaskManager, events: EventBus):
self.git_available = self._is_git_repo()
self.index_path = self.dir / "index.json"
index.json 是 worktree 的注册表——记录所有 worktree 的名称、路径、分支、关联任务、状态。
5.2 create() — 创建 worktree
def create(self, name: str, task_id: int = None, base_ref: str = "HEAD") -> str:
self._validate_name(name)
if self._find(name):
raise ValueError(f"Worktree '{name}' already exists")
path = self.dir / name
branch = f"wt/{name}"
self.events.emit("worktree.create.before", ...)
# 核心:执行 git worktree add
self._run_git(["worktree", "add", "-b", branch, str(path), base_ref])
# 写入 index
entry = {"name": name, "path": str(path), "branch": branch,
"task_id": task_id, "status": "active", "created_at": time.time()}
idx["worktrees"].append(entry)
# 绑定到任务
if task_id is not None:
self.tasks.bind_worktree(task_id, name)
self.events.emit("worktree.create.after", ...)
base_ref 默认为 HEAD(当前分支的最新提交)。名字校验 [A-Za-z0-9._-]{1,40} 阻止特殊字符——因为 worktree 名会变成目录名和分支名。
5.3 run() — 在 worktree 中执行命令
def run(self, name: str, command: str) -> str:
wt = self._find(name)
path = Path(wt["path"])
r = subprocess.run(
command,
shell=True,
cwd=path, # ← 关键:cwd 指向 worktree 目录
capture_output=True,
text=True,
timeout=300,
)
return (r.stdout + r.stderr).strip()[:50000]
和 run_bash 的唯一区别:cwd 指向 worktree 目录而非主工作目录。agent 可以在 worktree 中装包、改代码、跑测试——一切操作隔离在 worktree 内。
5.4 remove() — 删除 worktree
def remove(self, name: str, force: bool = False, complete_task: bool = False):
self._run_git(["worktree", "remove", "--force" if force else "", wt["path"]])
if complete_task and wt.get("task_id") is not None:
self.tasks.update(task_id, status="completed")
self.tasks.unbind_worktree(task_id)
idx["worktrees"][...]["status"] = "removed"
如果 complete_task: true,自动把关联任务标记为完成并解绑——一条命令完成"清理 workspace + 完成任务"。
5.5 keep() — 保留 worktree
def keep(self, name: str) -> str:
idx["worktrees"][...]["status"] = "kept"
idx["worktrees"][...]["kept_at"] = time.time()
不删除 worktree,只在 index 中标记为 kept。适合"代码还需要审查"或"先保留以备后续修改"的场景。
六、TaskManager 的扩展
s12 的 TaskManager 在 s07 的基础上新增了 worktree 字段和 bind_worktree / unbind_worktree 方法:
def bind_worktree(self, task_id: int, worktree: str, owner: str = "") -> str:
task = self._load(task_id)
task["worktree"] = worktree
if owner:
task["owner"] = owner
if task["status"] == "pending":
task["status"] = "in_progress"
self._save(task)
def unbind_worktree(self, task_id: int) -> str:
task = self._load(task_id)
task["worktree"] = ""
self._save(task)
任务和 worktree 之间是一对一的关系。task.worktree 字段记录了"这个任务在哪个隔离环境中执行"。
七、两个 Manager 的协作
Task 创建 → task.status = "pending"
↓
Worktree 创建 → task.bind_worktree(task_id, wt_name)
↓ task.status → "in_progress"
Agent 在 worktree 中工作 → worktree_run(wt_name, "pip install flask")
↓
工作完成 → worktree_remove(name, complete_task=True)
↓ task.status → "completed"
task.worktree → ""
Tasks 是控制面(管"该做什么"),Worktrees 是执行面(管"在哪里做")。两者的关联通过 task.worktree 字段 + bind_worktree 方法桥接。
八、完整流程走读
场景
用户:“重构认证模块,在隔离环境中进行,完成后清理。”
第 1 轮
Lead 创建任务:task_create("重构认证模块") → task 12。
第 2 轮
Lead 创建 worktree:worktree_create("auth-refactor", task_id=12) → 在 .worktrees/auth-refactor/ 创建隔离目录,分支 wt/auth-refactor。Task 12 的 status 自动变为 in_progress,worktree 设为 "auth-refactor"。
第 3-10 轮
Lead 在 worktree 中工作:worktree_run("auth-refactor", "pip install bcrypt")、worktree_run("auth-refactor", "python -m pytest tests/auth/")。所有修改在 wt/auth-refactor 分支上进行,主工作区完全不受影响。
第 11 轮
Lead 完成工作:worktree_remove("auth-refactor", complete_task=True) → worktree 被删除,Task 12 自动标记为 completed。分支可以后续合并回 main。
如果出错了
worktree_events(limit=10) 显示最近 10 条事件:
{"event": "worktree.create.after", "worktree": {"name": "auth-refactor", "status": "active"}}
{"event": "worktree.remove.failed", "worktree": {"name": "auth-refactor"}, "error": "worktree contains uncommitted changes"}
Lead 看到错误,改用 worktree_remove("auth-refactor", force=True) 强制删除,或用 worktree_keep("auth-refactor") 保留下来手动处理。
九、设计洞察
9.1 控制面与执行面的分离
Tasks(控制面)回答"做什么",Worktrees(执行面)回答"在哪里做"。两者通过 task.worktree 字段关联,各自独立演化。这种分离让系统可以:
- 换一种执行隔离方式(容器而非 worktree)而不影响任务管理
- 换一种任务管理方式(Kanban 而非 JSON)而不影响执行隔离
9.2 Git 作为平台
s12 大量依赖 Git(worktree add、worktree remove、rev-parse)。在很多人眼中 Git 是"版本控制工具",但在这里 Git 是文件系统管理平台。git worktree 解决了"在同一仓库中创建多个独立工作目录"的问题——这个问题自己实现可能需要上千行代码。
站在巨人的肩膀上,而不是自己造轮子。 这是工程中最重要的判断力之一。
9.3 可观测性不是后加的
EventBus 从 worktree 创建的第一步就记录事件。事件覆盖了完整的生命周期:before → after/failed,每条事件带时间戳、关联的 task、关联的 worktree。当系统变得不可预测(异步操作、多线程、外部依赖),事件日志是你理解"发生了什么"的唯一窗口。
9.4 s12 是整个系列的终章——也是新起点
回头看整个系列:
s01: 循环 ← agent 能动了
s02: 工具 ← agent 能操作文件系统了
s03: 计划 ← agent 能追踪进度了
s04: 子 agent ← agent 能委托任务了
s05: 知识 ← agent 能按需学习领域专长了
s06: 压缩 ← agent 能无限工作了
s07: 任务图 ← 状态在对话之外存活了
s08: 后台 ← agent 不等命令了
s09: 团队 ← agent 能合作了
s10: 协议 ← agent 能握手了
s11: 自主 ← agent 自己找工作了
s12: 隔离 ← agent 能在独立空间中工作了
s12 的 worktree 隔离让多 agent 并行成为可能——这是从"单机单 agent"到"分布式 agent 网络"的桥梁。虽然这个系列的代码在 s12 结束,但它指向的方向远不止于此。
更多推荐



所有评论(0)