Rename the read-only scan verb to `vigiles audit` — a local, zero-config Lighthouse-style report scoring a harness across four deterministic rings (Truthfulness/Triggering/Structure/Tested) with each finding's fix inline + a shareable HTML report and a versioned AuditReport JSON.
audit is a local report, not a CI step (CI uses `vigiles lint`). The executing checks (live MCP resolution + trigger-rate + the adoption preview) run only behind one interactive consent; there is no execution flag. The safety battery is not an audit ring — it lives in the vigiles/testing API.
Adds the adoption-gateway preview ("what would vigiles catch in your repo?"): the model drafts a spec from the instruction file, the cross-reference engine verifies every drafted ref deterministically.
BREAKING CHANGE: the `scan` verb is renamed to `audit` (no alias); the `--check-hooks`/`--verify-mcp`/`--trigger`/`--fix-plan`/`--explain`/`--deep`/`--measure`/`--fast`/`--no-measure` flags are removed.
2.2 KiB
hook-events
Cross-reference each hook's event name against the harness event catalog — a
hook registered under a name the platform doesn't define silently never fires,
a dead registration no generic JSON linter catches. Same detector vigiles audit
uses (verifyHookEvents / confidentHookEventIssues in
src/core/hook-events.ts); one detector, two callers, no drift.
What it flags (high-precision)
Only a close typo of a real event (edit distance ≤ 2, with a did-you-mean):
"hooks": { "PreToolUSe": [ … ] } // ✗ never fires. Did you mean "PreToolUse"?
A bare unrecognized event with no near match is NOT flagged. The event
set is not closed in practice — frameworks extend it (TheBushidoCollective/han
ships a custom runtime with TeammateIdle, WorktreeRemove, … in its own
hooks.json), so flagging those would be crying wolf. Only the canonical
object-keyed-by-event shape is checked; a plugin shipping a hooks array (a
non-CC custom format whose events live inside each entry) is skipped entirely.
The real Claude Code events: PreToolUse, PostToolUse, UserPromptSubmit,
Notification, Stop, SubagentStop, PreCompact, SessionStart,
SessionEnd.
Configuration
{ "rules": { "hook-events": "warn" } }
Severity
| Value | Behavior |
|---|---|
"error" |
vigiles lint exits non-zero (2) on a typo'd hook event |
"warn" (default) |
Prints a warning, exits 0 |
false |
Skip the check |
Scope
Reads the repo's hook configuration (plugin.json / .claude/settings.json /
hooks/hooks.json) via the same loader scan uses. A Codex repo's events live
in a different catalog — the check runs against the resolved harness dialect.
Why
hooks is the deterministic-constraints layer of the harness; a hook on a typo'd
event is enforcement that silently does nothing. Catching it at authoring time,
deterministically and for free, is the same cross-reference applied to the hook surface.