Development record
Per-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.
Per-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.
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: worktrees live in the store under the home folder, the store draft itd-2609091014076309 owns adding, listing and clearing them away, and a session that declares itself the coordinator is exempt from the block on writes in the primary checkout. itd-148 is blocked on that draft. 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.
Frontmatter
| id | iss-2608230847432285 |
|---|---|
| type | issue |
| lifecycle | open |
| severity | major |
.abcd/work/issues/open/iss-2608230847432285-per-agent-worktrees-do-not-isolate-a.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
mentions8
- iss-213Several 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.
- 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-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.
- iss-2610240859590333A session wrote records into the main checkout's working tree on main while another live session (abcd-0d) was working in the same checkout, because nothing enforces the rule that a concurrent session works in its own worktree. On 2026-10-24 this session ran capture, intent, decide --adr and go generate from the main checkout: an issue record, an intent draft, an ADR and two regenerated index regions landed in the shared tree, the regenerated indexes folding in a peer's untracked draft. Nothing refused or warned. capture, intent and decide write into whichever checkout they run in; the guard judges shell commands and questions, not where records are written; and the CONCURRENCY rules domain, which carries the rule, recalls only on prompts about worktrees, peers or sessions, so a prompt saying 'file the decision record' never injected it. The agent also skipped the required scan (session listing and abcd peers) before mutating. The rule held only as prose.
- 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