Development record
Duplicate iss-56 id: two open issues share id iss-56 — iss-56-iss-36-lists-abcd-logbook-as-a-retired.md and iss-56-managed-pre-commit-gates.md. The allocator scans max N across open/resolved/wontfix under flock+O_EXCL, so a collision implies a manual add that bypassed it or an allocator gap. Ledger-integrity bug: derived priority, blocked_by edges, and resolve/wontfix by id are all ambiguous while two files answer to iss-56. Detector (per unrecognized-input-never-writes / ledger integrity): a capture/record-lint check that ids are unique across the three status dirs; acceptance corpus = the two iss-56 files. Fix: renumber the later-created one to the next free id and repoint any inbound blocked_by.
Duplicate iss-56 id: two open issues share id iss-56 — iss-56-iss-36-lists-abcd-logbook-as-a-retired.md and iss-56-managed-pre-commit-gates.md. The allocator scans max N across open/resolved/wontfix under flock+O_EXCL, so a collision implies a manual add that bypassed it or an allocator gap. Ledger-integrity bug: derived priority, blocked_by edges, and resolve/wontfix by id are all ambiguous while two files answer to iss-56. Detector (per unrecognized-input-never-writes / ledger integrity): a capture/record-lint check that ids are unique across the three status dirs; acceptance corpus = the two iss-56 files. Fix: renumber the later-created one to the next free id and repoint any inbound blocked_by.
Frontmatter
| id | iss-74 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-74-duplicate-iss-56-id.md
open on GitHub ↗ · commit history ↗
mentions6
- iss-36retired-name banlist population: roughly fifty stale references to retired locations and identifiers survive in the record, and the drift outlived a dedicated same-day consistency pass — development/activity (38 refs in the brief), .work/issues and bare .work/ as a root path (11 refs), scripts/abcd/, .abcd/logbook, .flow/, .github/workflows/lint.yml and lint-corpus.yml, --since-staged, and the python-lint-names pattern narrowly missing bare intent_lint (used by intents/README.md and adr-34). Detector (per retire-the-name and fix-the-detector): add each retired spelling to record-lint banned_tokens with allow_context for genuinely historical passages, widen the intent_lint pattern, then drain the references BEHIND the armed bans — never ahead of them. Acceptance corpus: the reference counts above; the bans are proven when they flag all ~50 on first run and the count ratchets to zero.
- iss-56iss-36 lists .abcd/logbook as a retired location, but the shipped binary writes there: memory lint reports go to .abcd/logbook/memory/ (internal/core/memory/lint.go) and the scanner skip-list references .abcd/logbook/pii-scan/. Adjudicate before any logbook ban is armed; the logbook token was deliberately left OUT of record-lint banned_tokens.
- 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-115There is no uniqueness lint for spec ids, so two concurrent branches always mint the same spc-N. abcd mints the next free id from the local tree, so any two branches cut from the same base collide silently: the itd-73/itd-67 programme and the itd-95/itd-96 programme both minted spc-10 and spc-11 on 2026-07-21. The collision is invisible on each branch and only appears on merge, where it breaks the bidirectional intent-spec link in BOTH directions at once — 'itd-95 names spc-10, but spc-10 claims itd-73' and 'itd-67 names spc-11, but spc-11 claims itd-96' — because whichever spec wins the store lookup leaves the other intent's link dangling. iss-74 added an issue-id uniqueness lint; specs need the same guard, and record-lint is the natural home so CI catches it on the PR rather than a human catching it at merge. Consider also whether minting should reserve ids in a way concurrent branches cannot duplicate.
- 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.
- workaround-records-the-defectWorkaround records the defect