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.
2.5 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | |
|---|---|---|---|---|---|
| resolved | 2026-09-29 |
|
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.