Repository navigation
Description
Bug
docs-history (the mcpx compendium history / release-stamping tool, landed today in #3266 for #1865) panics with a Go runtime stack trace when a value-taking flag is the last argument of stamp or check.
Both subcommands parse flags with a hand-rolled loop that does i++; value = rest[i] with no bounds check:
pkgs/mcpx/tools/docs-history/main.go:1119-1127—stamp:--version,--date,--changes-dirpkgs/mcpx/tools/docs-history/main.go:1146-1153—check:--diff,--changes-dir
Evidence (verified this run)
Probe on the laptop (~/git/fleet/probe-2026-10-31-laneA-docshistory/): main.go copied verbatim from main 2cc551cd, sha256 12e1888103e770ed83476d6a65695f978e0c9cfa95e39915c54ba1948dec37b6 on both sides, built with Go 1.26.8.
Bug cases — every one panics:
$ docs-history stamp --version
panic: runtime error: index out of range [1] with length 1
goroutine 1 [running]: main.main() …
$ docs-history stamp --version 1.2.3 --date → panic: index out of range [3] with length 3
$ docs-history stamp --changes-dir → panic: index out of range [1] with length 1
$ docs-history check --diff → panic: index out of range [1] with length 1
$ docs-history check --changes-dir → panic: index out of range [1] with length 1
$ docs-history check doc.md --diff → panic: index out of range [2] with length 2
Controls — the tool's own intended behaviour for bad usage is a clean usage message:
$ docs-history stamp --version file.md → usage text, exit 2 (no panic)
$ docs-history check → usage text, exit 2
$ docs-history bogus-subcommand → usage text, exit 2
$ docs-history stamp --version 1.2.3 --date 2026-10-31 doc.md
→ exit 0; `since: unreleased` correctly rewritten to `since: 1.2.3`
Why it matters
stamp is the release step (docs/release-runbook.md) and check is a CI gate. A mistyped release command — a flag whose value was forgotten, or a shell variable that expanded to nothing — currently produces a runtime panic and stack trace instead of the usage text the tool already prints for every other usage error. In CI the panic output buries the actual mistake; at release time it looks like the tool itself is broken. The exit code happens to also be 2 (Go runtime), so scripts cannot distinguish a usage error from a crash by code alone.
Acceptance criteria
stamp/checkwith any value-taking flag (--version,--date,--changes-dir,--diff) as the final argument print the usage text (or a message naming the flag and its missing value) to stderr and exit 2 — no panic, no stack trace.- All currently-valid invocations behave exactly as before (valid stamp still stamps and exits 0; missing required values still usage + exit 2).
- A regression test covers each value-taking flag in trailing position for both subcommands (the existing
main_test.gosuite tests the library functions; the arg-parsing path inmain()needs coverage, e.g. by factoring the parse into a testable function or an exec-based test).
Related: #1865 (the tool's implementation issue). Distinct from the unrecognized-argument class filed for other scripts (#3264/#3278/#3281/#3287/#3296/#3297): those silently ignore unknown flags; this one crashes on a known flag missing its value.
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 1, 2026
Adopted as Phase 2 of design #3352 (corollary 3: a trailing value flag is a usage error — usage text + exit 2, the tool's own established behaviour, never a panic). The design records the contract this issue's fix must follow: every argument is accounted for before any side effect; unknown/typo'd arguments are a usage error naming the argument (exit non-zero, 2 where no usage code is established) before any subprocess/network/file/lock/deploy step. Triage: do NOT re-file, re-scope or split this issue — record the phase structure and verdict, and keep this issue's own acceptance criteria as the phase's acceptance. Design doc: files/designs/code-operator-argument-contract.md (keep-the-four-repos-healthy goal workspace).
19 remaining items
developing-today commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
opencodedezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
opencode; handed off to the laptop claimant (opencode-claimant), which launches the bound opencode session to drive task 8218 to its terminal state.dezren39 commentedon Nov 4, 2026
agent-note:v1
event: handed-off
task: 8218 (triage, repo-health-code-pilot; worker repo-worker-code; lane code-t)
by: repo-queue-worker lane T
Handed off to the opencode claimant (execution lane: opencode, lane-assignment row 1383). The claimant launches the bound session that drives task 8218 to its terminal state.
dezren39 commentedon Nov 4, 2026
agent-note:v1
task 8218 picked up by lane code-g; execution lane assigned opencode — handed off to the opencode claimant, which will launch the bound session and drive task 8218 to its terminal state. Issue #3312 verified OPEN with no hard-stop labels at handoff.
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off