Development record
A session sees the records its peers hold before it mints or fixes one
Press Release
Before a session captures, fixes or files anything, it can see what every peer already holds. One read-only reader answers the question from two sources today, the sibling worktrees' disks and the local branches, and from the register later. It reaches a session three ways:
capture resolve, the record dispatcher andintent auditname the peer that holds a record when they cannot find it here, instead of answering not found; the status board carries one line whenever a peer holds something this tree does not; and one read-only command prints the whole picture on demand. It shows issues and intent drafts alike, skips peers whose branch is merged or whose worktree is gone, and says out loud when a peer's ledger is in a state it will not read. Nothing is written: no claim, no lease, no session key. The implement verb reads the same picture before it picks a record."I had two sessions running in sibling worktrees, and one of them was about to capture an issue the other had captured an hour earlier, unpushed," said Maya, an autonomous-development practitioner who runs several agent sessions against one record. "The file was sitting on the disk the whole time, two directories over. Now the resolve tells me who has it, before I have done anything."
Why This Matters
Every collision on record so far happened between sessions that could have read each other's files. On 2026-09-01 a peer session re-fixed two issues that a paused branch had already fixed and not pushed. On 2026-09-09 two sessions held worktrees off one checkout, nothing pushed: one nearly minted a record its peer had already captured, and one nearly created a worktree over a peer's. On 2026-09-18, in a managed repository, a lane's capture resolve answered not found for a record that existed one worktree over, an audit agent working from a stale worktree reported three shipped intents as existing nowhere, and lanes merged each other's branches to resolve records. All of it is in iss-2609020716570699 and its corroboration. In each case the record existed on the machine, and nothing rendered it; the convention in AGENTS.md that asks a session to scan for peers points at a surface abcd never renders.
The claim record this was split from proposed a machine-scoped lease, a claimed_by stamp, refusals in the write verbs and a pushed duplicate guard. Two adversarial reviews on 2026-09-09 (their application is the ruling dcn-2609090000000005 of that date) found the expensive parts unsound for a human session and found that the collisions on record needed none of it. The maintainer ruled a split into the listing (this record), the upstream-terminal refusal and the claim. On 2026-09-20 the product thinker settled the four records' shape (below): this listing is the read side, the claim the write side, the register where both live across machines, and the implement verb the consumer.
Decisions
Settled with the product thinker on 2026-09-20:
- Four records, linked. This listing (read), the claim
itd-2609091034175565(write), the registeritd-2609150819440345(where claims and holdings live, across accounts and across machines over a network such as a tailnet), and the implement verbitd-2609201916151817(claims, checks, implements or drops and picks the next). Each is planned on its own; this one first. - The primitive: both sources through one reader. The sibling worktrees' disks (sees uncommitted captures) and the local branches through the common git dir (sees a branch checked out nowhere), behind one reader the upstream-terminal refusal and, later, the register share.
- The home: the refusals, the board, and a standalone read command.
capture resolve,abcd <record-id>andintent auditname the peer holding a record they cannot find here; the board carries one line; one read-only command (working namepeers; the name is settled at build time) prints the whole picture. - Spent peers are skipped. A worktree whose directory is gone, or whose branch is merged into the default branch, is left out of the diff and named in a count.
- A peer whose ledger holds one id in two status folders is marked, not read, and the other peers render normally; the block names the id and the remedy.
- Issues and intent drafts are both listed, by the same filename rule.
- Relation to
itd-148/spc-42: this is a distinct read primitive that the worktree render consumes; it does not ship that render early. - The always-on provenance line on every ledger verb is its own record,
iss-2609202053570475.
What's In Scope
- One reader, two sources. Given this checkout, the reader enumerates the peers git names (
git worktree list --porcelain, each candidate confirmed from its own--git-common-dir; every local branch through the common dir) and, per peer, reads the ids under.abcd/work/issues/{open,resolved,wontfix}/and.abcd/development/intents/drafts/by filename, opening a record only for its title through the same guarded reader every record read uses. - The diff. Per live peer: Records open there and absent here; records open here and terminal there; drafts there and absent here. Each id with its title where the file is readable, the id alone where it is not.
- The not-found paths.
capture resolve,abcd <record-id>andintent audit, when the record is not in this tree and a peer holds it, refuse naming the peer's branch and path and the folder that holds it. - The board line. The count of live peers and the count of ids across the diff, present only when the diff is non-empty.
- The standalone command, text and
--json, home paths redacted on every stream. AGENTS.md's concurrent-sessions convention names the command as the scan-before-mutating step.
What's Out of Scope
- Any write: No claim, no lease, no stamp, no hook, no session key (the claim record's).
- Presence or liveness: A peer holding a record says the record exists, not that a session does.
- Peers beyond this checkout's common dir: A second clone, another account, another machine (the register's).
- A record in a stash or an unsaved buffer.
- A record already terminal on the default branch (the upstream-terminal refusal's).
- Judging that two differently worded records describe one observation (
itd-87's). - Creating, moving or reclaiming worktrees (the worktree store's and
itd-148's).
Mechanism
We expect a read-only view of what peers hold to stop the local collisions on record because each was a failure of visibility and not of will: The peer's record existed on the machine before the collision, and the verb that collided answered not found rather than naming it. It is falsified if a session that was shown a peer's holding, in a refusal, on the board or in the command's output, still minted a duplicate of it or re-fixed a record shown as terminal elsewhere; the render's own output and the two records' timestamp ids tell that case apart from a session that never looked. It is also falsified, differently, if the next collision on record comes from a peer this reader cannot see, a second clone or another machine, which is the register's case.
Scope Conditions
- Holds for the peers that share this checkout's common git dir: Its worktrees and its local branches. A second clone, another account and another machine are the register's boundary.
- Holds for a record on a peer's disk or in a peer's branch; a stash or an unsaved buffer is invisible.
- Holds at the scale of this checkout, some thirty worktrees and a few hundred branches, each ledger some hundreds of records; behaviour past that, or on a network filesystem, is unmeasured.
- Holds where git answers for the peer under abcd's isolated environment; a peer git refuses (another uid's checkout, unless
~/.abcd/trusted-rootsre-admits it) is named and not read. - macOS and Linux; the porcelain listing's path form on Windows is untested.
- Assumes the peer's ledger uses the committed layout, so a peer at a commit before that layout existed contributes no rows and says so.
Acceptance Criteria
- Given a record captured under a sibling worktree's
open/and absent from every status folder here, when the standalone command runs, then one row under that peer names the id and its title, the block names the peer's branch and home-redacted path, the exit code is 0, andgit status --porcelainin both trees is byte-identical to before. - Given a record open here and present under a peer's
resolved/orwontfix/, when the command runs, then the record appears under that peer naming which terminal folder holds it. - Given a record open here and resolved on a local branch that no worktree has checked out, when the command runs, then that branch appears as a peer and the record under it.
- Given an intent draft under a peer's
drafts/with no draft of that id here, when the command runs, then it appears under that peer as a draft. - Given
capture resolve <iss-N>for a record not in this tree that a peer holds, when it runs, then the refusal names the peer's branch, path and folder instead of not found; the same forabcd <iss-N>andintent audit <itd-N>. - Given a peer whose branch is merged into the default branch, or whose worktree directory is gone, when the command runs, then it contributes no rows and is counted in a skipped-peers line.
- Given a peer whose ledger holds one id in two status folders, when the command runs, then that peer's block says it was not read, names the id and the remedy, and every other peer renders normally.
- Given a directory
git worktree listnames whose own common dir is not this checkout's, or for which git refuses to answer, when the command runs, then it is not read and its block says why. - Given a checkout with no peers, when the command runs, then it reports none, exits 0, and the board carries no line.
- Given a non-empty diff, when the board renders, then one line states the live-peer count and the id count; given an empty diff, the line is absent.
- Given
--json, when the command runs, then the payload carries the same blocks, and no value carries an unredacted home path. - Given a peer's record file that is unreadable or malformed, when the command runs, then the id appears without a title and the command exits 0.
- Given
AGENTS.md's concurrent-sessions convention, when it is read, then the scan-before-mutating step names the command beside the harness's session listing.
Typed Links
- builds_on
itd-2609091034175565(the claim): The record this was split from on 2026-09-09; the write side this read side answers. - refines
itd-2609091416304128(the upstream-terminal refusal): Shares the reader; it judges against the fetched default branch, this against local peers. - refines
itd-2609091014076309(the worktree store) anditd-148(every change in its own worktree): Their renders list worktrees; this reader gives them the ledger columns and does not ship their render. - built on by
itd-2609150819440345(the register): Adds the network source to this reader. - built on by
itd-2609201916151817(the implement verb): Reads this picture before it picks a record. - Prose cross-references, because no schema field carries the relation (
iss-2609091256264547):iss-2609020716570699(the collisions),iss-2608220750029993(the presence lease this is not).
Audit Notes
Fidelity review — receipt rcp-a5f2f1052770 (verifier intent-auditor claude-fable-5-1).
Provenance: intent-auditor@claude-fable-5-1 · rubric_hash sha256:effa65b3e9e88ff29433b443ec2be159522a8b0b71cf1434526514aa61edb13e · prompt_hash sha256:79c4c254f138aa0015a9eb00e07f5d1cfbb656bf88a89265f57fde8c478d4c82 Input attestations: diff:8486c141..cf1247d4 (PR #666, merged 20cc37eb; tree read at cede78b8)@-;
Acceptance rollup: MET 13 · MET_WITH_CONCERNS 0 · NOT_MET 0 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: the core test captures under a sibling worktree, reads, and asserts the row plus byte-identical porcelain in both trees; the surface test asserts the branch, the home-redacted path, the id and title in text and --json evidence: internal/core/peers/peers_test.go:122 — "func TestACaptureOnASiblingDiskIsARowUnderThatPeer" evidence: internal/core/peers/peers_test.go:129 — "if porcelain(f, f.here()) != beforeHere || porcelain(f, a) != beforeA {" evidence: internal/surface/cli/peers_surface_test.go:91 — "for _, want := range []string{"feat/a", "~/wt/a", "iss-100", "open there, absent here", "A finding the peer captured"} {"
- ac-2 — MET: the diff computes an open-here/terminal-there row carrying the peer's folder, and the test names the folder
evidence: internal/core/peers/peers.go:62 — "KindTerminalThere Kind = "terminal-there""
evidence: internal/core/peers/peers.go:77 — "Folder string
json:"folder"" evidence: internal/core/peers/peers_test.go:154 — "func TestARecordOpenHereAndTerminalThereNamesTheFolder" - ac-3 — MET: every local branch no worktree has checked out is read from the common dir with ls-tree as a branch peer, test-held evidence: internal/core/peers/read.go:142 — "rep.Peers = append(rep.Peers, readBranch(root, b))" evidence: internal/core/peers/read.go:430 — "args := []string{"ls-tree", "-r", "-z", "--full-tree", ref, "--"}" evidence: internal/core/peers/peers_test.go:182 — "func TestABranchCheckedOutNowhereIsAPeer"
- ac-4 — MET: a draft in a peer's drafts/ absent here is a draft-there row, test-held evidence: internal/core/peers/peers.go:67 — "KindDraftThere Kind = "draft-there"" evidence: internal/core/peers/peers_test.go:204 — "func TestAPeerDraftAbsentHereIsADraftRow"
- ac-5 — MET: all three verbs route their not-found error through peerHeldRefusal, which names each holder's branch, redacted path and folder, and the surface test runs all three and asserts 'not found' is gone evidence: internal/surface/cli/cli.go:221 — "return peerHeldRefusal(cwd, "", args[0], err)" evidence: internal/surface/cli/cli.go:2247 — "return peerHeldRefusal(repoRoot, "abcd intent audit: ", args[0]," evidence: internal/surface/cli/cli.go:3409 — "return peerHeldRefusal(repoRoot, "abcd capture resolve: ", args[0], err)" evidence: internal/surface/cli/peers.go:236 — "holders = append(holders, h+" holds it in "+l.Folder+"/")" evidence: internal/surface/cli/peers_surface_test.go:167 — "func TestNotFoundPathsNameThePeerThatHoldsTheRecord"
- ac-6 — MET: a gone directory and a branch merged by ancestry (with clean record folders) are returned as Skipped with a reason, rendered in a skipped count on the header line, and test-held; a merged worktree with uncommitted records deliberately stays live evidence: internal/core/peers/read.go:158 — "return p, &Skipped{Source: SourceWorktree, Branch: wt.branch, Path: wt.path, Reason: SkipGone}, true" evidence: internal/core/peers/read.go:186 — "return p, &Skipped{Source: SourceWorktree, Branch: wt.branch, Path: wt.path, Reason: SkipMerged}, false" evidence: internal/surface/cli/peers.go:157 — "return fmt.Sprintf("; %d skipped (%s)", len(sk), strings.Join(parts, ", "))" evidence: internal/core/peers/peers_test.go:225 — "func TestSpentPeersAreSkippedAndCounted"
- ac-7 — MET: judgeHoldings marks a peer holding one id in two folders with the ids and the remedy and no rows, and the test asserts the healthy sibling still renders evidence: internal/core/peers/read.go:240 — "return "its ledger holds one id in two places (" + strings.Join(split, "; ") +" evidence: internal/core/peers/peers_test.go:300 — "func TestASplitLedgerPeerIsMarkedAndOthersRender"
- ac-8 — MET: the candidate's own --git-common-dir is compared to this checkout's, and a refusal or a mismatch sets NotRead with the reason, test-held for both evidence: internal/core/peers/read.go:168 — "p.NotRead = "git refused to answer for it: " + firstLine(err.Error())" evidence: internal/core/peers/read.go:172 — "p.NotRead = "its own common dir is not this checkout's, so it belongs to another repository"" evidence: internal/core/peers/peers_test.go:329 — "func TestAForeignOrRefusedWorktreeIsNamedNotRead"
- ac-9 — MET: with no peers the command prints 'no peers' and the board carries no line in text or --json, test-held on the surface and the core evidence: internal/surface/cli/peers.go:96 — "fmt.Fprintln(w, "abcd peers — no peers")" evidence: internal/surface/cli/peers_surface_test.go:135 — "if out := string(runCLI(t, "peers")); !strings.Contains(out, "no peers") {" evidence: internal/core/peers/peers_test.go:356 — "func TestACheckoutWithNoPeersReportsNone"
- ac-10 — MET: the board's peers line is built only when the id count is non-zero and carries the live-peer and id counts, asserted present with one peer and absent with none evidence: internal/surface/cli/peers.go:187 — "if rep.IDCount() == 0 {" evidence: internal/surface/cli/peers.go:190 — "return &boardPeersLine{Live: rep.Live(), IDs: rep.IDCount()}" evidence: internal/surface/cli/peers_surface_test.go:132 — "func TestTheBoardCarriesAPeersLineOnlyWhenPeersHoldSomething"
- ac-11 — MET: the --json payload is built from the same Report with every peer and skipped path and NotRead reason passed through RedactHome, and the surface test asserts no home path in the raw JSON evidence: internal/surface/cli/peers.go:80 — "p.Path = fsutil.RedactHome(p.Path)" evidence: internal/surface/cli/peers.go:85 — "s.Path = fsutil.RedactHome(s.Path)" evidence: internal/surface/cli/peers_surface_test.go:99 — "noHomePath(t, home, string(raw))"
- ac-12 — MET: a title read that fails returns the empty string and the id is listed anyway; the test covers a malformed and a mode-0 file with the read succeeding evidence: internal/core/peers/read.go:321 — "if err != nil {" evidence: internal/core/peers/peers.go:79 — "malformed; the id is listed either way." evidence: internal/core/peers/peers_test.go:369 — "func TestAnUnreadableOrMalformedRecordListsTheIDAlone"
- ac-13 — MET: the scan-before-mutating step in AGENTS.md names
abcd peersbeside the harness's session listing, and a test reads that step and asserts both evidence: AGENTS.md:209 — "also rungo run ./cmd/abcd peers(--jsonfor a machine reader): it lists" evidence: internal/surface/cli/peers_surface_test.go:262 — "func TestTheScanBeforeMutatingConventionNamesThePeerListing"
Gap audit:
- honoured:
- one reader, two sources, nothing written evidence: internal/core/peers/peers.go:53 — "var Sources = []Source{SourceWorktree, SourceBranch}" evidence: internal/core/peers/peers.go:9 — "It opens no file for writing, runs only read-only git commands"
- the three not-found paths name the peer evidence: internal/surface/cli/peers_surface_test.go:167 — "func TestNotFoundPathsNameThePeerThatHoldsTheRecord"
- the register source is a declared empty slot, and a Report says so evidence: internal/core/peers/peers.go:45 — "SourceRegister is the slot the register intent (itd-2609150819440345)"
- a peer's branch and path are sanitised before they reach a stream evidence: internal/surface/cli/peers_surface_test.go:221 — "func TestThePeerHeldRefusalSanitisesThePeersBranchAndPath"
- a gone or refused worktree's unmerged branch is still read from the store evidence: internal/core/peers/peers_test.go:260 — "func TestAGoneOrRefusedWorktreesUnmergedBranchIsReadFromTheStore"
- diverged:
- the not-found paths look up drafts/ only: Locate spans every intent bucket, so intent audit names a peer's shipped/ copy too (a widening, not a loss) evidence: internal/surface/cli/peers_surface_test.go:184 — "{"intent audit", []string{"intent", "audit", "itd-77"}, []string{"side", "shipped/"}},"
- missing: (none)
Scope-condition dispositions:
- cond-2609202056488592 — survived: a listed directory whose own common dir is not this checkout's is named and not read, and the sources are the two local ones with the register slot empty evidence: internal/core/peers/read.go:171 — "if realPath(theirs) != realPath(common) {" evidence: internal/core/peers/peers.go:53 — "var Sources = []Source{SourceWorktree, SourceBranch}"
- cond-2609202056489916 — survived: holdings are read off a worktree's disk or from a branch's tree with ls-tree; nothing reads a stash or a buffer evidence: internal/core/peers/read.go:378 — "func scanDisk(root string) (holdings, bool, error) {" evidence: internal/core/peers/read.go:429 — "func scanTree(root, ref string) (holdings, bool, error) {"
- cond-2609202056486227 — untested: no test or artefact in the delivered diff exercises the reader at thirty worktrees or a few hundred branches, nor on a network filesystem
- cond-2609202056485097 — survived: a worktree git refuses to answer for is named with the refusal and not read, test-held with a dangling gitdir pointer evidence: internal/core/peers/read.go:166 — "theirs, err := commonDir(wt.path)" evidence: internal/core/peers/peers_test.go:329 — "func TestAForeignOrRefusedWorktreeIsNamedNotRead"
- cond-2609202056483851 — survived: the tests run on the ubuntu and macos legs of the CI matrix and the porcelain parser is tested for both path forms git emits; Windows is not in the matrix, as the condition states evidence: .github/workflows/ci.yml:230 — "os: [ubuntu-latest, macos-latest]" evidence: internal/gitutil/worktree_test.go:14 — "func TestParseWorktreeListReadsBothPorcelainForms"
- cond-2609202056489557 — survived: a peer holding no records at the committed layout is marked NotRead with that reason and contributes no rows evidence: internal/core/peers/read.go:224 — "return "it holds no records at the committed layout (" + capture.LedgerRelPath + "/, " +"
Grounds
- pursued: the pilot and the big run put four to seven lanes on one checkout this week, and every collision on record was a failure of visibility, not of will; we expect a read-only view of what peers hold, delivered in the verbs' own refusals, to stop them; shown wrong if a lane that was shown a peer's holding still duplicates or re-fixes it, or if the next collision comes from a peer this reader cannot see
Frontmatter
| id | itd-2609091416295622 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | major |
.abcd/development/intents/shipped/itd-2609091416295622-a-session-sees-the-records-its-sibling.md
open on GitHub ↗ · commit history ↗
References6
- 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
- itd-2609091014076309Session and agent worktrees live in a machine-scoped store that abcd lists and reclaims, never beside the user's own projectsrelated
- itd-2609091034175565Before an agent starts on an item, it reserves it on the shared remote, and everyone who works on the project sees the reservationbuilds on
- itd-2609091416304128capture resolve refuses a record the default branch has already closed, judged by the last fetchrelated
- itd-2609150819440345Which session holds which worktree, branch or record is coordinated entirely by conversation, so every new session repeats a handshake that nothing records. A session joining work in progress has no way to ask what is already claimed: it messages the peers it can see, waits for replies, and rebuilds a picture that the sessions before it had already built and did not write down. One measured encounter cost four messages and about fifteen minutes before any work began, and the picture it produced is not durable, so the session after that pays again. The convention that a diff you did not make is a peer's work depends on knowing who the peers are and what they hold, which is precisely the thing no artefact carries. The repository already records this gap for the narrow case of detecting a peer session before mutating git state; the wider case is claim rather than presence, and the two want the same substrate. Whatever holds it should be as cheap to write as it is to read, because a coordination record nobody updates is worse than the chat it replaced.related
- itd-2609201916151817One verb takes a READY intent to delivered, and refuses while a decision is openrelated
Referenced by9
- 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.related
- iss-2609020716570699Nothing tells an agent that a record it is about to fix has been claimed or resolved by another session until the resolution gate refuses the push. In one night a peer session re-fixed two issues a paused branch also fixed, and two of its open PRs duplicate merged work. The claim signal that worked in every published multi-agent run is the repository itself: a claim written into the open record (claimed_by: account and harness, branch) and pushed alone through the queue before any fix starts, so a losing race is a push rejection; plus a duplicate-guard required check that fails a PR whose Resolves trailer names a record already resolved on origin/main; plus capture resolve refusing a record that is already terminal on the fetched origin/main. Folder membership is already the status signal, so the claim extends the one canonical primitive rather than adding a lock file that rots. Refines iss-2608220750029993.related
- iss-2610262044300840`peers` means records held by sibling worktrees in the shipped reader, but the planned announcements ruling reserves it for sessions running nowrelated
- iss-2610262045516387itd-2609091416295622 defines peers as a read-only view of this checkout's common dir; itd-2609091034175565 has peers fetch origin and list every person's reservationsrelated
- itd-2609091034175565Before an agent starts on an item, it reserves it on the shared remote, and everyone who works on the project sees the reservationrelated
- itd-2609150819440345Which session holds which worktree, branch or record is coordinated entirely by conversation, so every new session repeats a handshake that nothing records. A session joining work in progress has no way to ask what is already claimed: it messages the peers it can see, waits for replies, and rebuilds a picture that the sessions before it had already built and did not write down. One measured encounter cost four messages and about fifteen minutes before any work began, and the picture it produced is not durable, so the session after that pays again. The convention that a diff you did not make is a peer's work depends on knowing who the peers are and what they hold, which is precisely the thing no artefact carries. The repository already records this gap for the narrow case of detecting a peer session before mutating git state; the wider case is claim rather than presence, and the two want the same substrate. Whatever holds it should be as cheap to write as it is to read, because a coordination record nobody updates is worse than the chat it replaced.built on by
- itd-2609201916151817One verb takes a READY intent to delivered, and refuses while a decision is openbuilt on by
- itd-2609221656373558Two sessions share one run, and the run measures which way of dividing the work is bestbuilt on by
- spc-2609202056480020a-session-sees-the-records-its-sibling-worktrees-hold-beforeimplemented by
mentions13
- dcn-26090900000000052026-09-09 — itd-2609091034175565, the claim intent, is split into three records (maintainer, ruling after two adversarial reviews of the widened draft, design/feasibility and record-discipline). The reviews found the expensive parts unsound as drafted: a `claimed_by` stamp on an issue record is invisible to any peer on an older binary, because `issueschema.Known` is a closed allow-list whose reader refuses and skips a record carrying an unknown key and `record_schema` mirrors the refusal into the gate, and version skew is the steady state here (five plugin-cache vintages beside a `go run` checkout); the write-verb refusals fire after the fix is written, because `AGENTS.md` puts `capture resolve` in the same change as the fix; no staleness threshold is safe in both directions for two sessions in one worktree, since the worktree-exists and branch-merged tests are identical for both and a host may fire session-end on a context clear with the human still present; and the pushed half costs a merge-queue pass per claim, measured at fifteen to sixteen minutes on this repository's merge-group `ci` leg. Every collision on record is one of two claim-free shapes. The ruling: itd-2609091416295622 carries the read-only sibling-worktree ledger diff over `git worktree list --porcelain` (no claim, no lease, no hook, no threshold; the piece that ships soonest); itd-2609091416304128 carries `capture resolve` and `capture wontfix` refusing a record terminal at the local `origin/main` ref as last fetched, stating the ref's age and fetching nothing, with the same judgement rendered read-only on `abcd <record-id>`; itd-2609091034175565 keeps the claim, the lease and the refusals as a draft marked not ready, carrying the refusal-surface, liveness and pushed-price questions as open questions and the two-release stamp migration as a hard constraint. The existing record stays the claim so the `promoted_from` trail from iss-2609020716570699 — whose remedy is the claim and the pushed half — stays true rather than being retitled onto a listing the issue never proposed; the two new records reach the issue through `related_intents` on the issue and on themselves, and every relation the schema cannot type is stated in prose as a prose cross-reference (iss-2609091256264547). All three sit in `drafts/`; adoption is the interview's. Rejected: re-scoping the existing record to the listing, which keeps the trail mechanically and breaks it semantically; a fifth relation word for "split from", which is the vague form the decomposition principle forbids.
- iss-100disembark has no conventions-tier adapters for constraints/naming, glossary, or internals, so these ground only from an authored abcd brief. Add adapters reading GLOSSARY.md / docs/glossary (naming, glossary) and docs/architecture / package layout (internals) so a repo with conventional docs but no abcd record still grounds them.
- iss-2609091256264547The decomposition discipline requires a cross-record link to be typed with one of four relations, supersedes or reverses or duplicates or refines, and never a vague related. Only the first of those four exists. supersedes is schema-known through recordHandleFields and is carried by fifty-eight decision records and three others, while reverses, duplicates and refines appear in no schema and in no committed record anywhere in the tree: the field list a record may carry is related_adrs, related_intents, builds_on and blocked_by, and a record carrying a key outside the known set is dropped by the reader rather than reported, so writing one of the three missing words would make the record invisible to every surface that reads it. The consequence is that an author following the rule literally either writes a link the tooling silently discards or writes the relation in prose and calls it typed, and the corpus shows the second: records assert a typed link in a heading and carry no frontmatter edge, which reads as done to a human and is invisible to every graph walker. That is the shape enforcement-claims-are-facts refuses, a convention naming a mechanism that does not exist, and it is load-bearing here because the decomposition protocol is the documented gate until its automated rung ships. Fix candidates, none chosen: implement the three missing relations as known fields so the rule can be followed; or narrow the rule to the vocabulary the schema implements and say what an author does with a relation the four words cannot express; or record that prose is the sanctioned form for the three and stop calling them typed. Detector: a record asserting a typed relation in its body carries a frontmatter edge naming the same target, and a relation the schema cannot express is refused at write time rather than dropped in silence.
- iss-2609100519122086Which session holds which worktree, branch or record is coordinated entirely by conversation, so every new session repeats a handshake that nothing records. A session joining work in progress has no way to ask what is already claimed: it messages the peers it can see, waits for replies, and rebuilds a picture that the sessions before it had already built and did not write down. One measured encounter cost four messages and about fifteen minutes before any work began, and the picture it produced is not durable, so the session after that pays again. The convention that a diff you did not make is a peer's work depends on knowing who the peers are and what they hold, which is precisely the thing no artefact carries. The repository already records this gap for the narrow case of detecting a peer session before mutating git state; the wider case is claim rather than presence, and the two want the same substrate. Whatever holds it should be as cheap to write as it is to read, because a coordination record nobody updates is worse than the chat it replaced.
- iss-2609190338070038The capture surface page documents the two-status-folders refusal but not the convention that avoids it: a record is resolved on the branch that carries it. commands/capture.md explains why an id in open/ and resolved/ at once is refused and how the merge artefact arises, and stops there; the rule that prevents it (never re-add a record to the default branch after a branch was cut from it; resolve it on the branch that carries it) lives only in this repository's AGENTS.md, which a managed repository does not inherit. In the Gropius sweep of 2026-09-19 (session gropiusllm-66, forty lanes) a record captured on an unmerged branch could not be resolved from another branch without producing exactly that duplicate once both landed, so lanes merged each other's branches to resolve. Wanted, either: one paragraph on the capture page stating the convention for a managed repository, or a resolve that tolerates a record absent from this checkout when told where it is (the session's --expect-on-branch), which is the ledger-visibility capability itd-2609091416295622 already weighs. This record is the documentation half.
- iss-2609200832054807No verb moves an untracked new record into a lane worktree. A draft filed with abcd intent "<text>" in the primary checkout is an untracked file with no history, so the one legitimate copy case in a worktree-per-lane flow, handing that draft to the lane that will plan and implement it, has no write path: the lane copies the file by hand, and the copy and the original are two untracked files with the same id in two trees until one is deleted, which is the shape the sibling-worktree visibility intent (itd-2609091416295622) exists to notice. Relayed from the Gropius session gropiusllm-2b on 2026-09-20 (sub-agent-lane experiment, low priority in the session's words). Wanted, either: a record export/import pair (or a move) that carries one uncommitted record from this checkout into a named worktree and removes it here, or filing directly into a named worktree (abcd intent "<text>" --worktree <lane>), so the record has one home from its first byte. Intent-shaped; the routing is the product thinker's.
- iss-2609202053570475Every ledger verb should name which checkout's ledger it addressed. The ledger is per worktree and says so nowhere: a capture filed in one worktree is invisible to capture resolve in another, and the verb's refusal reads "not found" with no hint that another checkout holds the record. The cheapest always-on remedy, asked for in the 2026-09-18 corroboration on iss-2609020716570699 and routed out of the peer-listing intent by its record-discipline review on 2026-09-20 as a cross-cutting change: one line from every ledger verb (capture, resolve, wontfix, promote, list, the record dispatcher, intent audit) naming the checkout root and branch whose ledger it read or wrote, on stderr in the text render and as a member in --json. Distinct from the peer listing (itd-2609091416295622), which reads other checkouts; this is the verb saying which one it is in.
- 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.
- itd-77abcd's User-Level Home Lives Where You Want It
- itd-87A Finding That Comes Back After You Closed It Tells You Something, And abcd Stops Throwing It Away
- itd-121Type The Id, Get Your Next Move
- spc-42every-change-starts-in-its-own-worktree-the-primary-checkout
- spc-2609202134338445one-verb-takes-a-single-intent-from-ready-to-delivered-witho