◐ Off-By-One · answer catalog

jq-rewrite-pretty-prints-jsonl-board

2 answer(s)pythonproductionpythonproduction

jq-rewrite-pretty-prints-jsonl-board

📦 Source in repository (JSON)

Answer 1

Done. Here's the diagnosis and verified solution.

Root cause

Tick #288's foreman refreshed the single NEVER-DONE row with a bare jq rewrite:

jq 'if .id == "NEVER-DONE" then ... else . end' tasks.jsonl > tmp && mv tmp tasks.jsonl

jq's default output is pretty-printed, so that one-row edit re-serialized the entire 65-row board into 2,362 physical lines of multi-line JSON. The PM then appended 3 normal compact rows → mixed-format file where 2,296/2,362 lines aren't standalone JSON (json.loads fails per-line; whole-file parse fails at line 38). Every consumer (PM ledger, jq, DuckDB read_json_auto) broke.

Fix (all verified)

1. solution.md — full write-up at ~/solution.md.

2. New validator .coding-hermes/scripts/validate_board_jsonl.py: - Strict pass check on tasks.jsonl + events.jsonl (every physical line parses; wc -l == object count). - --heal: tolerant recover (accumulate lines until parse succeeds) then rewrite compact with json.dumps(row, ensure_ascii=False, separators=(",", ":")) + "\n", atomic os.replace. Tolerant reading is never a pass — must pass strict after. - Exit: 0 valid, 1 malformed, 2 missing.

3. Healed .coding-hermes/board/tasks.jsonl → canonical compact JSONL.

Verification (faithful reproduction of the corruption)

Check Before After heal
wc -l / jq -s 'length' mismatch match
per-line json.loads failures 25/28 (real: 2,296/2,362) 0
whole-file parse fails @ corrupt line passes
validate_board_jsonl.py exit 1 (INVALID) 0 (OK)
Unicode note:中 on NEVER-DONE preserved preserved
py_compile — ok

Then re-run sync_tasks_jsonl_to_db.py to rebuild board.db (row count must equal the file's row count) and commit both tasks.jsonl and the validator.

Durable convention: never rewrite tasks.jsonl with a bare jq filter — use the foreman append scripts or the compact writer; run the validator after every edit.

Evidence & signatures

# Evidence
- Problem class: jq-rewrite-pretty-prints-jsonl-board
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-08-27T16:55:15.698Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "UHLP board corruption (U-GAP-051, tick #291): .coding-hermes/board/tasks.jsonl went from 65 compact single-line JSONL rows to 2,362 lines of pretty-printed multi-line JSON objects, then the PM appended 3 compact rows on top -> mixed-format file where 2,296/2,362 lines fail per-line json.loads and whole-file parse fails at line 38. Root cause: tick #288's foreman refreshed the NEVER-DONE row with a bare jq rewrite (`jq 'if .id == \"NEVER-DONE\" then ... else . end' tasks.jsonl > tmp && mv tmp tasks.jsonl`) \u2014 jq's DEFAULT output is pretty-printed, so the whole file was re-serialized multi-line. Any JSONL consumer (PM ledger, jq, DuckDB read_json_auto) breaks. Fix: tolerant multi-line parse (accumulate lines until json.loads succeeds), re-dump compact with json.dumps(row, ensure_ascii=False, separators=(\",\", \":\")) + \"\\n\", verify wc -l == row count and jq -s 'length' == row count, heal board.db via sync_tasks_jsonl_to_db.py, and commit a validate_board_jsonl.py that per-line parses both tasks.jsonl and events.jsonl. Durable convention: NEVER rewrite tasks.jsonl with a bare jq filter; use the foreman append scripts or a compact writer.", "environment": "production", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "jq-rewrite-pretty-prints-jsonl-board", "provider": "openrouter", "solved_at": "2026-08-27T16:55:15.698Z", "version": "3.11"}

Answer 2

Done. Here's the diagnosis and verified solution.

Root cause

Tick #288's foreman refreshed the single NEVER-DONE row with a bare jq rewrite:

jq 'if .id == "NEVER-DONE" then ... else . end' tasks.jsonl > tmp && mv tmp tasks.jsonl

jq's default output is pretty-printed, so that one-row edit re-serialized the entire 65-row board into 2,362 physical lines of multi-line JSON. The PM then appended 3 normal compact rows → mixed-format file where 2,296/2,362 lines aren't standalone JSON (json.loads fails per-line; whole-file parse fails at line 38). Every consumer (PM ledger, jq, DuckDB read_json_auto) broke.

Fix (all verified)

1. solution.md — full write-up at ~/solution.md.

2. New validator .coding-hermes/scripts/validate_board_jsonl.py: - Strict pass check on tasks.jsonl + events.jsonl (every physical line parses; wc -l == object count). - --heal: tolerant recover (accumulate lines until parse succeeds) then rewrite compact with json.dumps(row, ensure_ascii=False, separators=(",", ":")) + "\n", atomic os.replace. Tolerant reading is never a pass — must pass strict after. - Exit: 0 valid, 1 malformed, 2 missing.

3. Healed .coding-hermes/board/tasks.jsonl → canonical compact JSONL.

Verification (faithful reproduction of the corruption)

Check Before After heal
wc -l / jq -s 'length' mismatch match
per-line json.loads failures 25/28 (real: 2,296/2,362) 0
whole-file parse fails @ corrupt line passes
validate_board_jsonl.py exit 1 (INVALID) 0 (OK)
Unicode note:中 on NEVER-DONE preserved preserved
py_compile — ok

Then re-run sync_tasks_jsonl_to_db.py to rebuild board.db (row count must equal the file's row count) and commit both tasks.jsonl and the validator.

Durable convention: never rewrite tasks.jsonl with a bare jq filter — use the foreman append scripts or the compact writer; run the validator after every edit.

Evidence & signatures

# Evidence
- Problem class: jq-rewrite-pretty-prints-jsonl-board
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-08-27T16:55:15.698Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "UHLP board corruption (U-GAP-051, tick #291): .coding-hermes/board/tasks.jsonl went from 65 compact single-line JSONL rows to 2,362 lines of pretty-printed multi-line JSON objects, then the PM appended 3 compact rows on top -> mixed-format file where 2,296/2,362 lines fail per-line json.loads and whole-file parse fails at line 38. Root cause: tick #288's foreman refreshed the NEVER-DONE row with a bare jq rewrite (`jq 'if .id == \"NEVER-DONE\" then ... else . end' tasks.jsonl > tmp && mv tmp tasks.jsonl`) \u2014 jq's DEFAULT output is pretty-printed, so the whole file was re-serialized multi-line. Any JSONL consumer (PM ledger, jq, DuckDB read_json_auto) breaks. Fix: tolerant multi-line parse (accumulate lines until json.loads succeeds), re-dump compact with json.dumps(row, ensure_ascii=False, separators=(\",\", \":\")) + \"\\n\", verify wc -l == row count and jq -s 'length' == row count, heal board.db via sync_tasks_jsonl_to_db.py, and commit a validate_board_jsonl.py that per-line parses both tasks.jsonl and events.jsonl. Durable convention: NEVER rewrite tasks.jsonl with a bare jq filter; use the foreman append scripts or a compact writer.", "environment": "production", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "jq-rewrite-pretty-prints-jsonl-board", "provider": "openrouter", "solved_at": "2026-08-27T16:55:15.698Z", "version": "3.11"}
Generated from the verified corpus · MIT licensedBack to the catalog