probe-hook 0.1.0

The probe-algebra edit guard as a shipped Claude Code hook: speaks the hook protocol natively, derives its voices from the tree, teaches classes from the repo's own register, installs its own wiring — fail-open as a tested property, not a per-consumer convention.
Documentation

probe-hook — the edit guard as a SHIPPED envelope (the eleventh ask).

Agenda::edit_guard and GuardVoices::for_edit are mutation-tested and register-driven — and before this crate, every consumer wrapped them in the same four pieces of unjudged glue: a bash wrapper, inline JSON-parsing Python, a build-on-demand fallback that could run a stale binary, and hand-authored settings.json plumbing. All of it outside the mutation boundary, each consumer with different bugs. This crate is that envelope, inside the boundary:

  • speaks the Claude Code hook protocol natively — reads the PostToolUse JSON from stdin, extracts tool_input.file_path, honours CLAUDE_PROJECT_DIR;
  • discovers the repo's own declarations — voices derived from the tree (GuardVoices::for_edit), classes taught from spec/agenda.register; the consumer writes zero code;
  • carries the fail-open contract inside the boundary — every internal failure (malformed JSON, missing path, unreadable file, refused register) is silence, as a drilled property of [respond], not a || exit 0 convention;
  • installs its own wiring — [install] writes or idempotently merges the settings.json entry, so the plumbing is derived output, never hand-authored.

Honest frame — version skew: a globally installed probe-hook can be newer or older than the probe-algebra a repo pins, and the two can disagree about register grammar or voice derivation. The floor shipped here: every non-silent voice block carries the binary's version on its last line, and the guard is advisory and fail-open, so skew degrades to weaker advice, never a false refusal. (Re-execing a repo-local build is the known nicer form; deliberately not built until skew is observed hurting.)