Files
hq/04-ISSUES/155-two-records-may-share-a-number-and-nothing-says-so/00-report.md
T
jschoubben b967ef7be3 Two records shared a number, twice, and every check passed
Two machines filing issues in the same hour both read main correctly and
both took "the next free number". main lags every open pull request —
seven that evening — so they collided twice. The second collision
reached main with records, cycle and index all reporting success.

cycle.py now refuses a tree where two issue folders share a leading
number, and names both. Proven by adding a duplicate and watching it
fail. The colliding records become 153 and 154, renumbered in the branch
that lands last, because renumbering a branch whose author is still
pushing only moves the race.

The check catches a collision; it does not prevent one. Taking a number
still means reading the open pull requests as well as main — issue 155
says so.
2026-09-29 23:38:48 +02:00

2.5 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
resolved 2026-09-29
hq 00-META/checks/cycle.py
hq issue/two-records-share-a-number-and-nothing-says-so

155 — Two records may share a number, and every check passes

What was observed

On 2026-09-29 two machines opened issues against this repository within the same hour. Both read main correctly and both took "the next free number", and they collided twice:

one machine opened the other had already used
first 147, 148 147, 148 on an unmerged branch
second 149, 150 149 on an unmerged branch, 150 from renumbering the first collision

The first collision was reconciled by hand before merging. The second was merged into main, and records.py, cycle.py and index.py all reported success over a tree holding 149-a-declaration-that-shrinks-to-empty beside 149-an-adopted-machines-data-cannot-be-placed-where-it-is, and two folders numbered 150.

Why

The number is allocated as max(main) + 1, and main lags every open pull request — seven of them that evening. Two readers of the same main therefore compute the same next number, and neither is doing anything wrong. The existing reconciliation precedent (a second record numbered 127 became 149) assumed a single writer, which stopped being true when a second machine began filing its own findings.

Why it matters

An issue number is how every other record cites this one — fixed-by:, located-in:, a decision record's consequence, a commit message. Two records answering to one number is a citation that resolves to whichever folder the reader happened to open, and the failure is silent on both sides: the citer is not wrong, and the cited record exists.

It is also exactly the class this repository says it does not permit — a rule (00-META/process/03-issues.md: "take the next free number") enforced by nothing.

How it was fixed, and how the fix is checked

cycle.py now refuses a tree in which two issue folders share a leading number, and names both. Proven by adding a duplicate and watching it fail, then removing it and watching it pass.

The colliding records were renumbered 153 and 154, in the branch that landed last — renumbering a branch whose author is still pushing only moves the race.

The check catches the collision; it does not prevent it. Allocating a number still needs the open pull requests read as well as main. That is a habit the check now backstops rather than one it replaces.