use super::*;
use crate::agentic::{mcp::NoMcp, smart_harness::SmartHarness};
use crate::caveats::Caveats;
use std::{path::Path, sync::Arc};
fn harness(directory: &Path) -> (SmartHarness, content_addressable::ContentId) {
let mut session =
agent_harness::Session::open(directory, crate::test_guard::unbudgeted_session_config())
.unwrap();
let source = session
.retain_tool_output("fixture", b"retained original source")
.unwrap();
(
SmartHarness::new(
session,
Arc::new(|_| panic!("filesystem isolation never needs inference")),
Default::default(),
)
.unwrap(),
source,
)
}
async fn dispatch(
harness: &SmartHarness,
workspace: &Path,
caveats: &Caveats,
name: &str,
args: serde_json::Value,
permission_gate: Option<&mut dyn PermissionGate>,
) -> String {
dispatch_with_worktree_session(
harness,
workspace,
caveats,
name,
args,
permission_gate,
None,
)
.await
}
async fn dispatch_with_worktree_session(
harness: &SmartHarness,
workspace: &Path,
caveats: &Caveats,
name: &str,
args: serde_json::Value,
permission_gate: Option<&mut dyn PermissionGate>,
worktree_session: Option<&crate::worktree_adoption::WorktreeSession>,
) -> String {
let batch = harness.fixture_tool_batch(name, args.clone());
let invocation = batch.start(0, None).unwrap();
let mut display = super::super::display::ToolDisplay::new(Vec::new(), false, 80, 20, false);
execute_tool_with_display_cancellable(
&mut display,
name,
&args,
workspace.to_str().unwrap(),
false,
20,
caveats,
&mut NoMcp,
ToolCollaborators {
invocation: Some(&invocation),
permission_gate,
worktree_session,
..Default::default()
},
false,
PromptDisposition::Act,
None,
)
.await
.unwrap()
.unwrap()
}
#[tokio::test]
#[serial_test::serial]
async fn exposed_frame_refuses_generic_tool_dispatch() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = workspace.path().join(".newt/frame");
let (harness, _) = harness(&directory);
let marker = directory.join("marker");
std::fs::write(&marker, "frame contents").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
for name in ["read_file", "write_file", "list_dir", "delete_file"] {
let target = if name == "list_dir" {
&directory
} else {
&marker
};
let output = dispatch(
&harness,
workspace.path(),
&caveats,
name,
serde_json::json!({"path":target,"content":"changed"}),
None,
)
.await;
assert!(output.contains("frame isolation"), "{name}: {output}");
assert_eq!(std::fs::read_to_string(&marker).unwrap(), "frame contents");
}
}
struct WidenAll;
impl PermissionGate for WidenAll {
fn ask(&mut self, _: &[PermissionRequest]) -> PermissionDecision {
PermissionDecision::Allow(Caveats::top())
}
fn ask_question(&mut self, _: &str) -> HumanQuestionOutcome {
HumanQuestionOutcome::Answer("operator answer".into())
}
}
#[cfg(target_os = "macos")]
#[tokio::test]
#[serial_test::serial]
async fn native_once_filesystem_frame_preflight_precedes_consumption_and_spawn() {
let _env = super::disable_ocap_tests::env_lock().await;
let _engine = super::disable_ocap_tests::EnvVar::set("NEWT_SHELL_ENGINE", "safe-subset");
let _ocap = super::disable_ocap_tests::EnvVar::unset("NEWT_DISABLE_OCAP");
let _full = super::disable_ocap_tests::EnvVar::unset("NEWT_FULL_ACCESS");
struct CountingGate(usize);
impl PermissionGate for CountingGate {
fn ask(&mut self, _: &[PermissionRequest]) -> PermissionDecision {
self.0 += 1;
PermissionDecision::Allow(Caveats::top())
}
fn ask_with_caveats(
&mut self,
_: &Caveats,
requests: &[PermissionRequest],
) -> PermissionDecision {
self.ask(requests)
}
fn ask_question(&mut self, _: &str) -> HumanQuestionOutcome {
HumanQuestionOutcome::Unavailable
}
}
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let unrelated = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = workspace.path().join("must-not-run");
let baseline = Caveats {
exec: crate::caveats::Scope::only(["/usr/bin/touch".into()]),
..crate::confined_exec::workspace_confined_caveats(workspace.path())
};
let mut gate = CountingGate(0);
for (target, expected_calls) in [(directory.path(), 0), (unrelated.path(), 1)] {
let output = dispatch(
&harness,
workspace.path(),
&baseline,
"run_command",
serde_json::json!({
"command": format!("/usr/bin/touch '{}'", marker.display()),
"fs_read": [target.canonicalize().unwrap()],
}),
Some(&mut gate),
)
.await;
assert!(output.contains("frame isolation"), "{output}");
assert_eq!(
gate.0, expected_calls,
"preflight avoids consumption; a broader actual decision is validated afterwards"
);
assert!(
!marker.exists(),
"the rejected declaration must not spawn a child"
);
}
}
#[cfg(target_os = "macos")]
#[tokio::test]
#[serial_test::serial]
async fn live_permission_refresh_cannot_bypass_frame_isolation() {
let _env = super::disable_ocap_tests::env_lock().await;
let _engine = super::disable_ocap_tests::EnvVar::set("NEWT_SHELL_ENGINE", "safe-subset");
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
struct RecalledAll;
impl PermissionGate for RecalledAll {
fn ask(&mut self, _: &[PermissionRequest]) -> PermissionDecision {
panic!("passive refresh must not ask for new authority");
}
fn refresh_caveats(&mut self, _: &Caveats) -> PermissionDecision {
PermissionDecision::Allow(Caveats::top())
}
fn ask_question(&mut self, _: &str) -> HumanQuestionOutcome {
HumanQuestionOutcome::Unavailable
}
}
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = workspace.path().join("must-not-run");
let baseline = crate::confined_exec::workspace_confined_caveats(workspace.path());
let output = dispatch(
&harness,
workspace.path(),
&baseline,
"run_command",
serde_json::json!({"command": format!("/usr/bin/touch '{}'", marker.display())}),
Some(&mut RecalledAll),
)
.await;
assert!(output.contains("frame isolation"), "{output}");
assert!(
!marker.exists(),
"refused refresh must stop before any child runs"
);
}
#[tokio::test]
#[serial_test::serial]
async fn permission_widening_cannot_expose_private_frame() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = directory.path().join("marker");
std::fs::write(&marker, "private generated material").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"read_file",
serde_json::json!({"path":marker}),
Some(&mut WidenAll),
)
.await;
assert!(!output.contains("private generated material"), "{output}");
assert!(
output.contains("denied") || output.contains("frame isolation"),
"{output}"
);
}
#[tokio::test]
#[serial_test::serial]
async fn private_frame_denies_raw_tools_and_preserves_mediated_reads() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, source) = harness(directory.path());
let marker = directory.path().join("marker");
std::fs::write(&marker, "private generated material").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
if crate::agentic::smart_harness::validate_isolation_runtime().is_err() {
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"re_read",
serde_json::json!({"cid":source.to_string(),"max_bytes":16}),
None,
)
.await;
assert!(output.contains("frame isolation"), "{output}");
return;
}
for name in ["read_file", "write_file", "list_dir", "delete_file"] {
let target = if name == "list_dir" {
directory.path()
} else {
&marker
};
let output = dispatch(
&harness,
workspace.path(),
&caveats,
name,
serde_json::json!({"path":target,"content":"changed"}),
None,
)
.await;
assert!(output.contains("denied"), "{name}: {output}");
assert_eq!(
std::fs::read_to_string(&marker).unwrap(),
"private generated material"
);
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
{
std::os::unix::fs::symlink(directory.path(), workspace.path().join("private-link"))
.unwrap();
for name in ["read_file", "write_file", "list_dir", "delete_file"] {
let path = if name == "list_dir" {
"private-link"
} else {
"private-link/marker"
};
let output = dispatch(
&harness,
workspace.path(),
&caveats,
name,
serde_json::json!({"path":path,"content":"changed"}),
None,
)
.await;
assert!(output.contains("denied"), "symlink {name}: {output}");
assert_eq!(
std::fs::read_to_string(&marker).unwrap(),
"private generated material"
);
}
}
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"re_read",
serde_json::json!({"cid":source.to_string(),"max_bytes":16}),
None,
)
.await;
let receipt: serde_json::Value = serde_json::from_str(&output).unwrap();
assert_eq!(receipt["text"], "retained origina");
assert_eq!(receipt["complete"], false);
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[tokio::test]
#[serial_test::serial]
async fn real_shell_cannot_read_or_mutate_private_frame() {
use crate::caveats::Scope;
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let _engine = super::disable_ocap_tests::EnvVar::set("NEWT_SHELL_ENGINE", "host");
let _env_grant = super::disable_ocap_tests::EnvVar::set(
"NEWT_SHELL_ENV_PASSTHROUGH",
"GIT_CONFIG_GLOBAL:GIT_CONFIG_SYSTEM",
);
let _global = super::disable_ocap_tests::EnvVar::set("GIT_CONFIG_GLOBAL", "/dev/null");
let _system = super::disable_ocap_tests::EnvVar::set("GIT_CONFIG_SYSTEM", "/dev/null");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = directory.path().join("marker");
std::fs::write(&marker, "private generated material").unwrap();
let mut caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
caveats.exec = Scope::All;
caveats.net = Scope::All;
let command = format!(
"printf allowed > inside.txt; cat '{}'; printf changed > '{}'; ln '{}' hardlink.txt",
marker.display(),
marker.display(),
marker.display()
);
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"run_command",
serde_json::json!({"command":command}),
None,
)
.await;
assert!(!output.contains("private generated material"), "{output}");
assert_eq!(
std::fs::read_to_string(&marker).unwrap(),
"private generated material"
);
assert!(!workspace.path().join("hardlink.txt").exists());
if crate::ocap_l3_backend().1 {
assert_eq!(
std::fs::read_to_string(workspace.path().join("inside.txt"))
.unwrap_or_else(|error| panic!("workspace control failed ({error}): {output}")),
"allowed"
);
let found = dispatch(
&harness,
workspace.path(),
&caveats,
"run_command",
serde_json::json!({"command":"find . -name inside.txt"}),
None,
)
.await;
assert!(
found.contains("./inside.txt"),
"confined shell find must run: {found}"
);
let initialized = crate::git_hardening::hardened_git(workspace.path(), &["init", "-q"])
.unwrap()
.output()
.unwrap();
assert!(
initialized.status.success(),
"fixture repository initialization failed: {}",
String::from_utf8_lossy(&initialized.stderr)
);
std::fs::write(workspace.path().join("visible.txt"), "visible").unwrap();
let status = dispatch(
&harness,
workspace.path(),
&caveats,
"run_command",
serde_json::json!({"command":"git status --short"}),
None,
)
.await;
assert!(
status.contains("?? visible.txt"),
"scoped shell Git must run: {status}"
);
let staged = dispatch(
&harness,
workspace.path(),
&caveats,
"run_command",
serde_json::json!({"command":"git add visible.txt"}),
None,
)
.await;
assert!(!staged.starts_with("error:"), "{staged}");
let index = crate::git_hardening::hardened_git(workspace.path(), &["ls-files", "--cached"])
.unwrap()
.output()
.unwrap();
assert!(index.status.success());
assert_eq!(String::from_utf8(index.stdout).unwrap(), "visible.txt\n");
let index_before = std::fs::read(workspace.path().join(".git/index")).unwrap();
let commit = dispatch(
&harness,
workspace.path(),
&caveats,
"run_command",
serde_json::json!({"command":"git commit -m fixture"}),
None,
)
.await;
assert!(
commit.contains("refusing Git commit publication")
&& commit.contains("native commit attribution/signing policy is unavailable"),
"{commit}"
);
assert_eq!(
std::fs::read(workspace.path().join(".git/index")).unwrap(),
index_before,
"refused commit must leave the staged index unchanged"
);
let head = crate::git_hardening::hardened_git(
workspace.path(),
&["rev-parse", "--verify", "HEAD"],
)
.unwrap()
.output()
.unwrap();
assert!(
!head.status.success(),
"refused commit must leave the repository without a commit"
);
} else {
assert!(output.contains("frame isolation"), "{output}");
}
}
async fn dispatch_with_execution(
harness: &SmartHarness,
workspace: &Path,
caveats: &Caveats,
name: &str,
args: serde_json::Value,
) -> (String, Option<crate::ExecOutcome>) {
let batch = harness.fixture_tool_batch(name, args.clone());
let invocation = batch.start(0, None).unwrap();
let mut display = super::super::display::ToolDisplay::new(Vec::new(), false, 80, 20, false);
let execution = std::sync::OnceLock::new();
let output = execute_tool_with_display_cancellable(
&mut display,
name,
&args,
workspace.to_str().unwrap(),
false,
20,
caveats,
&mut NoMcp,
ToolCollaborators {
invocation: Some(&invocation),
execution: Some(&execution),
..Default::default()
},
false,
PromptDisposition::Act,
None,
)
.await
.unwrap()
.unwrap();
(output, execution.get().copied())
}
#[tokio::test]
#[serial_test::serial]
async fn smart_harness_refusals_ledger_as_failures() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = workspace.path().join(".newt/frame");
let (harness, _) = harness(&directory);
let marker = directory.join("marker");
std::fs::write(&marker, "frame contents").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
let (output, execution) = dispatch_with_execution(
&harness,
workspace.path(),
&caveats,
"read_file",
serde_json::json!({"path":marker}),
)
.await;
assert!(output.contains("frame isolation"), "{output}");
assert!(
!tool_ok(&output, execution),
"frame isolation refusal must ledger ok=false: {output}"
);
let mut display = super::super::display::ToolDisplay::new(Vec::new(), false, 80, 20, false);
let execution2 = std::sync::OnceLock::new();
let output2 = execute_tool_with_display_cancellable(
&mut display,
"re_read",
&serde_json::json!({}),
workspace.path().to_str().unwrap(),
false,
20,
&caveats,
&mut NoMcp,
ToolCollaborators {
execution: Some(&execution2),
..Default::default()
},
false,
PromptDisposition::Act,
None,
)
.await
.unwrap()
.unwrap();
assert!(output2.contains("re_read is unavailable"), "{output2}");
assert!(
!tool_ok(&output2, execution2.get().copied()),
"re_read-outside-smart-harness must ledger ok=false: {output2}"
);
}
struct UnconfinedDelegate(std::path::PathBuf);
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[tokio::test]
#[serial_test::serial]
async fn smart_find_refuses_the_unbound_recursive_walker() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
std::fs::write(directory.path().join("private-frame-record"), "private").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
let root = workspace.path().join("search");
std::fs::create_dir(&root).unwrap();
assert!(find_root_contained(
&caveats.fs_read,
workspace.path().to_str().unwrap(),
&root,
root.to_str().unwrap(),
));
std::fs::remove_dir(&root).unwrap();
std::os::unix::fs::symlink(directory.path(), &root).unwrap();
let args = serde_json::json!({});
let opts = find_opts_from_args(&args);
let (hits, _) = find_walk(&root, workspace.path(), &opts, None, |_| {}).unwrap();
assert!(hits.iter().any(|hit| hit.contains("private-frame-record")));
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"find",
serde_json::json!({"path":"."}),
None,
)
.await;
assert!(output.contains("Error: frame isolation:"), "{output}");
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[tokio::test]
#[serial_test::serial]
async fn smart_grep_refuses_the_unbound_recursive_walker() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"grep",
serde_json::json!({"pattern":"x","path":"."}),
None,
)
.await;
assert!(
output.contains("Error: frame isolation: native grep"),
"{output}"
);
}
impl super::super::git_tool::GitTool for UnconfinedDelegate {
fn dispatch(
&self,
_: &str,
_: &serde_json::Value,
_: &crate::git_caveats::GitCaveats,
_: &Caveats,
) -> Result<String, String> {
Ok(std::fs::read_to_string(&self.0).unwrap())
}
}
#[async_trait::async_trait]
impl super::super::crew_tool::CrewRunner for UnconfinedDelegate {
async fn dispatch(
&self,
_: &str,
_: &serde_json::Value,
_: &Caveats,
) -> Result<String, String> {
Ok(std::fs::read_to_string(&self.0).unwrap())
}
}
#[tokio::test]
#[serial_test::serial]
async fn smart_delegates_cannot_read_private_payloads() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = directory.path().join("marker");
std::fs::write(&marker, "private generated material").unwrap();
let delegate = UnconfinedDelegate(marker.clone());
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
for (name, args) in [
("git", serde_json::json!({"op":"add","paths":[marker]})),
("crew", serde_json::json!({"task":"read private frame"})),
] {
let batch = harness.fixture_tool_batch(name, args.clone());
let invocation = batch.start(0, None).unwrap();
let mut display = super::super::display::ToolDisplay::new(Vec::new(), false, 80, 20, false);
let output = execute_tool_with_display_cancellable(
&mut display,
name,
&args,
workspace.path().to_str().unwrap(),
false,
20,
&caveats,
&mut NoMcp,
ToolCollaborators {
invocation: Some(&invocation),
git_tool: Some(&delegate),
crew_runner: Some(&delegate),
..Default::default()
},
false,
PromptDisposition::Act,
None,
)
.await
.unwrap()
.unwrap();
assert!(
!output.contains("private generated material"),
"{name}: {output}"
);
assert!(
output.contains("scoped fs_read") || output.contains("frame isolation"),
"{name}: {output}"
);
}
}
#[tokio::test]
#[serial_test::serial]
async fn smart_tools_refuse_unconfined_launch_authority() {
let _env = super::disable_ocap_tests::env_lock().await;
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
std::fs::write(workspace.path().join("inside.txt"), "allowed content").unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
for (yolo, full) in [("1", "0"), ("0", "1")] {
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", yolo);
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", full);
let output = dispatch(
&harness,
workspace.path(),
&caveats,
"read_file",
serde_json::json!({"path":"inside.txt"}),
None,
)
.await;
assert!(output.contains("frame isolation"), "{output}");
assert!(!output.contains("allowed content"), "{output}");
}
}
#[test]
fn frame_permission_gate_forwards_consume_pending_once() {
use crate::agentic::smart_harness::FramePermissionGate;
use std::cell::Cell;
use std::rc::Rc;
let consumed = Rc::new(Cell::new(false));
struct ConsumeSpy(Rc<Cell<bool>>);
impl PermissionGate for ConsumeSpy {
fn ask(&mut self, _: &[PermissionRequest]) -> PermissionDecision {
PermissionDecision::Deny
}
fn ask_question(&mut self, _: &str) -> HumanQuestionOutcome {
HumanQuestionOutcome::Unavailable
}
fn consume_pending_once(&mut self, _kind: DenialKind, _target: &str) {
self.0.set(true);
}
}
let directory = tempfile::tempdir().unwrap();
let workspace = tempfile::tempdir().unwrap();
let (h, _) = harness(directory.path());
let mut spy = ConsumeSpy(consumed.clone());
{
let mut gate = FramePermissionGate {
harness: &h,
workspace: workspace.path(),
inner: &mut spy,
refusal: None,
};
gate.consume_pending_once(DenialKind::FsWrite, "/ws/out.txt");
}
assert!(
consumed.get(),
"#2636 finding 2: FramePermissionGate must forward consume_pending_once to inner gate"
);
}
#[cfg(target_os = "macos")]
#[tokio::test]
#[serial_test::serial]
async fn macos_smart_runtime_admits_confined_seatbelt() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
assert!(
agent_bridle::seatbelt_is_supported(),
"native suite requires Seatbelt"
);
crate::agentic::smart_harness::validate_isolation_runtime().unwrap();
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[tokio::test]
#[serial_test::serial]
async fn private_frame_cannot_leak_through_write_shrink_or_edit_preview() {
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (harness, _) = harness(directory.path());
let marker = directory.path().join("marker");
let private = "private generated material\n".repeat(100);
std::fs::write(&marker, &private).unwrap();
std::os::unix::fs::symlink(&marker, workspace.path().join("link")).unwrap();
let caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
for (name, args) in [
(
"write_file",
serde_json::json!({"path":"link","content":"changed"}),
),
(
"edit_file",
serde_json::json!({"path":"link","old_string":"absent","new_string":"changed"}),
),
] {
let output = dispatch(&harness, workspace.path(), &caveats, name, args, None).await;
assert!(
output.contains("denied") || output.contains("frame isolation"),
"{output}"
);
assert!(!output.contains("100"), "shrink oracle: {output}");
assert!(
!output.contains("private generated material"),
"preview leak: {output}"
);
assert_eq!(std::fs::read_to_string(&marker).unwrap(), private);
}
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[tokio::test]
#[serial_test::serial]
async fn smart_shell_worktrees_support_scoped_creation_editing_and_staging() {
use std::os::unix::fs::PermissionsExt as _;
let _env = super::disable_ocap_tests::env_lock().await;
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
let _engine = super::disable_ocap_tests::EnvVar::set("NEWT_SHELL_ENGINE", "host");
let _env_grant = super::disable_ocap_tests::EnvVar::set(
"NEWT_SHELL_ENV_PASSTHROUGH",
"GIT_CONFIG_GLOBAL:GIT_CONFIG_SYSTEM",
);
let _global = super::disable_ocap_tests::EnvVar::set("GIT_CONFIG_GLOBAL", "/dev/null");
let _system = super::disable_ocap_tests::EnvVar::set("GIT_CONFIG_SYSTEM", "/dev/null");
let workspace = tempfile::tempdir().unwrap();
let private = tempfile::tempdir().unwrap();
let external_parent = tempfile::tempdir().unwrap();
let external = external_parent.path().join("task-worktree");
std::fs::create_dir(&external).unwrap();
std::fs::set_permissions(&external, std::fs::Permissions::from_mode(0o700)).unwrap();
let sibling = external_parent.path().join("ungranted");
std::fs::write(&sibling, "outside authority").unwrap();
let (harness, _) = harness(private.path());
let git_fixture = |args: &[&str]| {
let output = crate::git_hardening::hardened_git(workspace.path(), args)
.unwrap()
.output()
.unwrap();
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
};
git_fixture(&["init", "-q"]);
std::fs::write(workspace.path().join("task.txt"), "baseline\n").unwrap();
std::fs::write(workspace.path().join(".gitignore"), ".worktrees/\n").unwrap();
git_fixture(&["add", "task.txt", ".gitignore"]);
git_fixture(&[
"-c",
"user.name=Fixture",
"-c",
"user.email=fixture@example.invalid",
"commit",
"-qm",
"fixture baseline",
]);
let mut caveats = crate::confined_exec::workspace_confined_caveats(workspace.path());
caveats.net = crate::caveats::Scope::All;
let session = crate::worktree_adoption::WorktreeSession::default();
for (index, destination) in [workspace.path().join(".worktrees/task"), external.clone()]
.into_iter()
.enumerate()
{
if index == 1 {
caveats.fs_read = crate::caveats::Scope::only([
workspace.path().to_string_lossy().into_owned(),
external.to_string_lossy().into_owned(),
]);
caveats.fs_write = caveats.fs_read.clone();
}
let create = dispatch_with_worktree_session(&harness, workspace.path(), &caveats, "run_command",
serde_json::json!({"command":format!("git worktree add -b fixture-{index} '{}'", destination.display())}), None, Some(&session)).await;
if index == 0 {
assert!(create.contains("choose a sibling destination"), "{create}");
assert!(!destination.join("task.txt").exists());
continue;
}
assert!(
session.snapshot().is_some(),
"creation was not adopted: {create}"
);
assert!(destination.join("task.txt").exists(), "{create}");
let edited = dispatch_with_worktree_session(&harness, &destination, &caveats, "edit_file",
serde_json::json!({"path":destination.join("task.txt"), "old_string":"baseline", "new_string":"worktree change"}), None, Some(&session)).await;
assert_eq!(
std::fs::read_to_string(destination.join("task.txt")).unwrap(),
"worktree change\n",
"{edited}"
);
let staged = dispatch_with_worktree_session(&harness, &destination, &caveats, "run_command",
serde_json::json!({"command":"git add task.txt && git status --short", "cwd":destination}), None, Some(&session)).await;
assert!(staged.contains("M task.txt"), "{staged}");
assert_eq!(
std::fs::read_to_string(workspace.path().join("task.txt")).unwrap(),
"baseline\n"
);
}
let denied = dispatch(
&harness,
workspace.path(),
&caveats,
"read_file",
serde_json::json!({"path":sibling}),
None,
)
.await;
assert!(denied.contains("denied"), "{denied}");
assert!(!denied.contains("outside authority"));
}
#[test]
fn cold_cache_fetch_frame_gate_preserves_protection() {
let _env = crate::process_env::lock();
let _yolo = super::disable_ocap_tests::EnvVar::set("NEWT_DISABLE_OCAP", "0");
let _full = super::disable_ocap_tests::EnvVar::set("NEWT_FULL_ACCESS", "0");
use crate::agentic::smart_harness::FramePermissionGate;
struct FetchGate(usize);
impl PermissionGate for FetchGate {
fn ask(&mut self, _: &[PermissionRequest]) -> PermissionDecision {
panic!("host path")
}
fn ask_question(&mut self, _: &str) -> HumanQuestionOutcome {
HumanQuestionOutcome::Unavailable
}
fn ask_dependency_fetch(
&mut self,
prepared: &Caveats,
_: &PermissionRequest,
) -> PermissionDecision {
self.0 += 1;
PermissionDecision::Allow(prepared.clone())
}
}
let workspace = tempfile::tempdir().unwrap();
let directory = tempfile::tempdir().unwrap();
let (h, _) = harness(directory.path());
let mut inner = FetchGate(0);
let request = PermissionRequest {
tool: "lifecycle".into(),
kind: DenialKind::Net,
target: "one locked fetch".into(),
reason: "unrestricted fetch egress".into(),
harness_bound: true,
};
let mut prepared = crate::confined_exec::workspace_confined_caveats(workspace.path());
prepared.net = crate::Scope::All;
{
let mut gate = FramePermissionGate {
harness: &h,
workspace: workspace.path(),
inner: &mut inner,
refusal: None,
};
let decision = gate.ask_dependency_fetch(&prepared, &request);
#[cfg(any(target_os = "linux", target_os = "macos"))]
assert!(
matches!(decision, PermissionDecision::Allow(_)),
"unexpected frame refusal: {:?}",
gate.refusal
);
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
assert!(matches!(decision, PermissionDecision::Deny));
assert!(gate.refusal.as_deref().is_some_and(|reason| reason.contains(
"durable smart harness requires object-bound filesystem tools and a supported kernel sandbox"
)));
}
prepared.fs_read = crate::Scope::All;
assert!(matches!(
gate.ask_dependency_fetch(&prepared, &request),
PermissionDecision::Deny
));
assert!(gate.refusal.is_some());
}
assert_eq!(
inner.0,
usize::from(cfg!(any(target_os = "linux", target_os = "macos")))
);
}