jsonl-board-duplicate-id-close
Wrote the verified solution to ~/board-duplicate-id-fix.md.
Root cause: tasks.jsonl is a canonical state file (one row per id), but board_append.py used append-only semantics for closures. Closing DOC-3 appended a second DOC-3 row instead of replacing the first, so boardctl validate's duplicate-id check (run by the board-lint pre-commit hook) rejected the commit — 6 closure rows → 6 duplicate errors + 1 → FAIL (7 error(s)).
Fix (three parts):
1. Prevent — close tasks with the in-place upsert: boardctl update <id> --status complete ... --replace.
2. Patch board_append.py — add upsert_task() that drops the existing row before writing, with atomic temp-file + os.replace().
3. Repair an already-poisoned board — board_dedup.py collapses duplicates keeping the newest row per id, then re-lint.
boardctl[error] ... duplicate task id "DOC-3", RESULT: FAIL.boardctl update --replace on a clean board: row count unchanged, one DOC-3, RESULT: OK.board_dedup.py on poisoned board: 3 -> 2 rows, then RESULT: OK (0 warning(s)), census 2/2 rows carry only canon keys (0 drift).boardctl update --replace refuses on an already-duplicated id (... appears on multiple lines ... refusing ambiguous update) — dedup first.boardctl validate --repair does not deduplicate (kept all 3 rows) and never overwrites tasks.jsonl — it is not a fix for this class.The markdown is fully self-contained: repro commands, the patched helper, the board_dedup.py script, the repair runbook, and a prevention checklist.
# Evidence - Problem class: jsonl-board-duplicate-id-close - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-28T23:44:55.397Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Closing an existing board task id via board_append.py (append-row semantics) creates a duplicate-id row; the boardctl pre-commit board-lint hook then rejects the commit with duplicate task id errors mid-tick. Tick <project>-2026-09-28-23-21-41: 6 appended closure rows were all rejected; fixed by in-place rewrite.", "environment": "coding-hermes foreman tick, <project> repo, JSONL canonical board (.coding-hermes/board/tasks.jsonl) with boardctl pre-commit lint hook", "language": "jsonl", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "jsonl-board-duplicate-id-close", "provider": "openrouter", "solved_at": "2026-09-28T23:44:55.408Z", "version": ""}Wrote the verified solution to ~/board-duplicate-id-fix.md.
Root cause: tasks.jsonl is a canonical state file (one row per id), but board_append.py used append-only semantics for closures. Closing DOC-3 appended a second DOC-3 row instead of replacing the first, so boardctl validate's duplicate-id check (run by the board-lint pre-commit hook) rejected the commit — 6 closure rows → 6 duplicate errors + 1 → FAIL (7 error(s)).
Fix (three parts):
1. Prevent — close tasks with the in-place upsert: boardctl update <id> --status complete ... --replace.
2. Patch board_append.py — add upsert_task() that drops the existing row before writing, with atomic temp-file + os.replace().
3. Repair an already-poisoned board — board_dedup.py collapses duplicates keeping the newest row per id, then re-lint.
boardctl[error] ... duplicate task id "DOC-3", RESULT: FAIL.boardctl update --replace on a clean board: row count unchanged, one DOC-3, RESULT: OK.board_dedup.py on poisoned board: 3 -> 2 rows, then RESULT: OK (0 warning(s)), census 2/2 rows carry only canon keys (0 drift).boardctl update --replace refuses on an already-duplicated id (... appears on multiple lines ... refusing ambiguous update) — dedup first.boardctl validate --repair does not deduplicate (kept all 3 rows) and never overwrites tasks.jsonl — it is not a fix for this class.The markdown is fully self-contained: repro commands, the patched helper, the board_dedup.py script, the repair runbook, and a prevention checklist.
# Evidence - Problem class: jsonl-board-duplicate-id-close - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-28T23:44:55.397Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Closing an existing board task id via board_append.py (append-row semantics) creates a duplicate-id row; the boardctl pre-commit board-lint hook then rejects the commit with duplicate task id errors mid-tick. Tick <project>-2026-09-28-23-21-41: 6 appended closure rows were all rejected; fixed by in-place rewrite.", "environment": "coding-hermes foreman tick, <project> repo, JSONL canonical board (.coding-hermes/board/tasks.jsonl) with boardctl pre-commit lint hook", "language": "jsonl", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "jsonl-board-duplicate-id-close", "provider": "openrouter", "solved_at": "2026-09-28T23:44:55.408Z", "version": ""}