Scope runtime workspace roots to execution environments (#32952)

## Why

Multi-environment turns can run against different filesystems, so a single
thread-wide workspace-root list cannot accurately describe every selected
environment.

## What changed

- Add optional `runtimeWorkspaceRoots` to each app-server environment selection.
  Omitted roots default to that environment's `cwd`, while an empty list selects
  no roots.
- Carry environment-native roots through turn selection, model-visible context,
  permission materialization, and tool sandboxing.
- Keep the top-level `runtimeWorkspaceRoots` field as a compatibility input when
  constructing default environment selections; explicit selections use their
  own roots.

## Testing

- Cover thread and turn API defaults, overrides, empty roots, and schema
  round-tripping.
- Verify foreign roots remain model-visible and remote execution applies the
  target environment's roots before sandbox selection.

GitOrigin-RevId: c6e7a62883c45c676c153055f46a55ee15a323a4
This commit is contained in:
pakrym-oai
2026-07-14 04:41:08 +00:00
committed by copyberry
parent b019a5577c
commit 393f64565a
62 changed files with 769 additions and 446 deletions
@@ -4227,13 +4227,15 @@ fn turn_start_params_round_trip_environments() {
let raw_cwd = r"C:\workspace";
let cwd: LegacyAppPathString =
serde_json::from_value(json!(raw_cwd)).expect("API path should deserialize");
let workspace_root = cwd.clone();
let params: TurnStartParams = serde_json::from_value(json!({
"threadId": "thread_123",
"input": [],
"environments": [
{
"environmentId": "local",
"cwd": cwd
"cwd": cwd,
"runtimeWorkspaceRoots": [workspace_root]
}
],
}))
@@ -4244,6 +4246,7 @@ fn turn_start_params_round_trip_environments() {
Some(vec![TurnEnvironmentParams {
environment_id: "local".to_string(),
cwd: cwd.clone(),
runtime_workspace_roots: Some(vec![workspace_root.clone()]),
}])
);
assert_eq!(
@@ -4257,7 +4260,8 @@ fn turn_start_params_round_trip_environments() {
Some(&json!([
{
"environmentId": "local",
"cwd": cwd
"cwd": cwd,
"runtimeWorkspaceRoots": [workspace_root]
}
]))
);
@@ -41,6 +41,9 @@ pub enum TurnStatus {
pub struct TurnEnvironmentParams {
pub environment_id: String,
pub cwd: LegacyAppPathString,
/// Environment-native runtime workspace roots. Omitted defaults to `cwd`.
#[ts(optional = nullable)]
pub runtime_workspace_roots: Option<Vec<LegacyAppPathString>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]