go-cli-id-format-validation
Diagnosis complete and verified. The full solution is written to ~/solution.md. Summary of what I did:
~/.local/bin/boardctl, built at 25dc442): create --id "bad id!" exited 0, appended a row + task_created event, and validate/doctor stayed silent.<email>:coding-hermes/boardctl, commit ecf5653): a compiled FleetTaskIDPattern enforced in Create() before any write and in UpdateTask() post-lookup, with a --force escape hatch and a warn-only doctor check.go test ./... green), running the full temp-board E2E (junk reject exit 1 + zero writes, --force exit 0, doctor warn exit 0, validate 0 errors, update gated), and RED-proving the matcher by disabling it.The document above (also at ~/solution.md) contains the title, root-cause analysis, exact code for all six change sites, the NEVER-DONE pitfall note, and the verification transcript.
# Evidence - Problem class: go-cli-id-format-validation - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-12T18:54:55.486Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Fleet board tool boardctl accepted any --id string: create --id \"bad id!\" exited 0 and wrote the row plus a task_created event while validate/doctor stayed silent, so junk ids could wedge downstream id-parsing consumers (task-router, board-scan keep-LAST dedupe). Fix: a fleet id pattern ^[A-Z][A-Z0-9]+(-[A-Z0-9]+)+$ compiled once in the board package next to the status/priority vocabularies, validated in Create() BEFORE any write (nothing is appended on reject) and in UpdateTask() for the target id post-lookup so legacy rows stay editable; a --force flag on both subcommands is the escape hatch; doctor itemizes legacy junk ids as warnings with tasks.jsonl line numbers (never errors \u2014 HasErrors untouched, so legacy boards still pass doctor); validate deliberately stays silent. Pitfall found while verifying: init ships the NEVER-DONE perpetual fixture row into tasks.jsonl, so re-creating NEVER-DONE exits 1 with an \"already exists\" error, NOT a format error \u2014 do not mistake it for a false rejection. Verification: temp-board E2E (junk id exit 1 + zero writes, --force exit 0, doctor warn exit 0, validate 0 errors, update gated by --force) plus 11 new Go tests, one of which was RED-proven by disabling the matcher.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-cli-id-format-validation", "provider": "openrouter", "solved_at": "2026-09-12T18:54:55.487Z", "version": ""}Diagnosis complete and verified. The full solution is written to ~/solution.md. Summary of what I did:
~/.local/bin/boardctl, built at 25dc442): create --id "bad id!" exited 0, appended a row + task_created event, and validate/doctor stayed silent.<email>:coding-hermes/boardctl, commit ecf5653): a compiled FleetTaskIDPattern enforced in Create() before any write and in UpdateTask() post-lookup, with a --force escape hatch and a warn-only doctor check.go test ./... green), running the full temp-board E2E (junk reject exit 1 + zero writes, --force exit 0, doctor warn exit 0, validate 0 errors, update gated), and RED-proving the matcher by disabling it.The document above (also at ~/solution.md) contains the title, root-cause analysis, exact code for all six change sites, the NEVER-DONE pitfall note, and the verification transcript.
# Evidence - Problem class: go-cli-id-format-validation - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-12T18:54:55.486Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Fleet board tool boardctl accepted any --id string: create --id \"bad id!\" exited 0 and wrote the row plus a task_created event while validate/doctor stayed silent, so junk ids could wedge downstream id-parsing consumers (task-router, board-scan keep-LAST dedupe). Fix: a fleet id pattern ^[A-Z][A-Z0-9]+(-[A-Z0-9]+)+$ compiled once in the board package next to the status/priority vocabularies, validated in Create() BEFORE any write (nothing is appended on reject) and in UpdateTask() for the target id post-lookup so legacy rows stay editable; a --force flag on both subcommands is the escape hatch; doctor itemizes legacy junk ids as warnings with tasks.jsonl line numbers (never errors \u2014 HasErrors untouched, so legacy boards still pass doctor); validate deliberately stays silent. Pitfall found while verifying: init ships the NEVER-DONE perpetual fixture row into tasks.jsonl, so re-creating NEVER-DONE exits 1 with an \"already exists\" error, NOT a format error \u2014 do not mistake it for a false rejection. Verification: temp-board E2E (junk id exit 1 + zero writes, --force exit 0, doctor warn exit 0, validate 0 errors, update gated by --force) plus 11 new Go tests, one of which was RED-proven by disabling the matcher.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-cli-id-format-validation", "provider": "openrouter", "solved_at": "2026-09-12T18:54:55.487Z", "version": ""}