Repository navigation
developer-experience: bare value-less CLI flags silently corrupt ledger/config state (issue #160) - #161
developer-experience: bare value-less CLI flags silently corrupt ledger/config state (issue #160)#161ruvnet wants to merge 2 commits into
Conversation
…er/config state (issue #160) parseArgs represents a value-less --flag as the boolean true, not a string. Nine call sites read an optional flag via `(flags.foo as string) || fallback`, where `true || fallback` is `true` -- the sentinel silently survives as if it were the user's value. Live-reproduced: `ledger append --date` (no value) wrote the literal cell "true" into LEDGER.md; `ledger verify --path` / `tui --path` (no value) silently reported an empty ledger as "OK"; `init --repo` (no value) baked "repo": true into the generated config. All four exited 0, no error. Adds `stringFlag()`, mirroring this file's own existing parseMergedPrNumbers/parseOpenCandidateCount/parseSinceRow/ parseLegacyDigest precedent (fallback on absence, throw on any non-string value), applied at every affected call site including freshness stamp --id, found by an independent critic subagent after the first pass missed it. 769+150 -> 784+150 tests (+15), 0 regressions. lint/typecheck clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MeVxH3JkwJ2ySWc8TsMu3T
Avoided literal | characters in the new row's text -- the finding describes a code pattern containing ||, which would have tripped the already-open, unfixed escapeCell/splitRow round-trip bug (issue #144 / PR #145) and corrupted the row's column count. Verified clean against CI's actual gate: `ledger verify --since-row 38 --legacy-digest ...` -> 51 rows OK. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MeVxH3JkwJ2ySWc8TsMu3T
|
CI:
This PR never touches Checked for an existing fix to port: open PR #159 (dependabot dev-dependency bump) does not touch Proposed patch (not applied in this PR, to avoid widening an unrelated-conceptual-change diff): Not re-run (this is a deterministic finding, not a flake) — will keep watching. Generated by Claude Code |
Nightly Dream Cycle, 2026-10-09. DEEP=developer-experience, SCAN=cli,tui. Full report:
docs/dream-cycle/2026-10-09-developer-experience-report.md. Issue: #160.Hypothesis (frozen before implementation)
Candidate
packages/cli/src/index.ts(+1 helper, 9 call sites converted):init --repo/--out,compile --out,schedule --out,ledger <sub> --path, all 10 ofledger append's string fields,tui --path, andfreshness stamp --id(added in a second pass after an independent critic caught the first-pass miss).packages/cli/src/index.test.ts: +15 regression tests, one per converted call site.Evaluation Receipt
Real evaluator:
npm test(vitest run && npm run test:governance).main@23a5770)npm run typechecknpm run lintLive pre/post-fix, all exit 0 → exit 1 with a clear usage error, no state written:
ledger append --date(no value) wrote the literal celltrueinto LEDGER.md pre-fix.ledger verify --path/tui --path(no value) silently reported a real, non-empty ledger as "✓ ledger OK — 0 rows" pre-fix.init --repo(no value) baked"repo": trueinto the generated config pre-fix.freshness stamp --id(no value) would have writtenpolicyId: truepre-fix.Baseline
Parent commit
23a577082aad39750051dc7ef0ec9d0d72900adf(main). Note: this session's checkout is shallow; the first baseline run showed 3 unrelated governance failures fromBASELINE_COMMITbeing unreachable (already-tracked issue #149 / open PR #150) — resolved locally withgit fetch --depth=200, no code change, before measuring the real 769+150 baseline above.Darwin Lineage
DARWIN=not-applicable— single validation-shape fix, no evolvable population, same judgment as #103/#122/#141.Evidence
OBSERVATION (grep + live repro ×4) → MEASUREMENT (769+150 → 784+150, 0 regressions) → INFERENCE (independent critic, separate subagent) → DECISION (one real scope miss found and fixed; one disclosed, not fixed) → DECISION (ACCEPT).
Reward-Hack Check
Independent adversarial critic (separate subagent, given only the diff, no authorship stake) returned APPROVE-WITH-FOLLOWUP: confirmed all repros genuine (reverted the fix, reproduced live) and genuinely fixed; confirmed the 15 new tests are non-tautological (fail on old code, pass on new); confirmed no gold/threshold/test-infra change; confirmed
--no-color/--help/--version/--report/--mergedcorrectly left untouched. It caught one real miss —freshness stamp --idused the identical unconverted pattern, mischaracterized by this candidate's first-pass "out of scope" writeup — fixed in a second pass, one more test added, full suite re-confirmed green. Its second finding (verify-entrypoint --cmd, a different pre-existing code shape) is a disclosed follow-up, not folded in.Security Review
Pure in-memory argument-validation logic. No new I/O/credential/network surface. Strictly more restrictive than before — can only newly reject previously-silently-wrong input, never newly accept something previously rejected.
Regression Analysis
0 pre-existing tests modified or removed. 15 new vitest tests added. Lint/typecheck/build clean.
ADR
None — a CLI argument-validation consistency fix, not an architectural decision.
Gist
GIST=LOCAL— noghCLI (invalidGH_TOKENthis session) or gist-creation MCP tool available. Full report committed atdocs/dream-cycle/2026-10-09-developer-experience-report.md.Issue
#160
Witness
Reproduce:
node packages/cli/dist/bin.js witness verify-report docs/dream-cycle/2026-10-09-developer-experience-report.md --commit 23a577082aad39750051dc7ef0ec9d0d72900adfMerge Policy
Human review required. This session never self-merges and never autonomously promotes candidate state.
dream.config.json'sautoMerge: false; noautomerge-safelabel applied.🤖 Generated with Claude Code
https://claude.ai/code/session_01MeVxH3JkwJ2ySWc8TsMu3T
Generated by Claude Code