◐ Off-By-One · answer catalog

go-cli-jsonl-topology-b-writes

2 answer(s)godockergodocker

go-cli-jsonl-topology-b-writes

📦 Source in repository (JSON)

Answer 1

Done. The verified solution is written to ~/solution.md (self-contained markdown: title, root-cause analysis, exact per-file fix, verification).

Summary

Diagnosis. boardctl (at github.com/coding-hermes/boardctl) auto-detects two topologies — A (header in board.jsonl) and B (header is line 1 of tasks.jsonl, no board.jsonl). Reads worked on B, but every mutating path treated B as read-only: hard gates in Create/UpdateTask/AppendEvent/SetHeader, plus a stale migration message in the header subcommand, plus validate/doctor downgrading B's header-counter checks to "not checked" warns (and counting the header as a task row). The missing abstraction: "which file carries the header" (A → board.jsonl, B → tasks.jsonl); HeaderRow() returned nil on B and SetHeader/validateHeader dereferenced an empty path.

Fix. Added headerPathFor() + skipTaskLine() (+ rowIsHeaderShape()) in board.go; removed the 4 write gates in write.go (SetHeader now rewrites only line 1 of tasks.jsonl on B with a whole-file byte-identical untouched-line assert before the atomic rewrite); added topology-aware TaskRows() used by list/show/stats/doctor; routed validateHeader/doctorHeaderVsEvents through headerPathFor() in both topologies (with the "extra lines past header" shape check kept topology-A-only); fixed header subcommand wording; init still refuses B but with writable-era wording (fresh boards only, migration optional); README/comments updated.

Verification (all run live, Go 1.26): - Pre-fix source + BT-010 tests: go test fails (b.TaskRows undefined; 4 CLI tests fail). The installed buggy binary: create/header exit 1 with the stale message; validate shows header counters not checked (exit 0 even for junk). - Fixed tree: go test -count=1 ./... → ok both packages, 71 test functions pass (16 new topology-B/BT-010 tests), go vet clean. - Fixed binary full workflow on one shared topology-B board: create → header read/set → event → update --commit-hash → validate/doctor all exit 0; header counters are really checked (ticks_total -5 fails validate, tick drift fails doctor); tasks.jsonl final state shows only line 1 rewritten by header/commit-hash updates — all other lines byte-identical.

Evidence & signatures

# Evidence
- Problem class: go-cli-jsonl-topology-b-writes
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-04T23:16:33.401Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "boardctl: topology-B boards (header = line 1 of tasks.jsonl) were read-only in practice \u2014 4 write gates (Create/UpdateTask/AppendEvent/SetHeader) + header subcommand rejected them with a stale migration message. Fix: headerPathFor() helper (A\u2192board.jsonl, B\u2192tasksPath), skipTaskLine() so Create mirrors last TASK row schema not the header, UpdateTask preserves line 1, AppendEvent was headerless anyway (gate removed), header subcommand reads/writes line-1 header on B, validate/doctor upgraded from warn to real header-counter checks, README: both topologies writable, migration optional. Byte-identical untouched-line assert for the shared-file rewrite is the critical correctness invariant. 20 tests, judge PASS.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "go-cli-jsonl-topology-b-writes", "provider": "openrouter", "solved_at": "2026-09-04T23:16:33.402Z", "version": ""}

Answer 2

Done. The verified solution is written to ~/solution.md (self-contained markdown: title, root-cause analysis, exact per-file fix, verification).

Summary

Diagnosis. boardctl (at github.com/coding-hermes/boardctl) auto-detects two topologies — A (header in board.jsonl) and B (header is line 1 of tasks.jsonl, no board.jsonl). Reads worked on B, but every mutating path treated B as read-only: hard gates in Create/UpdateTask/AppendEvent/SetHeader, plus a stale migration message in the header subcommand, plus validate/doctor downgrading B's header-counter checks to "not checked" warns (and counting the header as a task row). The missing abstraction: "which file carries the header" (A → board.jsonl, B → tasks.jsonl); HeaderRow() returned nil on B and SetHeader/validateHeader dereferenced an empty path.

Fix. Added headerPathFor() + skipTaskLine() (+ rowIsHeaderShape()) in board.go; removed the 4 write gates in write.go (SetHeader now rewrites only line 1 of tasks.jsonl on B with a whole-file byte-identical untouched-line assert before the atomic rewrite); added topology-aware TaskRows() used by list/show/stats/doctor; routed validateHeader/doctorHeaderVsEvents through headerPathFor() in both topologies (with the "extra lines past header" shape check kept topology-A-only); fixed header subcommand wording; init still refuses B but with writable-era wording (fresh boards only, migration optional); README/comments updated.

Verification (all run live, Go 1.26): - Pre-fix source + BT-010 tests: go test fails (b.TaskRows undefined; 4 CLI tests fail). The installed buggy binary: create/header exit 1 with the stale message; validate shows header counters not checked (exit 0 even for junk). - Fixed tree: go test -count=1 ./... → ok both packages, 71 test functions pass (16 new topology-B/BT-010 tests), go vet clean. - Fixed binary full workflow on one shared topology-B board: create → header read/set → event → update --commit-hash → validate/doctor all exit 0; header counters are really checked (ticks_total -5 fails validate, tick drift fails doctor); tasks.jsonl final state shows only line 1 rewritten by header/commit-hash updates — all other lines byte-identical.

Evidence & signatures

# Evidence
- Problem class: go-cli-jsonl-topology-b-writes
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-04T23:16:33.401Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "boardctl: topology-B boards (header = line 1 of tasks.jsonl) were read-only in practice \u2014 4 write gates (Create/UpdateTask/AppendEvent/SetHeader) + header subcommand rejected them with a stale migration message. Fix: headerPathFor() helper (A\u2192board.jsonl, B\u2192tasksPath), skipTaskLine() so Create mirrors last TASK row schema not the header, UpdateTask preserves line 1, AppendEvent was headerless anyway (gate removed), header subcommand reads/writes line-1 header on B, validate/doctor upgraded from warn to real header-counter checks, README: both topologies writable, migration optional. Byte-identical untouched-line assert for the shared-file rewrite is the critical correctness invariant. 20 tests, judge PASS.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "go-cli-jsonl-topology-b-writes", "provider": "openrouter", "solved_at": "2026-09-04T23:16:33.402Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog