LEARN CLAUDE CODE
S12: Worktree + Task Isolation — 目录隔离
问题:共享目录导致文件冲突
到 S11 为止,多个 Teammate 都在同一个工作目录里操作。这在实际中会导致严重的文件冲突——agent-A 正在修改 src/auth.ts,agent-B 同时也在改同一个文件。结果就是覆盖、冲突、代码丢失。
冲突场景:
Agent-A: 打开 src/auth.ts → 修改第30行 → 保存
Agent-B: 打开 src/auth.ts → 修改第45行 → 保存 (覆盖了 A 的修改!)
┌─── 共享工作目录 ───┐
│ src/ │
│ auth.ts ← A 在改│
│ auth.ts ← B 也在改│ ← 冲突!
│ db.ts │
│ api.ts │
└────────────────────┘
解法:Git Worktree 绑定任务 ID
Git Worktree 是 Git 的一个内置功能——它允许从同一个仓库创建多个工作目录,每个工作目录有自己独立的分支和文件。S12 的设计是:每个任务绑定一个 Worktree,实现完全的文件隔离。
隔离方案:
┌─── .worktrees/task-001/ ───┐ ┌─── .worktrees/task-002/ ───┐
│ branch: task-001 │ │ branch: task-002 │
│ src/ │ │ src/ │
│ auth.ts ← A 独占修改 │ │ auth.ts ← B 独占修改 │
│ db.ts │ │ db.ts │
│ api.ts │ │ api.ts │
└───────────────────────────┘ └───────────────────────────┘
│ │
└───────── 互不干扰 ────────────────┘
│
最后通过 Git merge 合并
双平面架构
S12 引入了一个清晰的架构分离——控制平面和执行平面:
| 平面 | 目录 | 内容 | 角色 |
|---|---|---|---|
| Control Plane(控制平面) | .tasks/ |
任务 JSON 文件、状态、依赖关系 | 描述"要做什么"——任务的元数据和协调信息 |
| Execution Plane(执行平面) | .worktrees/ |
每个任务的独立工作目录、Git 分支 | 执行"怎么做"——实际的代码修改在这里发生 |
双平面架构图:
┌──────────────────────────────────────────────────────────┐
│ Control Plane │
│ │
│ .tasks/ │
│ ├── task-001.json { status: "in_progress", ... } │
│ ├── task-002.json { status: "pending", ... } │
│ └── task-003.json { status: "completed", ... } │
│ │
│ 协调层:任务状态、依赖关系、Owner 分配 │
├──────────────────────────────────────────────────────────┤
│ Execution Plane │
│ │
│ .worktrees/ │
│ ├── task-001/ ← Agent-A 的独立工作目录 │
│ │ └── (完整的项目文件副本,branch: task-001) │
│ ├── task-002/ ← Agent-B 的独立工作目录 │
│ │ └── (完整的项目文件副本,branch: task-002) │
│ └── events.jsonl ← 事件流 │
│ │
│ 隔离层:每个任务独立修改文件,互不干扰 │
└──────────────────────────────────────────────────────────┘
Events 流
.worktrees/events.jsonl 记录了所有 Worktree 相关的事件——创建、切换、合并、删除。这是一个只追加的日志文件,用于审计和崩溃恢复。
{"event":"worktree_created", "taskId":"task-001", "branch":"task-001", "ts":"2025-01-15T10:00:00Z"}
{"event":"agent_entered", "taskId":"task-001", "agentId":"agent-frontend", "ts":"2025-01-15T10:00:01Z"}
{"event":"agent_exited", "taskId":"task-001", "agentId":"agent-frontend", "ts":"2025-01-15T11:30:00Z"}
{"event":"worktree_merged", "taskId":"task-001", "branch":"task-001", "ts":"2025-01-15T11:35:00Z"}
崩溃恢复:从磁盘状态重建
如果代理进程崩溃了怎么办?S12 的设计保证了完全可恢复——因为所有状态都在磁盘上:
- 扫描
.tasks/——重建任务图,知道哪些任务在进行中 - 扫描
.worktrees/——知道哪些 Worktree 存在、对应哪个任务 - 读取
events.jsonl——知道崩溃前的最后状态 - 恢复——对于
in_progress状态的任务,重新启动代理进入对应的 Worktree 继续工作
进程崩溃
→
重启
→
扫描 .tasks/
→
扫描 .worktrees/
→
重建状态
→
继续执行
对比:共享目录 vs Worktree 隔离
| 维度 | 共享目录(S09-S11) | Worktree 隔离(S12) |
|---|---|---|
| 文件冲突 | 频繁发生 | 不可能(物理隔离) |
| Git 操作 | 所有代理共用一个分支 | 每个任务独立分支 |
| 合并策略 | 需要锁或协调 | 标准 Git merge/rebase |
| 回滚 | 困难——修改交织 | 简单——删除 Worktree 即可 |
| 崩溃恢复 | 状态不确定 | 从磁盘完全重建 |
| 磁盘占用 | 一份 | 每任务一份副本(Git 优化后较小) |
对应官方工具
EnterWorktreeTool / ExitWorktreeTool
EnterWorktreeTool 创建或进入一个与任务绑定的 Git Worktree,自动创建对应分支。ExitWorktreeTool 退出 Worktree 并回到主目录。官方实现自动处理了 Worktree 的创建、分支管理和清理,代理只需要说"进入"和"退出"。
关键洞察:S12 的双平面架构体现了一个重要的工程原则——控制平面和数据平面分离。
.tasks/ 是控制平面(协调信息),.worktrees/ 是数据平面(实际执行)。这和 Kubernetes 的架构思想一致——etcd 存控制状态,Pod 做实际计算。分离后,崩溃恢复变得简单,因为控制状态是独立且持久的。