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