Closes #44. That issue overstated the risk and this corrects it. The hook is three lines and echoes a string -- no bash-isms, so it cannot fail the way secret-guard appeared to. The real exposure is narrower and duller: it can stop working silently, and its entire job is to be visible. THE ASSERTION THAT MATTERS IS REGISTRATION. A hook file that exists but is absent from hooks.json does nothing at all and looks identical on disk to one that works. So the test derives the command from hooks.json and runs it exactly as registered, substituting CLAUDE_PLUGIN_ROOT the way the harness does, rather than inventing its own invocation. That choice is the lesson from #44's sibling. secret_guard_test.sh piped its hook into `sh` while hooks.json runs it with `bash`; on Debian /bin/sh is dash, which has no `set -o pipefail`, so the suite failed 20/20 in CI against a hook that was FINE in production. The test was wrong, not the hook -- and the earlier commit message for that fix said the shebang decides the interpreter, which hooks.json shows is not true. Deriving the invocation removes the whole class rather than fixing one instance of it. No red phase to report: the hook was already correct, so this is regression pinning, not TDD. Teeth proven by mutation against a throwaway copy instead: - hook runs but prints nothing -> 6 failures - hook removed from hooks.json -> caught, suite stops early - ONE ritual step dropped, rule 0 still named -> caught (9 passed, 1 failed) The third is the one worth having. Losing the whole line is obvious; quietly losing "failing test" from the ritual while the banner still reads correctly is the drift that would actually happen. Bump-Type: patch Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>