diff --git a/rust/crates/tools/src/lib.rs b/rust/crates/tools/src/lib.rs index 9366963..9328e83 100644 --- a/rust/crates/tools/src/lib.rs +++ b/rust/crates/tools/src/lib.rs @@ -1427,9 +1427,20 @@ fn run_task_output(input: TaskIdInput) -> Result { #[allow(clippy::needless_pass_by_value)] fn run_worker_create(input: WorkerCreateInput) -> Result { + // Merge config-level trusted_roots with per-call overrides. + // Config provides the default allowlist; per-call roots add on top. + let config_roots: Vec = ConfigLoader::default_for(&input.cwd) + .load() + .ok() + .map(|c| c.trusted_roots().to_vec()) + .unwrap_or_default(); + let merged_roots: Vec = config_roots + .into_iter() + .chain(input.trusted_roots.iter().cloned()) + .collect(); let worker = global_worker_registry().create( &input.cwd, - &input.trusted_roots, + &merged_roots, input.auto_recover_prompt_misdelivery, ); to_pretty_json(worker) @@ -5506,6 +5517,43 @@ mod tests { assert_eq!(accepted_output["prompt_in_flight"], true); } + #[test] + fn worker_create_merges_config_trusted_roots_without_per_call_override() { + use std::fs; + // Write a .claw/settings.json in a temp dir with trustedRoots + let worktree = temp_path("config-trust-worktree"); + let claw_dir = worktree.join(".claw"); + fs::create_dir_all(&claw_dir).expect("create .claw dir"); + // Use the actual OS temp dir so the worktree path matches the allowlist + let tmp_root = std::env::temp_dir().to_str().expect("utf-8").to_string(); + let settings = format!("{{\"trustedRoots\": [\"{tmp_root}\"]}}"); + fs::write( + claw_dir.join("settings.json"), + settings, + ) + .expect("write settings"); + + // WorkerCreate with no per-call trusted_roots — config should supply them + let cwd = worktree.to_str().expect("valid utf-8").to_string(); + let created = execute_tool( + "WorkerCreate", + &json!({ + "cwd": cwd + // trusted_roots intentionally omitted + }), + ) + .expect("WorkerCreate should succeed"); + let output: serde_json::Value = serde_json::from_str(&created).expect("json"); + + // worktree is under /tmp, so config roots auto-resolve trust + assert_eq!( + output["trust_auto_resolve"], true, + "config-level trustedRoots should auto-resolve trust without per-call override" + ); + + fs::remove_dir_all(&worktree).ok(); + } + #[test] fn worker_tools_detect_misdelivery_and_arm_prompt_replay() { let created = execute_tool(