use std::io;
use std::path::PathBuf;
use crate::adapters::{HarnessAdapter, adapter_for};
use crate::core::Harness;
use crate::sandbox;
pub(crate) fn run_guard(marker: Option<String>) -> anyhow::Result<()> {
run_guard_hook("claude-code", marker)
}
pub(crate) fn run_guard_codex(marker: Option<String>) -> anyhow::Result<()> {
run_guard_hook("codex", marker)
}
pub(crate) fn run_guard_hook(harness_name: &str, marker: Option<String>) -> anyhow::Result<()> {
let payload = io::read_to_string(io::stdin()).unwrap_or_default();
let Ok(harness) = Harness::resolve(harness_name) else {
return Ok(());
};
let adapter = adapter_for(harness);
let Some(marker_path) = marker
.map(PathBuf::from)
.or_else(|| default_marker_path(adapter))
else {
return Ok(());
};
if let Some(verdict) = adapter.guard_verdict(&payload, sandbox::read_marker(&marker_path)) {
print!("{verdict}");
}
Ok(())
}
pub(crate) fn run_teardown_guard() -> anyhow::Result<()> {
let torn = sandbox::teardown_guard(&std::env::current_dir()?);
println!(
"{}",
if torn {
"🛡 Write guard removed."
} else {
"No write guard was installed — nothing to remove."
}
);
Ok(())
}
fn default_marker_path(adapter: &dyn HarnessAdapter) -> Option<PathBuf> {
Some(
adapter
.skills_dir(&std::env::current_dir().unwrap_or_default())?
.join(sandbox::GUARD_MARKER),
)
}