use super::invoking::{AGENT, Scene};
use crate::workspace::fixture;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::atomic::AtomicBool;
fn workflow_with_control(command: &Path) -> String {
format!(
"events: {{}}\ntool_control:\n command: {}\n",
command.display()
)
}
pub(super) fn control(scene: &Scene, body: &str) -> PathBuf {
let path = scene.ws.parent().unwrap_or(&scene.ws).join("control");
write_exec(&path, &format!("#!/usr/bin/env bash\n{body}\n"));
fixture::amend_config(
&scene.ws,
&[("workflow.yaml", &workflow_with_control(&path))],
);
path
}
fn write_exec(path: &Path, body: &str) {
let mut child = Command::new("sh")
.arg("-c")
.arg(r#"cat > "$1" && chmod 755 "$1""#)
.arg("sh")
.arg(path)
.stdin(Stdio::piped())
.spawn()
.expect("spawn the writer");
child
.stdin
.take()
.expect("stdin is piped")
.write_all(body.as_bytes())
.expect("write the script");
assert!(child.wait().expect("reap the writer").success());
}
#[test]
fn a_composing_tool_is_refused_at_depth_one() {
let scene = Scene::new();
let (code, out) = scene.invoke(r#"{"id":"tu_d","name":"python","input":{}}"#);
assert!(matches!(code, Ok(1)), "{out}");
assert!(
out.contains("composes tool invocations of its own and may not be one (depth 1)"),
"{out}"
);
assert!(
!scene.recorded("tu_d"),
"a refused invocation records nothing"
);
}
#[test]
fn a_retired_multi_tool_is_declined_as_any_ungranted_name() {
let scene = Scene::new();
let (code, out) = scene.invoke(r#"{"id":"tu_m","name":"multi_tool","input":{}}"#);
assert!(matches!(code, Ok(1)), "{out}");
assert!(out.contains("is not callable by a worker"), "{out}");
assert!(!scene.recorded("tu_m"));
}
#[test]
fn a_tool_outside_the_role_grant_is_declined_in_the_grant_gate_s_voice() {
let scene = Scene::new();
let (code, out) = scene.invoke(r#"{"id":"tu_g","name":"nosuch","input":{}}"#);
assert!(matches!(code, Ok(1)), "{out}");
assert!(out.contains("is not callable by a worker"), "{out}");
assert!(out.contains("declaring is not permitting"), "{out}");
assert!(!scene.recorded("tu_g"));
}
#[test]
fn a_control_refusal_settles_the_invocation_before_the_executor() {
let scene = Scene::new();
control(
&scene,
r#"echo '{"verdict":"refuse","reason":"not this one"}'"#,
);
let (code, out) = scene.invoke(r#"{"id":"tu_r","name":"bash","input":{"command":"echo ran"}}"#);
assert!(matches!(code, Ok(1)), "{out}");
assert!(
out.contains("was refused by the workflow's tool control"),
"{out}"
);
assert!(out.contains("not this one"), "{out}");
assert!(!scene.recorded("tu_r"));
}
#[test]
fn a_control_hold_degrades_to_the_re_issue_top_level_decline() {
let scene = Scene::new();
control(
&scene,
r#"echo '{"verdict":"hold","reason":"needs review"}'"#,
);
let (code, out) = scene.invoke(r#"{"id":"tu_h","name":"bash","input":{"command":"echo ran"}}"#);
assert!(matches!(code, Ok(1)), "{out}");
assert!(
out.contains("cannot park an invocation another tool is composing"),
"{out}"
);
assert!(
out.contains("re-issue this invocation as a top-level tool_use"),
"{out}"
);
assert!(out.contains("needs review"), "{out}");
assert!(!scene.recorded("tu_h"));
assert!(
crate::workspace::hold::read(&scene.ws, AGENT, &crate::template::RealGit::new()).is_none(),
"a degraded hold writes no mark"
);
}
#[test]
fn the_stop_landing_on_the_control_ceases_the_invocation() {
let scene = Scene::new();
control(&scene, "kill -TERM $$");
let stop = AtomicBool::new(true);
let (code, out) = scene.invoke_with(
r#"{"id":"tu_s","name":"bash","input":{"command":"echo ran"}}"#,
&stop,
);
assert!(matches!(code, Ok(1)), "{out}");
assert!(out.contains("the harness is stopping"), "{out}");
assert!(!scene.recorded("tu_s"));
}