board-hygiene-count-pinning
Solution written to ~/board-hygiene-count-pinning.md.
Root cause. A count like "six of 188 rows" is a point-in-time measurement stored as present-tense prose. The board stores the output but not the query or the instant. On an umbrella board the denominator is monotonically growing (sibling repos keep landing commit_repo rows), so every embedded count is guaranteed to age. Every underlying claim stays true, so review never catches it. The obvious "load JSON → patch → dump" fix has its own trap: a serializer-style mismatch reformatted 6323 lines in the first attempt.
Fix. Anchor every count, and when it is provenance, name the current value so growth reads as growth:
- six of 188 rows (at 838fd8c) — provenance only
- six of 188 rows (at 838fd8c; current: 7 of 195) — provenance + visible growth
- bare counts fail CI via --check
The included pin_counts.py auto-detects the file's own JSON style by brute-forcing (indent, ensure_ascii, separators, trailing_newline) until a round-trip is byte-exact, and hard-aborts otherwise — so a whole-file rewrite is impossible until proven safe.
Verified against a 188-row umbrella-board fixture with the exact embedded script:
- style proved indent=2, ensure_ascii=False, separators=None, newline="\n" before writing
- git diff --numstat → 3 3 board.json (only the 3 intended lines)
- byte-identical-others: all non-target files unchanged
- idempotent: second run pins 0
- reformat guard: hand-formatted JSON aborts with exit 1 and the file is untouched
- CI gate: FAIL: 3 unpinned (exit 1) → after apply → OK: all count phrases pinned (exit 0)
- the exact Python block extracted from the markdown re-runs correctly
# Evidence - Problem class: board-hygiene-count-pinning - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-20T01:54:57.838Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Closure notes and PM-ledger titles that quote a COUNT (six of 188 rows; 172 rows/151 unique ids) age silently: the number was true at write time, later legitimate work grows it, and the note reads as a lie while every claim in it stays true. Fix: pin the count to its measurement commit (at 838fd8c: six of 188) or recompute at close; when the count is provenance, pin the commit AND name the current value so growth is visible as growth. On an umbrella board the class is guaranteed because sibling repos keep landing commit_repo rows. Edit discipline: per-line json.loads/dumps preserving the file own style; prove with git diff --numstat and byte-identical-others count. For large pretty-printed JSON stores, first prove a full round-trip serialization is byte-exact (indent/ensure_ascii sweep) before a whole-file rewrite - a style mismatch reformatted 6323 lines in the first attempt and had to be reverted from a pre-edit copy.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "board-hygiene-count-pinning", "provider": "openrouter", "solved_at": "2026-09-20T01:54:57.838Z", "version": ""}Solution written to ~/board-hygiene-count-pinning.md.
Root cause. A count like "six of 188 rows" is a point-in-time measurement stored as present-tense prose. The board stores the output but not the query or the instant. On an umbrella board the denominator is monotonically growing (sibling repos keep landing commit_repo rows), so every embedded count is guaranteed to age. Every underlying claim stays true, so review never catches it. The obvious "load JSON → patch → dump" fix has its own trap: a serializer-style mismatch reformatted 6323 lines in the first attempt.
Fix. Anchor every count, and when it is provenance, name the current value so growth reads as growth:
- six of 188 rows (at 838fd8c) — provenance only
- six of 188 rows (at 838fd8c; current: 7 of 195) — provenance + visible growth
- bare counts fail CI via --check
The included pin_counts.py auto-detects the file's own JSON style by brute-forcing (indent, ensure_ascii, separators, trailing_newline) until a round-trip is byte-exact, and hard-aborts otherwise — so a whole-file rewrite is impossible until proven safe.
Verified against a 188-row umbrella-board fixture with the exact embedded script:
- style proved indent=2, ensure_ascii=False, separators=None, newline="\n" before writing
- git diff --numstat → 3 3 board.json (only the 3 intended lines)
- byte-identical-others: all non-target files unchanged
- idempotent: second run pins 0
- reformat guard: hand-formatted JSON aborts with exit 1 and the file is untouched
- CI gate: FAIL: 3 unpinned (exit 1) → after apply → OK: all count phrases pinned (exit 0)
- the exact Python block extracted from the markdown re-runs correctly
# Evidence - Problem class: board-hygiene-count-pinning - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-20T01:54:57.838Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Closure notes and PM-ledger titles that quote a COUNT (six of 188 rows; 172 rows/151 unique ids) age silently: the number was true at write time, later legitimate work grows it, and the note reads as a lie while every claim in it stays true. Fix: pin the count to its measurement commit (at 838fd8c: six of 188) or recompute at close; when the count is provenance, pin the commit AND name the current value so growth is visible as growth. On an umbrella board the class is guaranteed because sibling repos keep landing commit_repo rows. Edit discipline: per-line json.loads/dumps preserving the file own style; prove with git diff --numstat and byte-identical-others count. For large pretty-printed JSON stores, first prove a full round-trip serialization is byte-exact (indent/ensure_ascii sweep) before a whole-file rewrite - a style mismatch reformatted 6323 lines in the first attempt and had to be reverted from a pre-edit copy.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "board-hygiene-count-pinning", "provider": "openrouter", "solved_at": "2026-09-20T01:54:57.838Z", "version": ""}