diff --git a/crates/tui/src/core/engine.rs b/crates/tui/src/core/engine.rs index 2f7ef663..2cd07872 100644 --- a/crates/tui/src/core/engine.rs +++ b/crates/tui/src/core/engine.rs @@ -1294,13 +1294,14 @@ impl Engine { // registered, so leaving the sandbox policy at the seatbelt-strict // default is fine. AppMode::Plan => ctx, - // Agent and Yolo both register the shell tool. The sandbox-default - // policy denies all outbound network — including DNS — which - // breaks ordinary developer commands (cargo fetch, npm install, - // curl, yt-dlp, …) without buying the user any safety the - // application-level NetworkPolicy / approval flow doesn't already - // provide. Elevate to workspace-write + network. (#273) - AppMode::Agent | AppMode::Yolo => { + // Agent registers the shell tool and runs each command through + // the per-mode sandbox + per-tool approval flow. The sandbox + // default would deny all outbound network — including DNS — + // which breaks ordinary developer commands (cargo fetch, npm + // install, curl, yt-dlp, …) without buying the user any safety + // the approval flow doesn't already provide. Elevate to + // workspace-write + network. (#273) + AppMode::Agent => { ctx.with_elevated_sandbox_policy(crate::sandbox::SandboxPolicy::WorkspaceWrite { writable_roots: vec![self.session.workspace.clone()], network_access: true, @@ -1308,6 +1309,17 @@ impl Engine { exclude_slash_tmp: false, }) } + // YOLO is the explicit "no guardrails" mode — auto-approve all + // tools, trust mode on, no sandbox. Workspace-write was still + // intercepting commands that wanted to write outside the + // workspace (rare but legitimate: pipx install, npm install + // -g, brew, package-manager state under ~/.cache, sub-agent + // workspaces, …) which forced approval round-trips and + // contradicts the YOLO contract. The user opted into YOLO + // deliberately; trust them. + AppMode::Yolo => { + ctx.with_elevated_sandbox_policy(crate::sandbox::SandboxPolicy::DangerFullAccess) + } } } diff --git a/crates/tui/src/core/engine/tests.rs b/crates/tui/src/core/engine/tests.rs index 5179d97a..37f83a88 100644 --- a/crates/tui/src/core/engine/tests.rs +++ b/crates/tui/src/core/engine/tests.rs @@ -390,12 +390,20 @@ fn agent_and_yolo_modes_elevate_shell_sandbox_to_allow_network() { ); let yolo_ctx = engine.build_tool_context(AppMode::Yolo, false); + let yolo_policy = yolo_ctx + .elevated_sandbox_policy + .as_ref() + .expect("Yolo mode should elevate the sandbox policy"); + assert!(yolo_policy.has_network_access()); + // v0.8.11: YOLO drops to DangerFullAccess (no sandbox) so the user + // is not bounced through approval round-trips for legitimate + // outside-workspace writes (package installs, sub-agent + // workspaces, ~/.cache mutations, etc.). YOLO is opt-in and + // already enables trust mode + auto-approve; the sandbox was the + // last guardrail and contradicts the contract. assert!( - yolo_ctx - .elevated_sandbox_policy - .as_ref() - .expect("Yolo mode should elevate the sandbox policy") - .has_network_access(), + matches!(yolo_policy, crate::sandbox::SandboxPolicy::DangerFullAccess), + "Yolo mode must use DangerFullAccess (no sandbox); got {yolo_policy:?}", ); // Plan mode is read-only investigation and does not register the shell