board-jsonl-new-row-id-collides-with-complete-row
Solution written to ~/boardid-work/SOLUTION.md (self-contained, with the full boardid.py tool embedded as an appendix). The verified tool lives at ~/boardid-work/boardid.py.
The tick computed the next id from the open/pending row set (max open = H3-GAP-084 → 085) instead of from all rows. A complete row H3-GAP-085 (commit 6e0c4bb, filed by a stand-in PM lane) already held that id, so the appended row collided. The pre-read dupe scan only compared rows loaded for the open set, so it couldn't see the collision it was creating. Two invariants broke: allocation must use max(suffix over ALL statuses)+1, and the candidate must be grepped in the whole file immediately before writing.
id -> [line, status], count duplicates.H3-GAP-086.id substitution.git diff --numstat.### DETECT
H3-GAP-085 -> [(3, 'complete'), (4, 'open')]
!! DUPLICATE IDS (alarm) !!
### ALLOCATE
H3-GAP-086
### REPAIR
row re-id: line 4: H3-GAP-085 -> H3-GAP-086
ref re-id: notes/closure-A.md:2: H3-GAP-085 -> H3-GAP-086
ref re-id: notes/closure-B.md:2: H3-GAP-085 -> H3-GAP-086
### PROVE
total lines : 6
changed lines : [4]
byte-identical lines : 5
duplicate-id count : 1 -> {'H3-QA-3': [5, 6]} # only the benign per-cycle slot
new id occurrences : [4]
git diff --numstat : 1 1 board/tasks.jsonl
Also verified: the ambiguous-reference case (>1 occurrence on a line) is refused and leaves the board byte-identical, and re-iding onto an already-taken id is refused. The document records the original incident's post-repair reading of 194 rows / 193 unique ids with the corrected H3-GAP-086 in the two closure rows.
# Evidence - Problem class: board-jsonl-new-row-id-collides-with-complete-row - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-18T18:27:24.845Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a foreman tick appended a NEW board row and gave it the next free id in its family, computed from the OPEN rows it had just scanned. The id was in fact already taken by a COMPLETE row from another lane (a stand-in PM lane had filed+closed it earlier the same day), so the board silently held TWO rows with the same id and two different findings - exactly the id-reuse class that costs later ticks a whole repair task (PM-audit rows complaining that one id carries two findings).\n\nROOT CAUSE: id availability was inferred from the open/pending row set instead of from ALL rows. Complete rows keep their ids forever on a JSONL board; a family's max id is therefore set by the highest-numbered row of ANY status, not by the highest-numbered open one. The tick's pre-read dupe scan also only reported duplicates among rows it had already loaded for the open set, so it could not see the collision it was about to create.\n\nFIX (the recovery - the collision was caught and repaired in the same tick):\n1. Detect: parse EVERY line of tasks.jsonl, count ids, and print (id -> [line, status]) for the whole file. A '2 rows with the same id' count is the alarm, not a grep of the open set. grep -c '\"id\":\"<ID>\"' is enough when you already suspect one id.\n2. Re-id the NEW row, never the pre-existing one (the older row's commit_hash and the audit events that reference it are already published evidence). Pick the next free id by scanning all rows of the family for the max numeric suffix, then +1 (here H3-GAP-085 was taken by a complete row, so the new row became H3-GAP-086).\n3. Repair the references, not just the row: the new row's id had already been written into two closure notes committed in the same tick. Rewrite ONLY the affected lines (a targeted per-line string replace with an occurrence count assertion - refuse a blanket replace when the target line holds more than one occurrence) and leave every other line byte-identical from the CURRENT working file, never from HEAD (HEAD would revert another writer's in-flight row update).\n4. Prove the repair arithmetically: changed-line list == the intended line numbers, all other lines byte-identical count == total lines - changed lines, duplicate-id count back to the known benign set (per-cycle QA/DF slots), and git diff --numstat matches (3/2 for three changed lines where two existed before).\n\nPREVENTION: allocate a new row id from a full-file scan of the family (all statuses) and grep the WHOLE file for the candidate id (not the open set) immediately before writing; do the same for an id you are about to mention in a closure note. On boards with several writers (foreman lanes + stand-in PM lanes), re-parse the file at write time rather than trusting a row list read minutes earlier.\n\nVERIFICATION: after the repair the board read 194 rows / 193 unique ids (the single remaining duplicate being the known intentional per-cycle QA-H3-3 slot), the two closure rows carried the corrected id, and the appended row parsed with the new id.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "board-jsonl-new-row-id-collides-with-complete-row", "provider": "openrouter", "solved_at": "2026-09-18T18:27:24.849Z", "version": ""}Solution written to ~/boardid-work/SOLUTION.md (self-contained, with the full boardid.py tool embedded as an appendix). The verified tool lives at ~/boardid-work/boardid.py.
The tick computed the next id from the open/pending row set (max open = H3-GAP-084 → 085) instead of from all rows. A complete row H3-GAP-085 (commit 6e0c4bb, filed by a stand-in PM lane) already held that id, so the appended row collided. The pre-read dupe scan only compared rows loaded for the open set, so it couldn't see the collision it was creating. Two invariants broke: allocation must use max(suffix over ALL statuses)+1, and the candidate must be grepped in the whole file immediately before writing.
id -> [line, status], count duplicates.H3-GAP-086.id substitution.git diff --numstat.### DETECT
H3-GAP-085 -> [(3, 'complete'), (4, 'open')]
!! DUPLICATE IDS (alarm) !!
### ALLOCATE
H3-GAP-086
### REPAIR
row re-id: line 4: H3-GAP-085 -> H3-GAP-086
ref re-id: notes/closure-A.md:2: H3-GAP-085 -> H3-GAP-086
ref re-id: notes/closure-B.md:2: H3-GAP-085 -> H3-GAP-086
### PROVE
total lines : 6
changed lines : [4]
byte-identical lines : 5
duplicate-id count : 1 -> {'H3-QA-3': [5, 6]} # only the benign per-cycle slot
new id occurrences : [4]
git diff --numstat : 1 1 board/tasks.jsonl
Also verified: the ambiguous-reference case (>1 occurrence on a line) is refused and leaves the board byte-identical, and re-iding onto an already-taken id is refused. The document records the original incident's post-repair reading of 194 rows / 193 unique ids with the corrected H3-GAP-086 in the two closure rows.
# Evidence - Problem class: board-jsonl-new-row-id-collides-with-complete-row - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-18T18:27:24.845Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "SYMPTOM: a foreman tick appended a NEW board row and gave it the next free id in its family, computed from the OPEN rows it had just scanned. The id was in fact already taken by a COMPLETE row from another lane (a stand-in PM lane had filed+closed it earlier the same day), so the board silently held TWO rows with the same id and two different findings - exactly the id-reuse class that costs later ticks a whole repair task (PM-audit rows complaining that one id carries two findings).\n\nROOT CAUSE: id availability was inferred from the open/pending row set instead of from ALL rows. Complete rows keep their ids forever on a JSONL board; a family's max id is therefore set by the highest-numbered row of ANY status, not by the highest-numbered open one. The tick's pre-read dupe scan also only reported duplicates among rows it had already loaded for the open set, so it could not see the collision it was about to create.\n\nFIX (the recovery - the collision was caught and repaired in the same tick):\n1. Detect: parse EVERY line of tasks.jsonl, count ids, and print (id -> [line, status]) for the whole file. A '2 rows with the same id' count is the alarm, not a grep of the open set. grep -c '\"id\":\"<ID>\"' is enough when you already suspect one id.\n2. Re-id the NEW row, never the pre-existing one (the older row's commit_hash and the audit events that reference it are already published evidence). Pick the next free id by scanning all rows of the family for the max numeric suffix, then +1 (here H3-GAP-085 was taken by a complete row, so the new row became H3-GAP-086).\n3. Repair the references, not just the row: the new row's id had already been written into two closure notes committed in the same tick. Rewrite ONLY the affected lines (a targeted per-line string replace with an occurrence count assertion - refuse a blanket replace when the target line holds more than one occurrence) and leave every other line byte-identical from the CURRENT working file, never from HEAD (HEAD would revert another writer's in-flight row update).\n4. Prove the repair arithmetically: changed-line list == the intended line numbers, all other lines byte-identical count == total lines - changed lines, duplicate-id count back to the known benign set (per-cycle QA/DF slots), and git diff --numstat matches (3/2 for three changed lines where two existed before).\n\nPREVENTION: allocate a new row id from a full-file scan of the family (all statuses) and grep the WHOLE file for the candidate id (not the open set) immediately before writing; do the same for an id you are about to mention in a closure note. On boards with several writers (foreman lanes + stand-in PM lanes), re-parse the file at write time rather than trusting a row list read minutes earlier.\n\nVERIFICATION: after the repair the board read 194 rows / 193 unique ids (the single remaining duplicate being the known intentional per-cycle QA-H3-3 slot), the two closure rows carried the corrected id, and the appended row parsed with the new id.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "board-jsonl-new-row-id-collides-with-complete-row", "provider": "openrouter", "solved_at": "2026-09-18T18:27:24.849Z", "version": ""}