Skip to content

Chapter 9 · Worktree Isolation and Parallel Delivery ​

Chapter goals: Understand why FirstMate坚持 "one clean git worktree per task" isolation model, master the treehouse worktree pool, base-freshness boundaries, and the fail-closed teardown lifecycle.

9.1 Why Worktree Isolation Is Needed ​

Imagine the無隔离 scenario: you have the firstmate dispatch three crewmates to改 the same repo simultaneously — fixing the login bug, adding dark mode, refactoring utility functions. If they all work directly in your project directory, what happens?

text
No isolation parallel:
projects/myapp/            ← all crewmates share the同一 work area
├── src/login.ts           Crew A is modifying (半成品)
├── src/theme.css          Crew B is also改ing here (互相踩踏)
├── src/utils.ts           Crew C half-refactors; A's tests can't run
└── ???                    Who改 what? git diff is a mess

Uncommitted changes混在一起,无法拆分、无法回滚,甚至无法编译.The收益 of parallel becomes the事故 of parallel instantly.

Git already有 the answer: git worktree. It allows the same repo to checkout multiple work areas on磁盘 simultaneously, each with独立 files and an独立 HEAD, while sharing the同一 .git object store —既隔离又省空间:

bash
# Native git worktree demo: two独立 work areas from the same repo
cd myapp                          # Main checkout stays on the main branch
git worktree add ../myapp-fix -b fix/login-bug   # New worktree + new branch
git worktree add ../myapp-dark -b feat/dark-mode # One more
git worktree list
# /Users/captain/code/myapp        abc1234 [main]
# /Users/caoxueling/code/myapp-fix    def5678 [fix/login-bug]
# /Users/captain/code/myapp-dark  9abc123 [feat/dark-mode]

cd ../myapp-fix    # Mess around here freely; completely不影响 other work areas

FirstMate institutionalizes this mechanism: crewmates never故意 touch your project's primary checkout; each task completes in its own干净 worktree**. This is what "Worktrees, not branches in your checkout" means in the架构文档.

9.2 Treehouse: The Worktree Pool ​

Manually git worktree add per task is太繁琐, and requires handling cleanup, reuse, freshness, etc. FirstMate配套 uses treehouse to集中管理一批干净的 task worktree:

text
Task-to-worktree mapping:

projects/myapp/            ← your project clone (firstmate read-only; crewmates don't工作 here)
     │  fm-spawn.sh
     ├── treehouse worktree #1 ──→ fm-task1 (ship: fix login bug)
     ├── treehouse worktree #2 ──→ fm-task2 (scout: investigate性能 regression)
     └── treehouse worktree #3 ──→ fm-task3 (ship: dark mode)

Worktree providers per backend:
tmux / herdr / zellij / cmux  →  treehouse unified供给
orca                          →  Orca自建 worktree (records orca_worktree_id=,
                                  removed via orca worktree rm after常规 teardown checks)

Three要点:

  1. Pooled supply: the tmux, herdr, zellij, cmux four session backends all get worktrees from treehouse; only the experimental Orca backend manages worktree生命周期 itself.
  2. One task, one tree: each crewmate session binds an专属 worktree; mutuallyinvisible, mutually unpolluted.
  3. Return after use: after the task ends, the teardown流程 returns the worktree to the pool for reuse.

9.3 Spawn Gates: Two Checks in fm-spawn.sh ​

Isolation is not靠自觉; it is强制 by scripts. bin/fm-spawn.sh has两道硬性检查 before dispatching any ship or scout task.

Gate 1:真实且独立的 worktree root. Unless the resolved task path is a真实 git worktree root and distinct from the project primary checkout,启动 is refused.

Gate 2: base-freshness boundary. Each全新 ship/scout task's clean worktree must first align to origin's解析出的 default branch latest fetched tip; any unsafe or unverifiable baseline阻止s spawn:

text
base-freshness flow (handled by fm-spawn.sh):

1. fetch origin,解析 the default branch (origin/HEAD)
2. align the task worktree's base to that fetched tip
3. align succeeds       → worker allowed to start
4. unsafe/unverifiable → spawn stops; never开工 with a sick baseline

Why so strict? An outdated baseline means the crewmate develops on旧代码; the PR opens with一堆无谓冲突甚至逻辑错误. "Freshen first, then开工" strangles这类事故 at the起点. The precise refusal机制 is owned by the script header注释; regressioncoverage is in tests/fm-spawn-pool-base-freshen.test.sh.

9.4 Worktree Tangle: The唯一健康判据 Is Branch State ​

One特殊值得单独讲: the firstmate repo itself canalso be dispatched work (the fleet can调度 crewmates to维护 firstmate itself). In this case, FM_ROOT (firstmate's own运营 checkout) and the crewmate's临时 worktree are both linked worktrees of the same repo — "whether linked" no longer distinguishes健康 from不健康.

The架构文档's判别标准 is branch state:

text
Healthy topology:
FM_ROOT (primary checkout)              → stays on the default branch        ✅ healthy
linked worktree / secondmate home       → in detached HEAD                   ✅ healthy

The唯一病态 (worktree tangle):
FM_ROOT                                 → checked out a named non-default branch ❌ tangle

Once a tangle occurs,两处报警:

  • bin/fm-session-start.sh reports a TANGLE: line via bootstrap at session startup;
  • bin/fm-guard.sh prints the修复命令 at the next "changeable fleet action".

9.5 Fail-Closed Teardown: Never Lose Unlanded Work ​

When a task ends, the teardown流程 must decide: can this worktree be销毁? The answer follows a hard原则:

text
Teardown 判据:

1. 已提交的改动 (landed)   → 安全销毁 worktree ✅
2. 未提交的改动 (unlanded) → 拒绝销毁, up to the captain to decide ⚠️
3. scout worktree          → 报告存在且 decision inventory 完成后才可丢弃

This is Hard Rule 3 in action: never destroy unlanded work without captain authorization. The bin/fm-teardown.sh script implements the landed-work test;绕过拒绝或 --force 都需要船长明确授权.

9.6 Chapter Summary ​

  • Worktree isolation prevents并行事故: each crewmate gets an专属 clean worktree via treehouse;
  • Spawn has两道硬门禁:真实独立的 worktree root + base-freshness对齐 origin tip;
  • Orca is the only backend that自建 worktrees; others use treehouse统一供给;
  • Worktree tangle is detected by分支状态 (FM_ROOT on a named非默认 branch =病态);
  • Teardown is fail-closed: unlanded work is拒绝销毁 unless the captain explicitly authorizes.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. Why does FirstMate insist on one clean git worktree per task?

2. What is the base-freshness gate in fm-spawn.sh?

3. What triggers a "worktree tangle" alert?

4. When can a scout worktree be discarded?

🛠️ Hands-On Exercises ​

  1. Run git worktree list in a test repo; create two worktrees; verify they are独立 and互不干扰; then remove one and observe thepool state.
  2. Simulate a base-freshness failure: create a worktree落后于 origin/main and attempt to spawn; record the拒绝行为. Then fetch to latest and重试;对比 the metadata.
  3. Trigger a worktree tangle scenario (checkout a named branch in FM_ROOT); observe the TANGLE: line in the session startup digest and the修复命令 from fm-guard.sh.

Isolation understood. Next, Project Modes and Merge Permissions.