SIGN IN SIGN UP

test(hooks): characterize the hook decision paths end to end

`rtk rewrite`'s exit-code protocol is a public contract -- the claude and
cursor shell hooks, the opencode and pi TypeScript plugins, the hermes
Python adapter and openclaw all branch on it -- but no Rust test ever
called `run()`. `rewrite_cmd`'s own `exit_code_protocol` module asserts
against a locally re-implemented `expected_exit_code()` table, so the real
mapping could change without a single failure, including the #1155
invariant that a `Default` verdict must exit 3 and never 0.

Add an integration test that spawns the binary in a sandboxed
HOME/XDG_CONFIG_HOME/CLAUDE_CONFIG_DIR with project-level permission rules,
and pins the actual (exit code, stdout) pairs for allow, ask, deny,
compound deny, passthrough, default, compound rewrite, fd-dup redirect,
unattestable constructs and heredocs.

Alongside it, pin the two decision paths against each other on one corpus.
`rtk rewrite` and `rtk hook claude` answer the same question through two
independently written flows; the corpus asserts they agree, and a separate
test pins the one place they don't -- an already-RTK-prefixed command,
which the in-process hook defers on and `rtk rewrite` reports as an
ask-rewrite with the command unchanged. Modelled on registry.rs's
`segmenter_consistency` module.

Also pin `rtk hook check`, which had no test at all. It calls
`rewrite_command` directly with no verdict and none of the hooks' gates, so
it reports a rewrite for command substitutions and file redirects that both
hook paths refuse to touch.

No source change: this characterizes today's behavior so the decision-flow
consolidation can be shown to preserve it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
N
Nicolas Le Cam committed
af28c37216d9864c338a87ca2185fe9048c53c20
Parent: 8e9aa04