锁把并行写变成有序覆盖,不能给两项并行工作提供独立版本。Git Worktree 提供物理目录隔离并复用同一个 Git 对象库。
repository-root/
├ .git/
├ .agent_tutorial/{tasks.sqlite3, worktrees/}
│ ├ alice/ branch: wt/alice
│ └ bob/ branch: wt/bob
└ source files integration ref 所在主工作目录
reserved → active → kept → removed;active 可失败转 needs_review。绑定创建不会把 Task 从 pending 推进 in_progress。
reserved -> active -> kept ---------> removed
| ^
+-> needs_review --+
|
+-----------------> removed
先持久化意图(SQLite reserved + event),再 git worktree add;成功后凭读回证据才迁移 active。顺序反了会让「目录建了但没登记」这类孤儿副作用比多余状态记录严重得多。Git 子进程用 execFile 参数数组,不经过 shell;validateRepository 要求 workspace 正好是仓库根,子目录不行。
验证 Git 根 → 解析 integration_ref 为 baseline commit
→ 写入 reserved binding + reserve event
→ git worktree add -b wt/{name} {path} {baseline}
→ 验证新目录 HEAD/分支
→ 迁移 active + create event
扩展不可变 ToolContext(taskId/claimToken/worktreeName/executionScope)。每次工具调用重新执行 ToolContextProvider.resolve()(在 schema 校验后、Hook 与权限前),Hook 看到的就是最终执行上下文;解析失败报成对的 tool_context_error,handler 零调用。executionScope 是每回合新建的空冻结对象,用 WeakMap 映射到 claim token,生命周期正好一轮;不用 process.chdir()。
ToolContext {
workspace, identity, idempotencyKey?,
taskId?, claimToken?, worktreeName?, executionScope?,
}
同一 assistant 回复:
call1 claim_task(A) → scope 绑定 claim token
call2 write_file(...) → 重新解析已得 A 的 Worktree 路径
依次证明:Task completed;binding 为 active/kept/needs_review;受管路径是 Git 登记的 root;共享 common dir;HEAD 仍是 wt/{name};git status 空(非零退出与空串区别对待,Git 报错不泄露 stderr);branch tip 与 integration ref 可解析;merge-base --is-ancestor 成功。全部成立才 detach + branch -d + worktree remove(不用 -D/--force);任一条不过转 needs_review 并带 review_reason,已是 kept/needs_review 的不重复迁移。
完成 proof 后才:
git switch --detach <tip-sha>
git branch -d wt/{name}
git worktree remove <managed-path>
不使用 -D / --force;失败转入 needs_review
task_id/name/integration_ref;reserved → active,Task 仍 pending。
只接受 active binding;claimNext 只选 active binding 的 ready 任务。
resolve ToolContext → PreToolUse → 权限 → handler(写进 Worktree)。
keep 显式保留(active→kept);remove 安全证明后清理。