#3319 — ork shipped the worktree idiom its own docs call broken
Filed as one line in session-registrar. It was fourteen recommendation
sites across seven files, and the two worst reach the model rather than the operator.
The mechanism
git worktree add ../myrepo-task -b feat/x origin/main ← succeeds cd ../myrepo-task ← reports success Shell cwd was reset to /path/to/myrepo ← silent ...every later command now runs in the PRIMARY tree. A sibling path sits OUTSIDE the session's project directory, and the harness bounces any cd that leaves it. Nothing errors. Nothing warns.
This is the failure behind platform#9870: work was committed onto another
agent's branch, with that agent's uncommitted files sitting in the tree. The repo has
documented the idiom as broken since 2026-08-06 while still shipping it in seven files.
Before / after
BEFORE
git worktree add ../myrepo-task \
-b feat/x origin/main
cd ../myrepo-task
# sibling → outside the project dir
# cd is silently reverted
AFTER
WT=$(~/.claude/hooks/worktree-new.sh \
task feat/x) && cd "$WT"
pwd # confirm — the reset is silent
# .worktrees/task → inside the repo
# helper refuses an existing path
Every site, and who it taught
| File | Reaches | What it said |
|---|---|---|
lib/tool-invocation-rules.ts:95 |
MODEL | Fired on Agent(isolation:'worktree') and told the model to pre-create a
sibling, then prefix the prompt FIRST: cd <path>. It fires exactly when
a session is about to spawn parallel work. |
skills/implement/references/worktree-workflow.md |
MODEL | 7 occurrences, including cd ../myapp-auth in three separate flows. |
skills/implement/references/team-worktree-setup.md |
MODEL | 3 worktree-adds plus a directory diagram drawn around the sibling layout. |
skills/implement/references/agent-teams-phases.md |
MODEL | Told the lead to hand each teammate a sibling path over SendMessage. |
skills/implement/references/agent-teams-full-stack.md |
MODEL | 3 worktree-adds plus the per-teammate assignment table. |
lifecycle/session-registrar.ts:246 |
OPERATOR | The peer-collision warning — printed at the moment a session learns a peer exists, i.e. precisely when someone is about to act on it. |
lifecycle/sweep-stale-worktrees.ts:10 |
HISTORY | Kept. Describes the #1884 symptom this sweeper cleans up after. Now annotated "do not copy". Rewriting it would misrepresent the history. |
The test asserted the bug
BEFORE
expect(warning)
.toContain('git worktree add')
Locked the defect in as a contract. It passed, always, and could never have caught this.
AFTER
expect(warning)
.toContain('worktree-new.sh')
expect(warning)
.not.toMatch(/cd \.\.\//)
expect(warning)
.not.toMatch(/git worktree add \.\.\//)
Both negatives fail against origin/main, which emits exactly those strings.
Verified
✓ origin/main emits `git worktree add ../${repoName}-task` and `cd ../${repoName}-task` ✓ HEAD emits neither — only the helper ✓ session-registrar tests 9 passed / 9 ✓ npm run typecheck rc=0 ✓ npm run build rc=0 ✓ residual sweep only the 2 annotated historical lines remain
While this change was being written, the un-rebuilt rule fired on a live
Agent(isolation:'worktree') call and printed the sibling idiom verbatim —
the bug demonstrating itself at the exact moment the issue says it is most expensive.