Development record
Every 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 coordinator
Typed links: blocked_by itd-2609091014076309 (the store under the home folder, which owns adding, listing and clearing away worktrees; this intent uses those verbs, so it waits on that intent); related_adrs adr-2609091248200336 (the rule the store enacts). This record was rewritten on 2026-09-29 to the product thinker's rulings (see ## Decisions); the rewrite reverses the scope its 2026-08-26 planning interview gave it, a worktree verb family and a sweep of its own, with worktrees placed inside the primary checkout.
Press Release
abcd turns the primary checkout into a read-only surface: every change — a one-line docs fix included, peers present or not — begins in its own worktree in abcd's store under the home folder, and abcd enforces the boundary mechanically. A session gets its worktree from the store (itd-2609091014076309), which places it under
~/.abcd.noindex/worktrees/<root-sha>/and never beside or inside the user's own project; abcd records the entry where every peer session sees it on its next prompt, and seeds the worktree with the protections the primary checkout has — the private name-guard layer included, pre-populated to a floor of four categories (home/user paths, machine hostnames, personal email, real surname), each value held on the machine and never committed. A host-hook backed by the binary refuses file writes and git mutations attempted in the primary checkout, so a session whose working directory silently reverts to the shared tree is stopped at its first recognisable write instead of contaminating a tree another session is about to move. One session may declare itself the coordinator, the session that lands and records the others' work, and only that session is exempt from the block. Listing the worktrees and clearing away the ones whose work is done are the store's verbs, so there is one place to ask what exists and one way to reclaim it."I had two sessions going and asked one for a two-line docs fix, and it just did it — in its own worktree, kept with abcd's other machine state rather than beside my projects, visible to the other session, PR up," said Kira, an open-source project lead running concurrent agents. "When the other session's shell slipped back into my main checkout, abcd stopped its first edit and named the worktree route instead. The one session I told to coordinate could still land work in the main checkout; nobody else could."
Why This Matters
The checkout-is-the-unit-of-isolation convention has been carried by vigilance, and the ledger records vigilance failing safe rather than the setup holding:
- iss-213: several agents in ONE worktree produced a false-green preflight
spanning two branch switches, and a
git rebasesilently rebased main. - iss-2608230847432285 (major): per-agent worktrees did not isolate sessions whose shell cwd silently reverted to the shared checkout. Two sessions wrote into the primary tree believing they were in their worktrees, and only the diff-you-did-not-make convention prevented a bad commit. That record asks in terms for "whatever makes a session's tree unambiguous rather than remembered". The mutation block in the primary checkout is that durable form, aimed at the exact failure direction observed.
- The lint gates read the whole working tree, so any foreign work-in-progress
in a shared checkout fails
make preflightin both directions; a per-change worktree makes a gate's verdict describe the change it gates. - itd-107 leaves open (its orchestration caveats) whether independent peer sessions are kept apart by policy or by per-session worktrees; this intent supplies that answer.
Making the primary checkout read-only also gives it a positive role: it is the always-current surface of the repository's state — status renders, rules inspection, browsing — that is never mid-anything.
Per-change worktree cost is negligible in this ecosystem: worktrees share the object store, and Go's build cache is user-global.
Where the worktree lives is settled elsewhere: a tool never creates directories in space the user did not hand it (adr-2609091248200336), so a per-change worktree goes in the machine-scoped store the store intent (itd-2609091014076309) describes, keyed on the repository's root commit, and that intent owns the verbs that add, list and clear away worktrees. This intent is what makes the store the only route: the block in the primary checkout, the seeding of the protections, and the peer visibility.
What's In Scope
- Worktrees come from the store. This intent adds no verb that creates, lists or removes a worktree: the store intent (itd-2609091014076309) owns add, list and clean-up, and this intent calls them. Every refusal of the block names the store's add verb as the route, and nothing this intent writes lands beside or inside the primary checkout.
- The mutation block: a host-hook (thin caller; the check lives in the binary) that refuses file writes and git mutations in the primary checkout of an abcd-managed repo, naming the worktree route instead. The check is git-aware (resolved via the tree's git common directory, never a path prefix: which checkout a tree is comes from git, wherever it sits) and honest about its rung: hook-level interception of the host's file-edit and shell tools is a mitigation that catches recognisable writes, not a filesystem guarantee. A git-level pre-commit backstop in the primary checkout is the second layer, refusing commits there for humans and non-hooked tools, subject to the same allow-set.
- The declared coordinator is exempt. A session that declares itself the coordinator of the sessions working in the repository is exempt from the block in the primary checkout, at both layers; every other session is blocked. The exemption is never inferred from what a session does: it exists only by the session's own declaration. Because it lifts a write block, it is a trust path, and how the declaration is made and what stops a second session from making it are the spec's, reviewed as security work.
- The read-only surface's allow-set, stated explicitly: writes to the
local tier (
.abcd/.work.local/) and other gitignored or untracked paths (build output included), fetch and fast-forward of the default branch (what keeps the surface current), andgit worktreeadministration are permitted in the primary checkout; tracked-file writes and history-moving operations are what the block refuses. The ledger write ofabcd capturejoins the allow-set as a narrow carve-out (a new timestamp-named file under the issue ledger only, so concurrent captures cannot collide), paired with an adoption path: a capture written in the primary checkout is uncommitted by construction, and the next worktree abcd seeds adopts orphan captures into its change so they reach the default branch rather than sitting untracked. - Peer visibility as a mechanical duty (the convention layer): worktree entry and exit and record-id mints are recorded such that every peer session in the repository sees them at its next hook fire (the record-then-inject shape the rules loader already uses; delivery is at-next-prompt, not instantaneous). The coordination mechanism — typed claims, take or yield or escalate — remains itd-33's; this intent makes today's AGENTS.md announce convention mechanical rather than remembered, without adding the delivery channel itd-33 deliberately cut.
- Protection seeding on detection: a hook fire that finds itself in a worktree of an abcd-managed repo whose local tier lacks the name-guard layer seeds the pointer to the primary checkout's store, so worktrees the host created without abcd get the protection too. abcd-managed repos pre-populate the private banlist to the four-category floor above, values gathered by one-time setup prompt or from the user-level home, never derived silently and never committed.
- Scaffolded to all abcd-managed repos via the prepare and ahoy path.
What's Out of Scope
- Adding, listing and clearing away worktrees: the store intent (itd-2609091014076309) owns all three. The two refinements this intent's 2026-08-26 interview ruled for its own sweep — a merge proven by the forge's recorded pull-request state or by patch-equivalence where squash and rebase merges leave no ancestry, working without a forge; and an unmerged worktree inactive for 14 days surfaced with a dossier (dirty state first) and removed only on per-item confirmation — are carried to that intent's planning interview as input, not built here.
- Post-merge residue mechanics (remote PR branch, local branch, tracking ref): itd-118 owns them, and the store's clean-up is what its post-merge tidy calls.
- The coordination layer itself (claims, yield, escalation): that is itd-33, whose revisit triggers have fired and which owes a SOTA sweep first (iss-2608230943533581). This intent adds no delivery channel and no agent-to-agent negotiation.
- Session-presence leases for two sessions in ONE checkout (iss-2608220750029993): narrowed but not closed by this intent; it stays open.
- Met elsewhere since the 2026-08-26 interview, so no longer this intent's: the guard layer inside a linked worktree (iss-370, resolved by itd-150); the AGENTS.md concurrency rule restated by blast radius (iss-2608230957104179); push-time gates reading the committed tree through the preflight receipt (iss-2608210738378295); and the timestamp id mint for every record family (adr-45, iss-2608210737260468).
Scope Conditions
None stated.
Acceptance Criteria
Rewritten on 2026-09-29 to the product thinker's rulings (
## Decisions): the sweep's two criteria moved to the store intent, and the coordinator's criterion was added. The criteria are walked again after the store intent's planning interview, before anything is built.
- Given a session in the primary checkout of an abcd-managed repo that has not declared itself the coordinator, when it attempts a tracked-file write or a history-moving git operation through a hooked surface, then the block refuses with a message naming the store's add verb as the route, and read-only operations and allow-set writes are untouched.
- Given a session that has declared itself the coordinator, when it writes or commits in the primary checkout, then neither the hook nor the pre-commit backstop refuses it; and given a second session that has not declared itself, when it does the same, then it is refused.
- Given the store adds a worktree, or a hook fire detects a worktree without the guard layer, when the session works there, then the private name-guard layer is active in that worktree, pre-populated to at least the four floor categories with values that appear in no committed file, and the entry is recorded such that every live peer session sees it at its next hook fire.
- Given a session refused by the block, when it takes the route the
refusal names, then its worktree is under
~/.abcd.noindex/worktrees/<root-sha>/and neither the primary checkout nor its parent directory holds anything it did not hold before. - Given a record-id mint from any worktree while a peer session is live, when the mint runs, then the family and checkout are recorded for peer visibility at next hook fire.
- Given a repo where no worktree exists and no peer runs, when a read-only verb runs in the primary checkout, then nothing about its behaviour or cost has changed, and no bare invocation acquires a write as a side effect of the block or the seeding.
Decisions
Ruled by the product thinker on 2026-09-29 (interview by orchestrator abcd-23 of autonomous run A; recorded in dcn-2609290000000007):
- The store under the home folder wins (adr-2609091248200336): a per-change worktree lives in the store, never inside or beside the checkout; this record is rewritten to match.
- The store intent owns add, list and clean-up (itd-2609091014076309); this intent uses them and builds no worktree verb of its own.
- A session that declares itself the coordinator is exempt from the write block in the primary checkout; every other session is blocked.
- The store intent is planned first: nothing from the store intent, the
merged-worktree clean-up included, is built before its planning
interview. This intent's own wait is not part of the ruling: it follows
from decision 2, because this intent uses the store's verbs, and is
carried by its
blocked_byon the store intent. - The mint-visibility criterion stays, as peer awareness (ruled 2026-09-30 at the store intent's planning interview): timestamp ids make a clash impossible (adr-45), and the criterion is kept for what a peer learns, not for collision safety.
SOTA
Surveyed on 2026-10-23 for the enforcement gap only (the store sibling carries its own prior art); sources, evidence tiers and the local fit risks are in the security-isolation SOTA note.
- The host now enforces worktree isolation itself with four checks, for a session already in a worktree: edits targeting the main checkout, a command whose working directory resolves there or cannot be verified, git redirected by
-C,--git-dir,GIT_DIR,GIT_WORK_TREEor acd, and any command text it cannot parse ("You can't turn this check off"). The checks run "while a session is isolated in a worktree" and protect the main checkout from that session; a session started in the primary checkout, this intent's case, gets none of them, so they cannot replace the native block there (Claude Code worktrees). - It states the same limit this intent states: "None of them tracks which files a shell command writes, so a command that writes into the main checkout without running git there, such as
cpor a shell redirect, isn't refused" (same page). - The host's worktrees live inside the checkout (
.claude/worktrees/<name>/), against adr-2609091248200336;${CLAUDE_PROJECT_DIR}stays at the main checkout in hooks while the hook'scwdfollows the worktree (same page). - A
PreToolUsehook can refuse with a reason, and "staying silent doesn't approve it"; a hook that fails or times out lets the action proceed by default, andonFailure: "block"on a command or HTTP hook (host v2.1.295 or later) makes it block instead, the fail-closed setting for the native block's hook seam (Claude Code hooks). - The host itself writes into the main checkout from a worktree session: a standing approval ("Yes, and don't ask again") is saved to the main checkout's
.claude/settings.local.json, so it applies in every worktree and survives the worktree's removal (Claude Code worktrees). That write is not a tool call, so no hook sees it; the allow-set names it, or the record states it as a known exception. - The git backstop's reach is as drafted:
pre-commitandpre-merge-commit"can be bypassed with the--no-verifyoption" (githooks). - An OS-level immutable flag exists and is the wrong tool:
chflags uchgstops git's own fast-forward and the allow-set with it (chflags(1)). - No field precedent for a declared coordinator; the closest shape is a renewed lease with an expiry and a fencing token, from the 2026-10-17 coordination note.
Path 2: build the block natively, shaped to the host's four checks and stating what they miss, with the hook as the seam so a host check can replace a native one at a time; the coordinator's declaration as a lease file in the primary checkout's local tier (session, pid, start time), renewed while the session lives and expiring without it. The independent fit-challenge is still owed before the build.
Open Questions
- How does a session declare itself the coordinator, and what stops a second one? Decision 3 rules that the exemption exists; its mechanism (a flag, a mode, a local-tier file) and the refusal of a second declaration are the spec's, to be settled after the store intent's planning interview.
Audit Notes
Empty. Populated by intent-auditor when intent moves to shipped/.
References
- Resolved by shipping: iss-2608230847432285, iss-213. The three others this list once named (iss-370, iss-2608230957104179, iss-2608210738378295) were resolved by other changes (see Out of Scope).
- The store this intent is blocked by: itd-2609091014076309, and the rule it enacts, adr-2609091248200336.
- Adjacent intents: itd-118 (merged work leaves no residue: consumed), itd-33 (coordination mechanism: this intent carries only the record-then-inject visibility duty), itd-115 (merge without churn), itd-107 (dispatches subagents into per-worktree isolation and asks the independent-peers question this intent answers).
- Sequencing: adr-45 ruling 3 and iss-2608210737260468 (the timestamp mint, since landed), with the collision recurrence iss-2608221126066632 and the wontfix sibling iss-2608220150157512.
- Host prior art: the Claude Code harness's own worktree isolation (per-session worktrees inside the checkout, base-ref policy). This intent is the host-agnostic, abcd-owned form of that behaviour, with the worktree in the store rather than inside the checkout.
Frontmatter
| id | itd-148 |
|---|---|
| type | intent |
| lifecycle | planned |
| kind | standalone |
| severity | major |
.abcd/development/intents/planned/itd-148-every-change-starts-in-its-own-worktree.md
open on GitHub ↗ · commit history ↗
References3
- adr-2609091248200336A tool never creates directories in user-owned project space; the store's location binds now and its verbs bind when the store shipsrelated
- itd-118Merged work leaves no residue: abcd-managed repos delete a PR branch on merge, and abcd tidies the stale local branch, tracking ref, and worktreebuilds on
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsblocked by
Referenced by9
- 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.related
- 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.related
- iss-2610262044322326The worktree-block intent assigns typed claims to itd-33, but the shipped reservation intent delivered the claimrelated
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsrelated
- itd-2609091416295622A session sees the records its peers hold before it mints or fixes onerelated
- itd-2609221656373558Two sessions share one run, and the run measures which way of dividing the work is bestbuilt on by
- itd-2610161621364075The agents abcd launches on its own work inside a sandbox the operating system enforcesrelated
- itd-2610170634394993Headless agents in parallel coordinate through the shared remote, not conversationrelated
- spc-42every-change-starts-in-its-own-worktree-the-primary-checkoutimplemented by
mentions27
- adr-45Record ids are timestamp-numeric, capture-stable, and never allocated by looking at the maximum
- dcn-26092900000000072026-09-29 — The product thinker answered twenty-six owed rulings and the published-history question in one interview, asked one at a time by orchestrator abcd-23 of autonomous run A (recorded by lane recRulings for orchestrator abcd-cb). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, dated 2026-09-29, and are restated here because that file is not committed. Published history is left as it is, with no rewrite. The build loop's fidelity audit runs once, on the lane that closes the spec, over the whole delivery (AI). On the vendor denylist the product thinker answered, verbatim: "I think we need an allow list rather than trying to catch a deny list." The interviewer's reading of that answer, recorded as a reading and not as the product thinker's words, is that the per-provider allowlist is the control and the vendor denylist is not extended to chase spellings, with whether the bundled `anthropic/*` entry stays as a backstop left to the technical facilitator (AA(a)). Only a route the person set up on their own machine may use their paid key, and a repository's own route to it is refused, which replaces the route half of itd-2609081951381895 decision 8 (AA(b)). The live site setup, the API adapter and the decision adapter may each close on tests against a simulated service, with the live paid check recorded as owed to a person (iss-2609291925387011, iss-2609291925393913, iss-2609291925398978). itd-111's last criterion is met by an agent's timing check on macOS plus the Linux CI run, so the intent may be finished. Automated dependency updates are switched on, pushed with a personal or app token the person creates and stores as a repository secret (itd-2609221842494980; creating the token is the person's act, and the lane builds everything else and names the secret it expects). itd-6 adds a Go MCP module, proposed for the person's explicit sign-off before it is fetched; closing itd-6 on a fake server was not ruled in this interview. (A later answer the same day, H1b in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md`, dated 2026-09-29, rules that it is not: itd-6 is finished only after running once against the real RepoPrompt app, a check owed to a person.) For itd-148: the store under the home folder wins (adr-2609091248200336); the store draft itd-2609091014076309 owns add, list and clean-up and itd-148 uses them; a session that declares itself the coordinator is exempt from the write block in the primary checkout and every other session is blocked; and the store draft is planned first, with nothing from the store draft, the merged-worktree clean-up included, built before its planning interview (Q4). itd-148's own wait is not part of that ruling: it follows from Q2, because itd-148 uses the store's verbs, and is carried by the `blocked_by` below. itd-148 and spc-42 are rewritten to match in this change, and itd-148 is now `blocked_by` the store draft. A release retrospective is seeded from a release, the intents a tag shipped (AD); itd-24 and its spec are rewritten to the release in this change. An unpointed route is refused naming the one setting to add, as built in 35100512e, so AC11 of itd-2609170822093401 is complete (BR1). A missed target becomes `next`, whatever the following release is numbered (BS1). Spec pieces keep "step" and the lane stages are renamed, a breaking change to the JSON fields `step`, `performed` and `refusal.step` that resolves iss-2609291313276243 and corrects the glossary entry `core/step.md` (BU1), and the old command spellings are removed in that same breaking release (BT1). The text board shows Later as a count only while the site and `--json` keep the full list (BV1), and an intent in progress appears only under Now (BV2). A pause of zero is allowed (BW1); drain stays in the agents' help list until it runs end to end (BX1); a managed repository must hold the drain eligibility decision in its own record, and drain refuses there until it does (BX2); a capture without a remedy is refused (BX3), which tightens the one-line capture friction `commands/capture.md` promises, so the lane that builds it reconciles that page, the principle wording and every caller that files a capture; a run's pick reason keeps the shared `pursued:` kind with its marker (BZ1); and an intent whose blocker was superseded waits on the successor, transitively (BZ2). The five itd-48 follow-ups are planned as one intent, drafted as itd-2609291923559186 (BT2), and all warn rules share one shrink-only baseline file in which a new warning fails, drafted as itd-2609291924469783 (BT3); both drafts wait on their planning interviews. Each ruling that contradicts a shipped behaviour or another record is amended in the change that builds it, not here. itd-7's planning interview stays owed.
- dcn-26093000000000222026-09-30 — The worktree store is planned (itd-2609091014076309, spc-2609301811532881), after two adversarial reviews and a planning interview with the product thinker and technical facilitator, asked one at a time. Decomposition: file as is, with no new ADR or principle; the build loop's lane primitive moves into the store's package, so the intent `refines` itd-2609201916151817. Rulings: the verb is `abcd ahoy worktree add|list|prune`; "merged" is the forge's recorded pull-request state or patch-equivalence, and it works with no forge; an unmerged worktree quiet for 14 days (repo-configurable) is surfaced with a dossier and removed only when named (`--yes <name>`), never forced; a reclaimed worktree's local tier is moved, never deleted, into a new sibling store `~/.abcd/notes/<root-sha>/<timestamp>-<name>/`, redacted on write with a manifest; the plugin page carries `add` as a host-run step; the worktree directory is `0o700`; prune exits 0 when it reclaimed something, 1 when it reclaimed nothing, 2 on a refusal; a directory keyed on an abbreviated root commit is listed as "not a lane" and names the full-key lane; the board line keeps "can be cleared" as an estimate. The 21 acceptance criteria are the product thinker's. Grounds: "pursued: working copies keep piling up with nothing to list or clear them; wrong if, after it ships, copies still accumulate outside the store." Carried from itd-148's 2026-08-26 interview and confirmed here: the merge proof and the quiet sweep. Also ruled: itd-148 keeps its mint-visibility criterion as peer awareness (its Decision 5).
- iss-370Agent worktrees commit without the private name-guard: .abcd/.work.local/ is per-worktree, so every isolated-worktree agent commit runs with the banlist layer absent — loudly warned, per design, but the isolated-agent pattern now systematically bypasses a protection the main checkout has. Candidate remedies: the worktree-creation path seeds a pointer to the primary checkout's store, or the hook falls back to reading the primary worktree's local tier
- iss-2608210737260468The intent (itd) and spec (spc) families still mint via the legacy max+1 refs-union allocator; adr-45 ruling 3 schedules their adoption of the timestamp-numeric mint seam as configuration — a swap of the allocation call in the intent and spec stores onto the shared recordid seam, retiring their MaxAcrossRefs scans and mint warnings — after the captures family has run the scheme for a release cycle (itd-114 ac-6's Given clause). This is the tracker so the rollout's second family is not forgotten once that cycle completes
- iss-2608210738378295Local record gates validate the WORKING TREE, not the committed/pushed tree, so a partial commit passes them while the committed tree fails CI. Demonstrated live this session: git mv staged a rename (iss-370->377) but the follow-up sed edit to the frontmatter id was left unstaged; git commit captured only the rename, so the committed file had filename iss-377 with frontmatter iss-370 — a record_schema blocker. record-lint had passed at commit time because it reads the working tree (which held the sed edit), and the pre-push make preflight passes for the same reason (the unstaged edit is still present); only CI, checking out the commit, sees the divergence. Fix direction: run the push-time gate against the tree that will actually ship (e.g. a clean worktree of HEAD, or git stash --keep-index before linting), so a working-tree/index divergence cannot pass locally and fail CI. Sibling of iss-147 (guard-load reads guard.json from the working tree).
- iss-2608220150157512ADRs, intents and specs still mint sequential ids (adr-NNNN, itd-N, spc-N), so two parallel branches minting in the same family produce add/add collisions on the same id — the exact mechanism adr-45 removed for issue captures, whose timestamp-numeric ids produced zero conflicts across twelve same-day captures on 2026-08-22 while the sequential families carry the standing risk. adr-45 rollout note 3 already names the path: one allocator, per-family adoption as configuration. Extending timestamp minting to the remaining families closes the class
- iss-2608220750029993Session-presence detection for shared checkouts: each live session leases a marker (session id, intended branch, started-at) in the checkout, and the pre-commit gate warns when another live session's lease is present — the armed-detector rung of the AGENTS.md concurrent-session conventions, which are vigilance-only until this ships. Lease home needs thought: the local tier is per-worktree by design, and the hazard is precisely two sessions in ONE worktree, so the lease belongs to the checkout, not the branch.
- iss-2608221126066632Live recurrence, 2026-08-22: two concurrent sessions in two current checkouts each minted itd-144 and itd-145 in the same window — four records, two ids — resolved by hand-renumbering one side to itd-146/147. This is the second, undocumented path into the sequential-id collision recorded as iss-2608220150157512, which describes the stale-view path adr-45 already anticipated. Staleness was NOT the cause here: one session fast-forwarded 46 commits immediately before minting and still collided. The structural fact is that intents and specs mint max+1 (nextIntentID) while withIntentMintLock in internal/core/intent/create.go is advisory and scoped to a single checkout, so it cannot see a sibling worktree; two current checkouts therefore allocate the same id by construction. The durable fix is the timestamp mint adoption recorded as iss-2608210737260468. Recorded deliberately because capture has no add-evidence path and itd-87 (recurrence escalation) is unbuilt, so this evidence would otherwise exist only in two session transcripts.
- iss-2608221328552172abcd intent and abcd capture both swallow an unrecognised sub-verb as content and mint a record at exit 0, violating unrecognised-input-never-writes on the two highest-traffic mutating verbs. Verified on 45afe46 against a freshly built binary: 'abcd intent nosuchthing' prints 'created itd-148 (drafts)' and exits 0; 'abcd capture nosuchthing' prints 'captured iss-... (open)' and exits 0. Both records were durable files on disk, removed by hand afterwards. The principle at development/principles/unrecognized-input-never-writes.md states the rule -- a verb that mutates state fails closed, anything not exactly recognised is an error, never a fallback interpretation -- and cites this precise scenario as its founding evidence: a misspelled capture subcommand swallowed as capture text, filing an issue when the user asked to resolve one. The principle is therefore documented and unenforced, and the failure it was written about is still live on both verbs. The cause is structural rather than accidental: both verbs take free text as their canonical create path, so an unknown token is indistinguishable from intended content. That makes a bare token ambiguous by construction, which is the design question a fix must answer -- candidates include requiring quoting or an explicit create flag for the text path, refusing a single bare token that matches no sub-verb and resembles one, or accepting text only from stdin. A typo costs a spurious durable record, a burnt id under the max+1 intent allocator, and a record-lint index_drift blocker until the stray is noticed. Related: adr-45 on id allocation.
- 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-2608230957104179the scan-before-mutating rule enumerates four git operations and misses shared artefacts outside git
- iss-2609020721142452Worktrees for parallel lanes are created one directory above the repository (../abcd-wt-<lane>, ../abcd-f185, ../abcd-integration), which litters the parent directory with a dozen sibling checkouts named by convention only, leaves them behind when a session dies (21 spent worktrees, 1.4G, were removed by hand on 2026-09-01), and gives nothing a stable place to look for them. Assessment of where they should go: (1) inside the repository under .abcd/.work.local/worktrees/ keeps them with their owner and gitignored, but a worktree inside the main working tree is walked by every tree scan (the payload gate, name-guard, docs-lint), which already flakes during worktree creation (iss-2608261331317889) and would slow every gate; (2) under the user-level home, ~/.abcd/worktrees/<root-sha>/<branch-slug>/, keyed the way the history store already keys a repository by its root commit, keeps them out of every scan, survives a session, and gives an abcd verb a place to list, prune and reattach them; (3) the git default (anywhere) is the status quo. Option 2 fits the existing home layout and the one-canonical-primitive rule (the root-sha keying exists), and it makes the concurrent-sessions convention in AGENTS.md checkable: a session lists its peers' worktrees by reading one directory. It needs: a verb or documented one-liner (abcd worktree add <lane> / list / prune), the AGENTS.md convention updated, the lane brief updated, and a prune rule for worktrees whose branch is merged.
- iss-2609100509533147`abcd intent` creates its draft in the checkout it runs in, with no repository or worktree target, which bites when the record store is being edited across several worktrees at once.
- iss-2609170640135192A local branch whose pull request has merged is never pruned, so a checkout accumulates them until somebody sweeps by hand: this checkout held 57 on 2026-09-17, one per landed PR since early September. The sweep cannot be 'git branch --merged', because the repository allows squash and rebase merges and those leave no ancestry, so 20 of the 57 read as unmerged by ancestry and were provably merged only by patch-id or by the forge's PR state; and a branch checked out in a worktree survives the sweep until the worktree is removed. abcd knows the merge state (the resolution gates already read origin/main and the PR), so the install step or a fetch-time pass could list the merged branches and remove them on consent, never one with unmerged patches, never one a worktree holds, and never a name matching a backup pattern.
- iss-2609200830169721A managed repository is running the whole intent lifecycle through one sub-agent per record, and asks whether the pattern should become an abcd recipe. The shape, reported by the Gropius session gropiusllm-2b on 2026-09-20: a main session interviews the product thinker one decision at a time, reading the reviewer's recorded options off the draft rather than re-deriving them, records each answer as it is given, then fans out one Opus 5 sub-agent per intent or issue, each in its own worktree, which fills the draft from the answers, runs abcd intent plan, writes the spec, implements test-first, runs the security and ruthless reviewers as its own sub-agents, closes the spec in the landing pull request and arms auto-merge; record-only lanes edit exactly one record each and may not plan. The session named what abcd already gave it (quoted-text filing, capture provenance flags, intent ready --json as the gate every lane runs, the Review and Open Questions convention on a held draft) and what it lacked (recorded separately: the answer write path, the hold state, the append-lock on the decision log, the integration-branch landing, the lane worktree location). Whether abcd documents this as a recipe (a plugin page, a runbook in the brief, or a scaffolded lane brief) is the product thinker's to decide; recorded here so the decision has a record to rest on. Note that abcd's own record already plans the worktree half (itd-148) and asks the same session-per-lane question from the coordination side (itd-2609150819440345).
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- 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-33Multiple Agents Coordinate On Intent And Spec Work Without Duplicating Effort Or Producing Competing Artefacts
- itd-107Autonomous Routines Assemble From One Versioned Template
- itd-115A Ready PR Merges Without Ever Wedging BEHIND
- itd-150Agent worktrees commit without the private name-guard: .abcd/.work.local/ is per-worktree, so every isolated-worktree agent commit runs with the banlist layer absent — loudly warned, per design, but the isolated-agent pattern now systematically bypasses a protection the main checkout has. Candidate remedies: the worktree-creation path seeds a pointer to the primary checkout's store, or the hook falls back to reading the primary worktree's local tier
- itd-2610240850336695The person grants their sessions what they may do alone, until a time
- itd-2611031342000215The status line shows each role what it needs, in a table a repository can tune
- spc-2609202056480020a-session-sees-the-records-its-sibling-worktrees-hold-before