test(gate): a fixture emitter for the live PreToolUse check, and what it proved
deploy / test (push) Successful in 4m41s
deploy / build (push) Successful in 5m46s

Tried to close the last open question — does the PreToolUse gate actually
fire in a guest — and got most of the way.

Established:
  - the generated script blocks and allows correctly under DASH, not just
    macOS sh: force-push and `cd /tmp && rm -rf /` return 2, while
    `grep -rn 'rm -rf /' docs/` and ordinary work return 0
  - without node it allows and writes the `inert` marker, so a gate that
    cannot parse is distinguishable from one that matched nothing
  - `claude` in the runtime image supports `--settings` (SETTINGS-OK)
  - PreToolUse DOES fire under `claude -p` in this image — measured by an
    earlier session and recorded in vm_stop_gate.rs:36

Unproven, and now precisely scoped: whether Claude Code honours a
PreToolUse hook supplied via `--settings <path>` specifically, with a real
agent turn. The live attempt hit the weekly subscription rate limit, and
`claude doctor` does not report hooks, so there is no non-LLM confirmation
available.

`emit_guest_assets` (ignored by default) writes the real hook script and the
real settings document to /tmp so the check can be run against the actual
binary in one docker command — no microVM, no fleet. The exact command is in
docs/NEXT-SESSION.md.

Worth stating plainly: if that link is broken, the gate is inert in
production and looks exactly like a gate that found nothing — which is the
failure mode this whole session has been about.

Full workspace suite green: 107 binaries.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-20 14:45:48 -07:00
co-authored by Claude Opus 5
parent afb1e29bf3
commit 0be932fd83
2 changed files with 51 additions and 3 deletions
+11
View File
@@ -479,6 +479,17 @@ mod shell_tests {
let _ = std::fs::remove_dir_all(&dir);
}
/// Writes the real guest assets to /tmp so they can be run against the
/// actual `claude` binary. Ignored: it is a fixture generator, not a check.
#[test]
#[ignore = "emits guest assets for a live hook test"]
fn emit_guest_assets() {
std::fs::write("/tmp/guest-tool-gate.sh", hook_script(GUEST_DIR)).unwrap();
let doc = crate::vm_tool_tap::guest_settings(None, None, Some(GUEST_DIR));
std::fs::write("/tmp/guest-settings.json", doc.to_string()).unwrap();
println!("wrote /tmp/guest-tool-gate.sh and /tmp/guest-settings.json");
}
#[test]
fn the_shell_blocks_a_force_push_with_exit_2_and_a_reason() {
let payload = r#"{"tool_name":"Bash","tool_input":{"command":"git push --force origin main"}}"#;