Development record
Two Agents Can Mint At The Same Instant And Never Collide
Press Release
abcd record ids stop colliding when the work goes parallel. Every id abcd mints is collision-proof by construction, with no coordination between agents: the native default needs no network and no registry, and two agents minting the same instant on different branches produce different ids — neither is ever renumbered. The concrete scheme is the planning grill's one big decision, chosen against this repository's own id grammar so that collision-safety is not paid for in readability or in ripple. Where a team wants a shared mint registry, an optional forge-backed allocator can hand out numbers server-side — allocation only: the committed ledger stays the sole store, exactly as the forge-mirror decision requires.
"Two hunts and a release session minted over eighty ids in one weekend and collided three times — one collision cost us a release re-cut," said Kira, an open-source maintainer. "Now every routine just mints. Nothing renumbers, nothing waits, and I still read
capture listnewest-first at a glance."
Why This Matters
Record-id allocation is branch-local: each minter scans the refs for the
family's highest id and takes the next one. iss-80 closed the
commit-then-branch case with MaxAcrossRefs and accepted the residual —
two branches that both mint before either commits — as a trade-off, tracked by
no open item, with the candidate schemes ("forge-minted / random-suffix /
timestamp / reserve-registry") named as SOTA under research in the issue's
body. That acceptance was reasonable for one maintainer; the repository it
priced no longer exists.
The week of 2026-08-19/20 reopened the question with recorded costs: three
live id collisions in two days across three distinct minter pairings
(hunt-vs-session twice, hunt-vs-hunt once; iss-330 is the standing record, the
round-2 renumber in dcn-2608200000000001 the second occurrence, PR #386 the third),
one of which invalidated a tagged release cut whose receipts were already
frozen and forced a full re-cut. The
graded field test
confirmed all four pre-registered predictions: the mechanism is max+1 from a
stale checkout, decided purely by merge timing; detection always falls to
issue_id_unique at PR CI, after the work is done; and the working mitigation
— just-in-time fetch-and-verify twice per task, plus scanning unmerged
bughunt-* branch ledgers — held for the one minter carrying it and nobody
else. Safety must live in the mint, not in every minter's prompt.
What's In Scope
- The mint itself: a collision-proof allocation scheme behind the one id-minting seam the record families share, chosen at the grill against the fit criterion below.
- Every family the chosen scheme reaches for free. The maintainer's
observed ranking (2026-08-20) is iss ≫ itd > adr > spc — issues are where
all three collisions happened, intents are mechanically agent-mintable via
capture promote, adr had a reservation near-miss (the adr-42/adr-43 rename), specs are interview-serialised. A format-preserving scheme costs the same for all families, making scope a rollout order (captures first), not an exclusion; an expensive scheme narrows toisswith the rest a recorded residual. - The optional forge-backed allocator — number allocation and, as a side effect, a shared mint registry visible to every forge-configured minter. Allocation only.
What's Out of Scope
- The forge as a store. The 2026-08-19 decision (dcn-2608190000000001; embodied
in itd-129)
is ledger-canonical, mirror-out, "the forge owns nothing" — this intent's
forge option allocates numbers and never stores records. Any forge
read/write beyond allocation is itd-129's surface (typed relation:
itd-114's allocator option
builds_onitd-129's adapter seam). - Semantic deduplication (iss-344, the same-defect-twice class): belongs to the capture-time validator rung (itd-84). The grill should still weigh that the forge allocator incidentally gives minters visibility of each other — the shared root cause of both collision classes — a property no purely-local scheme has.
- Any remap of legacy ids:
iss-N/itd-N/spc-N/adr ordinals already minted stay exactly as they are (the ids-are-capture-stable invariant).
SOTA
Anchors: UUIDv7 / ULID (time-ordered, coordinator-free distributed ids); git's dual id (collision-proof core + human short handle); forge server-side numbering (atomic by definition); and the two candidates iss-80 named that the first draft of this section dropped: timestamp-numeric ids and reserve-registry.
The fit criterion is this repository's own id grammar. The repo is a
closed numeric id type-system: the release bijection, the canonical resolver,
the record-lint handle and uniqueness rules, capture list ordering, the
abcd <id> dispatch and its typo guard, the ledger store contract, and every
promoted_to (historical)/resolved_by field anchor on (iss|itd|spc)-[0-9]+ (and adr's
zero-padded filename ordinals), with several consumers failing silently on a
non-matching id — a ULID-shaped record drops out of the release cut unreported,
its typed links go unchecked, and it sorts below every legacy record forever.
The adversarial design review of 2026-08-20 sized that ripple at roughly
thirty surfaces. Candidates are therefore judged on collision-safety times
ripple:
- Timestamp-numeric (
iss-<yymmddHHMMSS><random digits>): time-ordered, offline, coordination-free; kills the observed max+1 mechanism; matches[0-9]+literally, so the existing grammar, parsers, sorts, and gates hold unchanged (the existing O_EXCL bump-retry absorbs same-second residue). Cost: 14–16-digit ids; legacy ids sort numerically below all new ones — which is correct time order. - ULID/UUIDv7-shaped: strongest entropy; breaks the numeric grammar — pays the full ~30-surface ripple plus a permanent dual-grammar tax, and the CHANGELOG line the bijection forces is where "legible at a glance" goes to die.
- Forge-allocated numbers: atomic, registry-visible; allocates for the issues family only, needs network at mint, and is opt-in — the benefit accrues only to configured minters.
- Reserve-registry / random-suffix: named by iss-80; a committed reservation file recreates merge-contention on itself; random suffixes alone lose time-ordering. Kept on the table for the grill to dismiss with reasons rather than silence.
Declared path: 2 — native floor, adapter seam. Scheme selected at the
2026-08-20 planning interview: timestamp-numeric (iss-<yymmddHHMMSS><random digits>), under the fit criterion above — collision-proof against the
observed mechanism at near-zero ripple, format-preserving for every existing
consumer. The forge allocator is the optional adapter behind the same seam. The id format is a trust surface, not plumbing: its
decision lands as an ADR at planning (with a brief-invariant seat for
capture-stability), per the adr-44 extraction precedent — not deferred to
adoption.
Acceptance Criteria
BDD (the itd-1 discipline). The mint's clock and entropy are injectable seams so the race cases are deterministic in tests.
- Given two minters on separate branches whose injected clocks read the same instant, when both mint before either pushes, then the two ids differ, and merging both branches passes every uniqueness gate with no renumber.
- Given no network is available, when an id is minted natively, then the mint succeeds and is collision-proof by the native scheme alone.
- Given ids minted by the chosen scheme, when the repository's own
consumers run against them — the release-cut derivation and bijection, the
canonical resolver, the record-lint handle and uniqueness rules,
capture listordering, and theabcd <id>dispatch — then every one resolves, cites, sorts, and gates them without modification beyond what the scheme's ADR names, and a mixed ledger (legacy + new) time-orders correctly incapture list. - Given a record carrying a legacy sequential id, when the new scheme is in effect, then the legacy id stays valid, stable, and unrenumbered.
- Given the forge allocator is configured, when
abcd capturemints, then the number is allocated server-side, the record is written to the committed ledger (never stored on the forge), and an offline mint under forge configuration refuses loudly or falls back per the ADR's explicit choice — never a silent mixed outcome. - Given the rollout's first family (captures) has run the scheme for a release cycle, when a second family adopts it, then the adoption is a configuration of the shared mint seam, not a second implementation.
Decomposition (itd-84 re-run, 2026-08-20 — supersedes the 2026-08-16 table)
| Part | Type | Home |
|---|---|---|
| Collision-proof minting, native default + optional forge allocator | capability | this intent |
| Candidate schemes and the repo-grammar fit criterion | SOTA declaration (path 2) | this intent's SOTA section |
| The id format and its capture-stability guarantee | trust rule | ADR at planning + brief-invariant seat (adr-44 precedent) |
| The forge allocator's network posture at mint time | trust rule | the same ADR, ruled against brief invariants 7 and 10 |
| "Native-default, adapter-optional" | stance | already carried by brief invariant 2 (adr-22) and prefer-sota — correctly cited, no new principle |
| Mint-seam mechanics, per-family rollout | plumbing | the spec at planning |
Typed links: refines [iss-80] (reopens the residual its resolution accepted,
on the strength of iss-330, the round-2 renumber, and the graded field test);
the forge-allocator option builds_on itd-129's adapter seam and never
crosses its ledger-canonical line; evidence: iss-330, iss-344,
the field test.
Advisory reversal flag — CONFIRMED DISCHARGED at the 2026-08-20
interview: the selected scheme (timestamp-numeric) keeps the id numeric,
human-readable, and time-ordered; no property of iss-N reverses.
Open Questions
All four interview questions were ruled at the 2026-08-20 planning interview; the rulings live in adr-45 and are folded into the SOTA and scope sections above:
- The central fork — RULED: timestamp-numeric. Chosen against the fit criterion; the reversal flag is discharged (no reversal — the format stays numeric and time-ordered).
- Rollout — RULED: captures first, all families follow as configuration of the shared seam after one release cycle; adr's zero-padded ordinal gets its ruling at its turn.
- Offline-under-forge — RULED: fall back to native, loudly. Capture never blocks on network; the mint names the path it took; the format stays uniform either way.
- The uniqueness detectors — RULED: keep, as the cheap assertion the scheme held (the field test's P3: late detection is bad, no detection is worse).
One question remains genuinely open for the spec: the random-digit width and same-instant tiebreak (the existing O_EXCL bump-retry vs wider entropy) — mechanics, not policy.
Audit Notes
Fidelity review — receipt rcp-b0efd378c917 (verifier intent-fidelity-reviewer claude-fable-5).
Provenance: intent-fidelity-reviewer@claude-fable-5 · rubric_hash sha256:335141cece2a50bace98c25567572b17690278eead062316b70502f2cba48d7f · prompt_hash sha256:c4a1de6076c1a45725b6a0d70466cf65a7772a1f45b1917f78543c3c99f04a10 Input attestations: diff:9c1364c..4d58f05@sha256:082dda4963241179f4d34f73dc368158796d81db43e7c72ac3e774688114f8b6;
Acceptance rollup: MET 4 · MET_WITH_CONCERNS 1 · NOT_MET 1 · INCONCLUSIVE 0
Per-criterion verdicts:
- ac-1 — MET: TestMintSameInstantDiffers pins two same-instant injected-clock minters producing distinct ids at the seam; TestCaptureBranchesSameInstantNeverCollide reproduces it across two real git branches minting before either pushes; and TestCaptureBranchesMergeUnionPassesGates closes the merge clause literally — it performs the git merge of the two minting branches, asserts both ids survive unrenumbered in open/, runs the armed issue_id_unique gate clean over the union, and proves the gate is not vacuous with a planted same-id duplicate that fires it. Both packages pass (go test ./internal/core/capture/ ./internal/core/recordid/). evidence: internal/core/recordid/mint_test.go:60 — "func TestMintSameInstantDiffers(t *testing.T) {" evidence: internal/core/capture/refunion_test.go:63 — "if resA.ID == resB.ID {" evidence: internal/core/capture/refunion_test.go:113 — "r.Git("merge", "--no-edit", trunk)" evidence: internal/core/capture/refunion_test.go:127 — "if len(findings) != 0 {" evidence: internal/core/capture/refunion_test.go:141 — "if len(findings) < 2 {"
- ac-2 — MET: The native mint is offline by construction: mint.go's entire import set is crypto/rand, encoding/binary, fmt, io, regexp, time — no network-capable package exists in the path — and Mint's only inputs are the injected clock and entropy ("It reads nothing — no ledger, no refs, no maximum"); collision-proofness by the native scheme alone is the time-stamp-plus-uniform-suffix design exercised by the same-instant and ignores-ledger-maximum tests, all running hermetically with no network. evidence: internal/core/recordid/mint.go:16 — ""crypto/rand"" evidence: internal/core/recordid/mint.go:55 — "It reads nothing — no ledger," evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:138 — "(the native path has no network use by construction — the mint's only" evidence: internal/core/capture/mint_test.go:149 — "func TestCaptureMintIgnoresLedgerMaximum(t *testing.T) {"
- ac-3 — MET: TestRippleGateConsumersHoldOnMintedIDs executes the criterion rather than asserting it: a mixed legacy+native ledger built partly by the real production mint is run through capture-list ordering (mixed ledger asserted in correct time order, legacy era first), the status board, the canonical resolver, the abcd <id> dispatch (record.Describe), the record-lint uniqueness/impact/schema rules gating clean, and the release-cut derivation and bijection (exactly the native resolved record cut, patch bump derived) — and the delivered diff modifies none of those consumer packages (changelog, record, lint untouched), matching adr-45 ruling 1's format-preserving claim. evidence: internal/core/capture/ripplegate_test.go:45 — "func TestRippleGateConsumersHoldOnMintedIDs(t *testing.T) {" evidence: internal/core/capture/ripplegate_test.go:98 — "if !(pos[legacyOpen.ID] < pos[legacyFixed.ID] && pos[legacyFixed.ID] < pos[nativeOpen.ID]" evidence: internal/core/capture/ripplegate_test.go:144 — "if len(findings) != 0 {" evidence: internal/core/capture/ripplegate_test.go:155 — "if len(shipped.Added) != 1 || shipped.Added[0].ID != nativeFixed.ID {"
- ac-4 — MET: The ripple gate plants legacy sequential ids (iss-3, iss-374) beneath the native era and asserts they remain present, resolvable, and listed under their original ids beside timestamp mints — never renumbered; capture-stability is seated as adr-45 ruling 2 and brief invariant 11, and reservePath still refuses any id already present in the ledger rather than reusing or remapping it. evidence: internal/core/capture/ripplegate_test.go:51 — "legacyOpen := mustCapture(t, root, ledger, "legacy-open", "iss-3")" evidence: internal/core/capture/ripplegate_test.go:98 — "if !(pos[legacyOpen.ID] < pos[legacyFixed.ID]" evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:36 — "2. Ids are capture-stable: once minted, an id is never renumbered by any" evidence: .abcd/development/brief/02-constraints/03-invariants.md:35 — "Record ids are collision-proof by construction and capture-stable"
- ac-5 — NOT_MET: The forge-backed allocator is not delivered: no forge allocation, server-side numbering, or offline-refusal/fallback code exists anywhere in the diff. This is a recorded, signed-off deferral, not an omission discovered here — spc-33 rules the forge allocator "out of this spec's delivery" as a later adapter behind the same seam, and adr-45 ruling 4 records the loud-native-fallback posture it must honour when it lands — but the criterion's observable outcome (server-side allocation under forge configuration) is absent from the delivered reality. evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:18 — "adapter behind the same seam and is out of this spec's delivery" evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:143 — "later adapter, not this delivery." evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:43 — "4. The optional forge allocator allocates and never stores"
- ac-6 — MET_WITH_CONCERNS: The ruled deliverable at this stage — the family-generic seam — is delivered and tested: Mint(family) costs itd and spc the identical call (TestMintFamilyGeneric), so adoption is a configuration swap, not a second implementation. Concern, per adr-45 ruling 3: the criterion's full scenario (a second family actually adopting after captures run a release cycle) is future-by-design — the itd/spc allocators deliberately keep their legacy max+1-with-refs-union minting until each family's adoption change swaps the allocation call, so the adoption itself remains owed.
evidence: internal/core/recordid/mint_test.go:82 — "func TestMintFamilyGeneric(t *testing.T) {"
evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:40 — "3. Rollout is captures-first, then every family through the same seam:"
evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:104 — "(
spc) allocators keep their legacy max+1-with-refs-union minting and their"
Gap audit:
- honoured:
- In-Scope: one collision-proof mint behind the shared id-minting seam, wired into capture — the mint consults no maximum and capture's reservation redraws on clash evidence: internal/core/recordid/mint.go:58 — "func (m Minter) Mint(family string) (string, error) {" evidence: internal/core/capture/alloc.go:143 — "issID, mErr := minter.Mint("iss")"
- Decomposition trust rule: the id format and capture-stability landed as an ADR at planning with a brief-invariant seat (adr-45 + invariant 11), per the adr-44 precedent evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:13 — "# ADR-45: Record ids are timestamp-numeric, capture-stable, and never allocated by looking at the maximum" evidence: .abcd/development/brief/02-constraints/03-invariants.md:35 — "Record ids are collision-proof by construction and capture-stable"
- Out-of-Scope: no remap of legacy ids — legacy sequential ids stay exactly as minted beside the native era evidence: internal/core/capture/ripplegate_test.go:51 — "legacyOpen := mustCapture(t, root, ledger, "legacy-open", "iss-3")" evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:36 — "2. Ids are capture-stable: once minted, an id is never renumbered by any"
- Open Questions: the one question left genuinely open (random-digit width and same-instant tiebreak) is settled by spc-33 rulings 1-2 and pinned by deterministic tests — 4-digit rejection-sampled suffix, redraw-on-clash evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:27 — "followed by a 4-digit uniform random suffix, zero-padded to fixed width" evidence: internal/core/recordid/mint_test.go:110 — "func TestMintSuffixRejectionSampling(t *testing.T) {" evidence: internal/core/capture/mint_test.go:70 — "func TestCaptureSameInstantSameLedgerRedraws(t *testing.T) {"
- Open Questions ruling: the uniqueness detectors stay armed as the scheme's fail-safe — kept, reinterpreted as scheme assertions, and exercised non-vacuously by the merge-union test's planted-duplicate negative control evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:48 — "5. The uniqueness detectors stay as the cheap assertion that the scheme" evidence: internal/core/capture/refunion_test.go:141 — "if len(findings) < 2 {"
- diverged:
- In-Scope: "every family the chosen scheme reaches for free" is delivered as seam generality only — itd/spc mint through the identical call in tests, but their production allocators deliberately keep legacy max+1-with-refs-union minting until each family's adoption turn (adr-45 ruling 3, captures-first)
evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:104 — "(
spc) allocators keep their legacy max+1-with-refs-union minting and their" evidence: internal/core/recordid/mint_test.go:82 — "func TestMintFamilyGeneric(t *testing.T) {" - The intent's SOTA section sketched the existing O_EXCL bump-retry as the same-second tiebreak; spc-33 ruling 2 replaced the bump with a redraw (a bump is a miniature max+1) — a recorded, reasoned divergence, and the redraw is what shipped
evidence: .abcd/development/intents/shipped/itd-114-abcd-mints-collision-proof-record-ids.md:115 — "unchanged (the existing O_EXCL bump-retry absorbs same-second residue)."
evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:61 — "step: on
EEXISTthe mint redraws a fresh id (same clock read policy, new"
- In-Scope: "every family the chosen scheme reaches for free" is delivered as seam generality only — itd/spc mint through the identical call in tests, but their production allocators deliberately keep legacy max+1-with-refs-union minting until each family's adoption turn (adr-45 ruling 3, captures-first)
evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:104 — "(
- missing:
- In-Scope bullet 3: the optional forge-backed allocator — and with it the offline-under-forge loud-fallback behaviour ruled at the interview — is not in the delivery; spc-33 defers it by ruling to a later adapter behind the same seam, so the press release's forge-registry promise remains owed evidence: .abcd/development/specs/closed/spc-33-abcd-mints-collision-proof-record-ids.md:18 — "adapter behind the same seam and is out of this spec's delivery" evidence: .abcd/development/decisions/adrs/0045-record-ids-are-timestamp-numeric-and.md:43 — "4. The optional forge allocator allocates and never stores"
Frontmatter
| id | itd-114 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-114-abcd-mints-collision-proof-record-ids.md
open on GitHub ↗ · commit history ↗
Referenced by6
- adr-45Record ids are timestamp-numeric, capture-stable, and never allocated by looking at the maximumrelated
- iss-2610262034489695itd-114's maintainer reads capture list newest-first; the capture chapter orders the list by derived priority, unblocked first and then by severity.related
- iss-2610262043063912itd-107 keeps the strict merge policy because ids minted on two branches can collide; itd-114 says such ids never collide.related
- iss-2610262043071551itd-115 keeps the strict merge gate to catch duplicate ids from parallel sessions; itd-114 says ids are collision-proof with no coordination.related
- iss-2610262044038958itd-44 writes ADRs under a next-free ordinal; itd-114 makes every minted id collision-proof across branchesrelated
- spc-33abcd-mints-collision-proof-record-ids-across-parallel-agentsimplemented by
mentions29
- adr-22Bundled dependencies become pluggable adapters over a native default
- adr-42The guard's parse layer is a mistake filter, not a security boundary — matching is two-tier, and completeness is abandoned as a goal
- adr-43Contributions are inbound = outbound MIT, and the trust boundary is the organisation's role ladder
- adr-44abcd never mutates a remote uninvited, and identity derives from caller-local facts
- dcn-26081900000000012026-08-19 — The `.abcd/work/issues/` ledger is the single canonical issue store; forge
- dcn-26082000000000012026-08-20 — bughunt round 2 (branch bughunt-a/round-2): captured iss-331..iss-343 and fixed (ids 339-343 re-minted from an initial 326-330 after main concurrently took those numbers in the v0.6.1 cut)
- dcn-26082000000000042026-08-20 — itd-114 (collision-proof record ids) is pulled forward: two live
- dcn-26082000000000072026-08-20 — the spc-33 mint mechanics are ruled and the native mint ships
- iss-3phase membership and lifecycle directories disagree: planned intents (itd-20, itd-24, itd-29, itd-46) appear in no phase Scope, while draft itd-43 is scoped into Phase 0/1 yet listed later-phase. ADR-bound.
- iss-80Record id allocators (itd-N, spc-N, iss-N) are branch-local: parallel agents on separate branches each scan for max+1 and mint the SAME id. Two intents both claimed itd-82 and both merged to main (PRs #46, #47). The iss-N allocator hit the same class before (iss-77 collision, manually renumbered to iss-79; class recorded as iss-74). Resolving a collision forces a renumber, which breaks the record's stated 'ids are capture-stable, never renumbered' invariant -- so the minting scheme, not the renumber, is the defect. This capture is the MINTING half: a collision-free allocation scheme is needed (forge-minted / random-suffix / timestamp / reserve-registry -- SOTA under research). The DETECTION half is armed separately: intent_lifecycle now blocks duplicate intent ids.
- iss-330Parallel-mint id collision observed live: the maintainer's bughunt session and the release session each minted iss-291..293 concurrently; the collision surfaced only at the merge-queue's record-lint on the second branch, costing a full release re-cut. Direct field evidence for itd-114 (collision-proof record ids) — the ledger's next-free-integer mint is unsafe under exactly the parallel-agent workflows the repo now runs daily
- iss-344Parallel hunts capture the same defect twice: iss-306 (hunt A round 1, landed late) and iss-339 (hunt B round 2) record the identical githubRemoteRe case-sensitivity bug, minted independently on unmerged branches invisible to each other. Collision-proof ids (itd-114) do not solve this class — it is the semantic sibling of the id collision, sharing the root cause that parallel minters cannot see each other's unmerged mints. Candidate rungs: a capture-time similarity check (itd-84's validator rung), hunt briefings that read open PRs' ledgers, or a shared mint registry as a side effect of itd-114's forge-backed option
- iss-371The persona_registry lint checks names, not roles: itd-114 shipped 'Bob, a maintainer' (Bob is registered staff engineer; the maintainer role is Kira's) and itd-115 has 'Carol, a facilitator' (Nia's role) — both passed lint. The selection-by-role rule (personas.json, itd-79) has no detector for role-name agreement
- iss-374The hand-maintained ADR index lists adr-44 as proposed but the record frontmatter is accepted; the index drifted after status was flipped without updating the index
- 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-2608210737264758The optional forge-backed allocator (itd-114 ac-5) is deferred by recorded ruling — spc-33 names it a later adapter behind the same mint seam, adr-45 ruling 4 fixes its posture (allocates and never stores per itd-129's ledger-canonical line; offline falls back to native loudly) — but no open work item holds the seat, so nothing tracks building it. The fidelity verdict on itd-114 carries the criterion as NOT_MET/deferred-by-ruling; this capture is the deferred work's ledger seat, builds on itd-129's adapter seam when that lands
- iss-2608210737265820intent audit ingest appends the INGESTED verdict block at end-of-file, so when a shipped intent carries link-reference definitions after its Audit Notes heading (itd-114: the iss-80 link ref) the block lands below them — rendering fine but visually detached from the Audit Notes section it belongs to. The writer should insert under the Audit Notes heading (or above trailing link-ref definitions) rather than appending at EOF
- iss-2608210737265933Two accepted mint residuals recorded so future hunts do not rediscover them as findings (spc-33 bounds-and-residuals section; surfaced by the pre-PR security review of the itd-114 delivery): (1) recordid's fileID rebuilds an id from the parsed integer, so a timestamp stamp with a leading zero — reachable only from a host clock in 2000-2009 or from 2100 onward — resolves to a different id than its filename claims (the year-2100 horizon the spec accepts); (2) the mint's rejection-sampling loop is uncapped, safe today because entropy is crypto/rand or an injected test reader that EOFs, but if Minter.Entropy ever becomes configurable from env/config/flags the loop needs an iteration cap. Neither has an attack path under the current wiring
- iss-2608210923436594User-local agent memory is an unarmed, non-portable convention store: several working conventions (attribution footer handling, cloud-routine git identity, citation integrity) live only in one developer's per-project memory, so abcd works here partly because that memory compensates — and none of it travels to other users' managed repos. abcd already owns the portable homes (the bundled rules domains, .abcd/development/principles/, the per-project .abcd/memory/ substrate, validators); what is missing is the deliberate graduation loop: a convention that appears twice in local memory is a candidate for a rules-domain line, a principle, or a validator, and nothing currently prompts that promotion. Same shape as the itd-114 lesson — safety must live in the tool, not in every minter's prompt or any one user's memory
- iss-2608210923437502The bundled COMMITTING rules domain (the defaults every managed repo inherits from the binary) says Assisted-by-not-Co-Authored-By but omits the two attribution failures that keep recurring operationally and are currently patched by per-agent memory and per-routine prompt text: (1) the harness auto-appends a Generated-by footer plus session link to PR bodies and issue comments it creates — the domain should instruct the post-write read-back-and-strip (iss-178 remedy a, as an injected rule rather than every routine prompt re-carrying it); (2) autonomous runs default their git identity to the tool, which the attribution gate rejects (iss-193's class) — the domain should name the commit-as-the-human requirement. Prevention rung, complementing iss-178's detection remedy b; prompt-carried and memory-carried safety is the anti-pattern itd-114 just retired for minting
- iss-2608211143185943README.md described abcd capture as minting records 'with the next free id' — the proper name of the max+1 allocation protocol that adr-45/spc-33/itd-114 abolished after live collisions (one costing a release re-cut). 'Next free id' is the codebase's own name for the retired mechanism (recordid.MaxAcrossRefs, lint.go). The README is the only public document still describing it, setting the wrong mental model (small sequential successor-comparable ids) and legitimising the hand-add-at-max+1 path iss-74 identified as a collision source. Written 2026-08-17, pre-rollout.
- iss-2608211144555085The ADR index (.abcd/development/decisions/adrs/README.md) ends at the adr-44 row while adr-45 is accepted (2026-08-20) and cited as settled law by six live records (the invariants brief, itd-114, spc-33, .abcd/work/issues/README.md, two open issues, DECISIONS.md). 37 ADR files vs 36 index rows — exactly one missing. The index is the declared hand-maintained roll-call (adrs/README.md) and is not among index_drift's four registered indexes, so it is structurally ungated. Third recurrence of this class in the same table (after resolved iss-296 and iss-374), which iss-38's decision (hand-kept indexes must be deleted or gated) predicts.
- iss-2608300108376943A bundle of intents cannot share one spec through the ceremony: a spec's intent back-link is a single itd-N, intent link refuses a spec that names a different intent, and spec close refuses a disagreeing link, so the bundle-member kind (itd-114 vocabulary) has no shared-spec path. Ruling (13) of the cold-reading workstream binds the instrument trio (itd-183, itd-184, itd-185) as one bundle with a shared spec; the planning session stamps bundle-member and plans three specs written as one cross-linked design instead, logged as an improvisation. Either the spec back-link becomes a list, or the bundle kind's contract states that members carry sibling specs.
- iss-2609251451432601intent audit ingest: the first ingest, and any replacement, deletes trailing link-reference definitions under Audit Notes when the owed stub sits above them (the itd-114 shape appendToAuditNotes parks a stub above, per iss-2608210737265820). Same root cause as the unbounded review-block extent; same fix (a bounded extent). No record in the tree has a stub followed by refs today.
- iss-2610021502084298No check meets the retired role word in an intent's press release at the record: the docs-lint rule roles/retired-role-word roots at the docs, the command pages and the rules, so a shipped or planned intent's press release carrying it is refused only when the site composer renders it as the landing page's hero quote, which is how itd-60's first MET audit broke the site-render gate (iss-2610021446271464). After the R5 reword of itd-60, thirteen shipped press releases still carry the word (itd-65, itd-66, itd-67, itd-69, itd-73, itd-74, itd-93, itd-102, itd-111, itd-114, itd-125, itd-2609111003026787, itd-2609212137129937), so the next MET audit ingested for any of them refuses the render again on a branch that only recorded an audit; the product thinker's ruling R5 (2026-10-02) accepted that a future slip breaks the build and did not ask for this check. Related to iss-2610020731591808, which names the brief, the principles and the personas registry as swept but unguarded.
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Them
- itd-84An Intent Is Decomposed Before It Is Filed, And A Reversal Is Only Ever Flagged
- itd-115A Ready PR Merges Without Ever Wedging BEHIND
- itd-129Forge mirror as an opt-in adapter: the ledger mirrors out to forge issues one way, the forge id lives in the record schema, closures without import self-heal, and the whole surface is loudly absent without forge auth