Defect r: a newline inside a quoted string was splitting bash commands, causing false blocks.
- Replaced regex split with a manual parser tracking single, double, and backtick quotes.
- Added support for heredocs (<<EOF ... EOF) so their bodies stay as single segments.
- All existing tests pass; added cases for multi-line node/python calls and heredocs.
Defect p: guardrails-replay writes synthetic config/boulder to a temp
directory (mkdtempSync) via new omoDir parameter, never under --directory.
Defect q: getStatBucket groups "bash_banned" and "bash_protected_port"
into "Always-Scope" table; all other rules into "(B) Scoped".
ruleId enrichment: every Error thrown by a guardrail rule now carries
err.ruleId (one of the 8 config IDs).
omoDir threading: Guardrails factory takes an omoDir param (defaults to
<directory>/.omo). loadConfig, readBoulder, _openLog, and all scope-gated
checks (checkWorktreeLine, checkWriteOutsideWorktree, checkBashMainCheckout,
checkPlanTickGate) thread a 'base' arg so they read artifacts from omoDir.
Cache invalidation: added _boulderBase and _configBase alongside _boulderDir
/_configDir. Cache key is (directory, base, mtime) to prevent stale reads
when omoDir differs across sessions.
Per-session scope in replay: Guardrails reads boulder.json once at factory
creation. Replay loop creates one factory per session, writing that session's
boulder to disk before instantiation.
Tests: 219 pass (guardrails.test 184 + guardrails-replay.test 5 +
guardrails.contract.test 30).
Defect o: When tests FAIL, the detail is at most 20 lines total.
- Fixed ERROR prefix: pytest prints 'ERROR ' (not 'ERRORS ')
- Truncation with '... and N more' when summary exceeds 20 lines
- Fallback (last 20 lines) unchanged
Defect n: check_lint now filters ruff output to only match real finding
lines (pattern: <path>:<line>:<col>: <CODE> <message>). Summary lines
like 'All checks passed!', 'Found N error(s).', and '[*] N fixable ...'
are ignored.
Defects fixed:
- (k) Rewrite targets output.args.prompt, not output.prompt
- (l) Prepended line uses actual main checkout directory, not parent of worktree
- (m) Parser accepts 'path. cd there', 'path -- cd there', 'path' forms;
dotted paths (e.g. feat.v2) are no longer truncated