Closes#173, #174, #175, #176 and #170.
#174 — decideHook read exit 2, `decision` and `permissionDecision` but not the
harness's halt-the-turn field, so `assertBlocksDisasters` reported a guard that
stopped every disaster as blocking none. The field is read from the PORT, not
hard-coded: `continue` is documented for Claude Code and unverified for Codex.
The issue's adjacent suggestion was deliberately NOT implemented — adding the
halt to `hook-block-ineffective` as a block-attempt signal would fire on hooks
that WORK, since a halt is not event-scoped. It reads as a suppressor instead,
fixing a real false alarm. A mutation implementing the original suggestion
literally is pinned by a test that fails on it.
#173 — compile printed its errors, exited 1, and wrote a hash-valid CLAUDE.md
anyway, so `lint` went green over refs it had just called dead. Nothing is
written on a failed compile now.
#176 — eight small defects, including `audit --out` outside the repo appending
unreachable `../../..` entries to .gitignore (a documented read-only report
editing a tracked file), an unknown command exiting 1 against a documented 2,
and STABILITY.md promising the removed `scan` verb.
#175 + #176.2 — three missing capabilities, each opt-in and additive:
`{surface}` in testGlobs, `--single`, and `rulesDir` so `.claude/rules/**`
stops being invisible.
#170 — one enumeration of export forms written against the grammar, both naming
checks driven off it, and `check-internal-tag.mjs` asking the TypeScript
compiler instead of a regex. It immediately found the issue's open case, 13
tagged types the regex had never seen, and a live gap in the ESLint rule.
BREAKING CHANGE: `HookRunResult` gains a required `haltsTurn`, so code that
CONSTRUCTS one (a test fake) must set it. Reading a result is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>