Development record
Several agents sharing ONE git worktree silently invalidated a verification result and came close to losing committed work. Observed repeatedly during the 2026-08-11 install-test round, in a repo that is about to run more agents, not fewer.
Several agents sharing ONE git worktree silently invalidated a verification result and came close to losing committed work. Observed repeatedly during the 2026-08-11 install-test round, in a repo that is about to run more agents, not fewer.
What happened, in one session: the working tree was switched under an in-flight agent three times (to main, to a second agent's branch, and to a dependabot branch); a "git rebase origin/main" silently rebased MAIN because the branch had changed underneath between the checkout and the rebase; a "git checkout" failed with "error: could not detach HEAD" as a transient race against another agent's git process, succeeding on retry with no lock present; and a "make preflight" running in the background spanned two branch switches, so its exit 0 described no tree in particular.
The last one is the dangerous member of the set. A long verification (preflight is several minutes here) that reports clean while the tree changes beneath it is a FALSE GREEN of the kind the loud-staging principle exists to refuse — and unlike a red result, nothing about it invites a second look. A change verified that way could merge on the strength of a run that never saw it. In this round the result was noticed and discarded, and CI was used as the authority instead; that was luck and vigilance, not a property of the setup.
The near-miss on work: two commits existed only on a local branch while another agent was pruning branches and worktrees. Pushing early is what protected them, which is a habit rather than a guarantee.
Directions, none adopted. Give each agent its own git worktree (git worktree add), so branch state is per-agent and the whole class disappears — the harness already supports worktree isolation for subagents. Or, if a shared tree is kept, treat any verification longer than a moment as untrustworthy and defer to CI, and have agents assert the expected branch immediately before and after a long-running gate rather than assuming it held. Worth settling before the next multi-agent round rather than after the first bad merge.
Deferral 2026-09-29
Deferred past v0.11.1: Carried by the planned itd-148, rewritten on 2026-09-29 to the product thinker's rulings and now blocked on the store draft itd-2609091014076309, which owns adding, listing and clearing away worktrees; the per-agent worktree direction this record proposed is the convention in AGENTS.md meanwhile. Owed: the store draft's planning interview with the product thinker, before which nothing from the store draft is built (ruling Q4, 2026-09-29); itd-148 waits on the store's verbs through its blocked_by (ruling Q2).
Deferral lapsed 2026-10-23
The deferral past v0.11.1 lapsed long ago and is withdrawn, on the old-majors triage of 2026-10-23. It stays open until itd-148 ships. The reason it carried stays in the body above.
What it waits on
It is carried by itd-148, which waits on the planned store intent itd-2609091014076309 for the verbs that add, list and clear away worktrees.
Frontmatter
| id | iss-213 |
|---|---|
| type | issue |
| lifecycle | open |
| severity | major |
.abcd/work/issues/open/iss-213-several-agents-sharing-one-git-worktree.md
open on GitHub ↗ · commit history ↗
References1
- itd-148Every change starts in its own worktree in abcd's store: the primary checkout is a read-only surface, and abcd blocks mutations there for every session but a declared coordinatorrelated
mentions10
- iss-2608230847432285Per-agent worktrees do not isolate a session whose shell cwd reverts to the shared checkout, so the mitigation iss-213 recommended has a hole. This refines iss-213, which recorded several agents sharing one git worktree silently invalidating a verification result, and whose recommended direction was to give each agent its own worktree so the whole class disappears. That direction is now in force via the AGENTS.md Concurrent sessions section, and on 2026-08-23 three concurrent sessions demonstrated it does not hold. A session's shell cwd can be silently reset from its worktree back to the primary working directory, and the notice arrives on the tool result AFTER the command that caused it, so the contamination lands on the NEXT command. It fails toward the shared tree, which is the wrong direction: two sessions wrote into the main checkout while believing they were in their own worktree. One appended to two Go test files, the other filed a capture and edited three record files, and both discovered it only when a third session read git status in the main checkout and asked who owned the diffs. Nobody lost work, because the convention that a diff you did not make is a peer's work held and the owners were asked rather than the files committed. The isolation property did not hold; the coordination convention compensated for it. Two details generalise beyond this instance. First, the failure is silent in BOTH directions: nothing warns the writer, and nothing would have warned a committer using git add -A, because the misplaced files are indistinguishable from that session's own in git status. What stood between this and a bad commit was one session committing with explicit paths and another happening to run git status for an unrelated reason. Detection was not mechanical in any of the three cases. Second, this is the write-side twin of iss-213 rather than a restatement of it: iss-213's dangerous member was a verification result that described no tree in particular, on the read side, while this is work landing in a tree whose HEAD another session is preparing to move. Same root cause, that the checkout is the unit of isolation and nothing enforces which checkout a session is in, on opposite sides of the read/write boundary. The mechanical mitigation is to address the tree explicitly on every git invocation, git -C <abs-path>, and to use absolute paths for file writes, rather than relying on a persisted cd: a cd is a session-global mutation with no scope and no expiry, which is the wrong shape for the mechanism that is supposed to provide isolation. AGENTS.md states that the checkout is the unit of isolation without saying what makes a session stay in its checkout, and that gap is what let three sessions make the same mistake in one day. Decide the routing: an AGENTS.md line under Concurrent sessions is the cheapest rung and matches how the sequential-id caveat was handled, while the durable form is whatever makes a session's tree unambiguous rather than remembered.
- iss-2608230847432287the adversarial-review floor assumes below-the-line artefacts are covered by their gates, and today they were not
- iss-2608230943533581itd-33's revisit triggers have fired and the coordination question owes a SOTA sweep that no record currently asks for. On 2026-08-23 several sessions ran in parallel in this repo and spent real effort coordinating rather than working: three of them landed writes in the wrong checkout when a shell cwd silently reverted from a per-agent worktree to the shared tree, and what stood between that and a bad commit was the AGENTS.md convention that a diff you did not make is a peer's work, not any mechanical property of the setup. That is itd-33's fifth revisit trigger — two consecutive successful multi-agent runs, after which the absence of coordination becomes the next bottleneck — and the intent asks in terms for exactly this texture to be recorded in the ledger so its design proceeds against real evidence rather than guesses. The accumulated evidence is now iss-213 (2026-08-11, a shared worktree and a false-green preflight spanning branch switches), iss-2608220750029992 (two sessions in one checkout, a branch switch unstaging a peer's index), iss-2608220750029993 (the session-presence lease, the armed-detector rung of the AGENTS.md conventions), iss-2608230847432285 (per-agent worktrees do not isolate a session whose cwd reverts), and the parallel-mint collisions iss-2608220150157512 and iss-2608221126066632. The gap this capture exists to close is the research one. .abcd/development/research/notes/ holds sixteen SOTA notes and not one covers multi-agent orchestration or coordination; itd-15 audits agent prompts against their research baselines, which is a different question. itd-33's own narrowing pass dropped LangGraph, CrewAI and AutoGen from its References when it cut file-level claims and substrate selection — right for that scope, but it leaves no record anywhere that a state-of-the-art sweep is owed on the topic at all, so without this entry the ask exists only in one session's transcript. The sweep should run under the protocol in .abcd/development/research/notes/2026-08-22-sota-research-protocol.md and cover at minimum what coordination substrates the field actually uses for same-machine multi-agent work on one repository, whether a claim-and-yield contract of itd-33's shape is state of the art or a local invention, how other systems make a session's tree unambiguous rather than remembered, and what the evidence says about coordination overhead against parallel throughput — the cost today's sessions paid in full. Promoting itd-33 out of drafts/ is a maintainer decision and is deliberately not taken here.
- iss-2608261331317889TestPayloadTreeImplementationsResolveIdentically failed transiently during a pre-push preflight with 'the payload carries 109 rejected file(s)', then passed in isolation minutes later with an identical two-markdown-file diff and a clean tree. Between the two runs a peer session created .claude/worktrees/pr513-conflicts in the shared checkout, so the plausible mechanism is the payload walk sweeping a sibling worktree mid-population — the iss-213 class (a peer's activity silently invalidating a verification result), now reaching the payload scan through the preflight gate. Not reproduced deterministically; captured as a sighting so the flake has a marker if it recurs.
- iss-2610111926302443TestWorktreeStoreRuleNamesTheIntentsActualState (internal/core/lint/conventionsfile_test.go) checks for stale draft wording per blank-line paragraph, and the references list in .abcd/development/brief/04-surfaces/34-build.md is one paragraph naming six intents, so a later '(a draft)' beside a different intent in that list would fail the test naming itd-2609091014076309 falsely.
- iss-2610111926302792Present-state planning prose still calls itd-2609091014076309 'the store draft' although the intent is in planned/: itd-148 (lines 64 and 188), spc-42 (lines 27 and 112) and iss-213 (line 11). The drift fix for iss-2610090744073409 corrected the CONCURRENCY rule, the build brief page and lane.go, and left these planning records as out of its remedy's scope; its ruthless review recorded them.
- iss-2610112237488013Three planning records still treat the worktree-store intent itd-2609091014076309's planning interview as owed, though it was held on 2026-09-30 (its record lists the rulings, and its Open Questions read 'None open'): spc-42's '## Blocked on' lists that interview as the blocker; iss-213's deferral_reason says 'Owed: the store draft's planning interview'; itd-148's Acceptance Criteria note and Open Questions defer to after it; and spc-42's Scope item 2 calls the check verb's name one of the store intent's open questions, though that intent's Decision 5 settled it as a sub-verb of ahoy. Found by the lane for iss-2610111926302792.
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projects
- itd-2610161621364075The agents abcd launches on its own work inside a sandbox the operating system enforces
- spc-42every-change-starts-in-its-own-worktree-the-primary-checkout