Pair thread environment settings (#26687)

## Why

Thread cwd and environment selections are a single logical setting in
core: updating one without the other can silently desynchronize the
next-turn execution context. This change makes that relationship
explicit in the internal thread settings flow while preserving the
existing app-server public API shape.

## What changed

- Moved the cwd/environment pair through internal
`ThreadSettingsOverrides.environment_settings` instead of a top-level
internal `cwd` field.
- Kept `thread/settings/update` public params unchanged, with app-server
translating top-level `cwd` into the paired internal settings shape.
- Moved `Op::UserInput` environment overrides into thread settings so
user turns and settings updates use the same core path.
- Updated core, app-server, MCP, memories, sample, and test callsites to
construct the paired settings shape.

## Verification

- `git diff --check`
- Local test run starting after PR creation.
This commit is contained in:
pakrym-oai
2026-06-08 13:55:15 -07:00
committed by GitHub
parent f9a680b907
commit f3c1283411
90 changed files with 521 additions and 820 deletions
+14 -5
View File
@@ -32,6 +32,7 @@ use codex_protocol::protocol::ThreadMemoryMode;
use codex_protocol::protocol::ThreadSource;
use codex_protocol::protocol::TokenUsageInfo;
use codex_protocol::protocol::TurnEnvironmentSelection;
use codex_protocol::protocol::TurnEnvironmentSelections;
use codex_protocol::protocol::W3cTraceContext;
use codex_protocol::user_input::UserInput;
use codex_thread_store::StoredThread;
@@ -59,7 +60,7 @@ pub struct ThreadConfigSnapshot {
pub approvals_reviewer: ApprovalsReviewer,
pub permission_profile: PermissionProfile,
pub active_permission_profile: Option<ActivePermissionProfile>,
pub cwd: AbsolutePathBuf,
pub environments: TurnEnvironmentSelections,
pub workspace_roots: Vec<AbsolutePathBuf>,
pub profile_workspace_roots: Vec<AbsolutePathBuf>,
pub ephemeral: bool,
@@ -114,10 +115,18 @@ impl TryStartTurnIfIdleError {
}
impl ThreadConfigSnapshot {
pub fn cwd(&self) -> &AbsolutePathBuf {
&self.environments.legacy_fallback_cwd
}
pub fn environment_selections(&self) -> &[TurnEnvironmentSelection] {
&self.environments.environments
}
pub fn sandbox_policy(&self) -> SandboxPolicy {
codex_sandboxing::compatibility_sandbox_policy_for_permission_profile(
&self.permission_profile,
self.cwd.as_path(),
self.cwd().as_path(),
)
}
}
@@ -125,7 +134,7 @@ impl ThreadConfigSnapshot {
/// Thread settings overrides that app-server validates before starting a turn.
#[derive(Clone, Default)]
pub struct CodexThreadSettingsOverrides {
pub cwd: Option<AbsolutePathBuf>,
pub environments: Option<TurnEnvironmentSelections>,
pub workspace_roots: Option<Vec<AbsolutePathBuf>>,
pub profile_workspace_roots: Option<Vec<AbsolutePathBuf>>,
pub approval_policy: Option<AskForApproval>,
@@ -330,7 +339,7 @@ impl CodexThread {
overrides: CodexThreadSettingsOverrides,
) -> SessionSettingsUpdate {
let CodexThreadSettingsOverrides {
cwd,
environments,
workspace_roots,
profile_workspace_roots,
approval_policy,
@@ -357,7 +366,7 @@ impl CodexThread {
};
SessionSettingsUpdate {
cwd,
environments,
workspace_roots,
profile_workspace_roots,
approval_policy,