A nightwatch hardening release out of plan pl-7a81 (parent mulch-e7f6): strict regex parsing for --outcome-duration / --duration (#37), normalized fatal-error coloring across the remaining CLI sites (#38), file-path context in Claude settings.json parse errors (#39), and --json honored by the deprecated mulch update command (#40). No schema, hook, config, or public command surface changes. 1482 tests across 70 files / 3831 expect() calls (up from 1460 / 69 / 3778 in 0.10.4).
Added
src/utils/numeric-flags.ts(mulch-5b9c, #37): extractsparseStrictPositiveIntandparseStrictNonNegativeNumber— regex-gated parsers used byrecord/edit/outcomefor--outcome-duration/--duration. Mirrors the inline parsers already inready/prime/compact/rank(mx-5b9578) and is the first time the convention has been shared via a util module.
Fixed
--outcome-duration/--durationsilently accepted garbage input (mulch-5b9c, #37):record,edit, andoutcomeparsed these flags with bareNumber.parseFloat, so--outcome-duration 10abcwrote10and--duration 3.7xyzwrote3.7to.mulch/expertise/*.jsonl. They now go throughparseStrictNonNegativeNumberand reject anything that isn't a clean non-negative number with--<flag> must be a non-negative number (got "<raw>"), exit1, and write nothing.--jsonmode emits the standard error envelope on stderr.- Fatal-error stderr coloring was inconsistent (mulch-2a17, #38): the remaining plain
console.error("Error: …")sites inquery.ts,prime.ts,search.ts, and several other commands now wrap fatal messages inchalk.red(...), matching the convention used byrecord/sync/validate. No wording changes;--jsonerror envelopes are unchanged (chalk only applies to the human-readable branch). - Claude
settings.jsonparse errors lacked file-path context (mulch-1b36, #39): a corrupted.claude/settings.jsonused to surface as a bareUnexpected token …fromJSON.parse. The Claude recipe's install / check / remove now route through aparseClaudeSettings()helper that rethrows asFailed to parse Claude settings at <absolute-path>: <reason>, matching thefile:linecontext conventionreadExpertiseFilealready uses (mx-7c199c). mulch updateignored--json(mulch-a8cd, #40): the deprecatedupdatecommand always printed its yellow deprecation warning to stdout, breaking the JSON-output contract every other command honors. When--jsonis active it now emits{success:false, command:"update", error:…}to stderr viaoutputJsonErrorand exits1; the human-readable yellow warning is unchanged.
CI
- Pin
bun-versionin.github/workflows/ci.yml(#39):setup-bun@v2was readingengines.bun(>=1.0.0) and resolving the range via the GitHub tags API, which intermittently 404s and reds the job. Explicitbun-versionskips that range-resolution path.
Testing
- 1482 tests across 70 files, 3831 expect() calls (up from 1460 / 69 / 3778 in 0.10.4).
- New
test/utils/numeric-flags.test.tscovering both parsers' accept/reject boundaries. - New spawn-integration tests in
test/commands/record.test.ts,test/commands/edit.test.ts, andtest/commands/outcome.test.tsasserting (a) invalid--outcome-duration/--durationexits non-zero and writes no record/outcome, (b) valid inputs round-trip unchanged, (c)--jsonmode produces the standard error envelope on stderr. - New
test/commands/setup.test.tscases covering the wrapped Claudesettings.jsonparse error (path is present, originalSyntaxErrorreason is preserved). - New
test/commands/update.test.tscases for the deprecated command honoring--json.