[codex] Bind shell snapshots to retained thread environments (#28421)

## Why

Shell snapshots are currently session-scoped even though shell and cwd
are properties of a selected turn environment. That makes snapshot
refresh depend on separate session-cwd plumbing, prevents retained
environments from retaining their snapshot work, and can make snapshot
construction use a different shell than command execution.

This follows #27955 by making the retained thread-environment service
own environment snapshot lifecycles. Session configuration remains the
requested selection state, while `ThreadEnvironments` remains the source
of successfully resolved environments.

## What changed

- Configure the shell-snapshot builder before initial environment
resolution.
- Start each local environment snapshot task when its `TurnEnvironment`
is built and retain that shared task while environment ID and cwd still
match.
- Inherit retained environment snapshots into spawned child threads.
- Carry the selected `TurnEnvironment` through shell runtimes so
snapshot construction and command execution use the same
environment-specific shell and cwd.
- Load project instructions and warm plugins/skills after initial
environment resolution.
- Continue decoding invalid UTF-8 instruction files lossily without
emitting a startup warning.
- Keep requested selections in `SessionConfiguration`; failed or
duplicate resolutions only affect the resolved environment snapshot.

## Validation

- `cargo check -p codex-core --tests`
- `just test -p codex-home instructions` (6 passed)
- Focused environment, instruction, shell-snapshot, and user-shell tests
(84 passed)
- Focused shell-snapshot, user-shell, and unified-exec tests (126
passed; two event-timing tests passed on retry)
This commit is contained in:
pakrym-oai authored and GitHub committed 2026-06-15 20:10:53 -07:00
1 parent ecfe174d5f
commit 022f1221e8
28 files changed
+453 -617

No files matched your search

+2 -2
View File
@@ -27,7 +27,6 @@ use std::collections::HashSet;
use std::sync::Arc;
use std::sync::Weak;
use codex_exec_server::Environment;
use codex_network_proxy::NetworkProxy;
use codex_protocol::models::AdditionalPermissionProfile;
use codex_tools::UnifiedExecShellMode;
@@ -40,6 +39,7 @@ use tokio::sync::Mutex;
use crate::sandboxing::SandboxPermissions;
use crate::session::session::Session;
use crate::session::turn_context::TurnContext;
use crate::session::turn_context::TurnEnvironment;
use crate::shell::ShellType;
use crate::tools::network_approval::DeferredNetworkApproval;
@@ -98,7 +98,7 @@ pub(crate) struct ExecCommandRequest {
pub max_output_tokens: Option<usize>,
pub cwd: AbsolutePathBuf,
pub sandbox_cwd: AbsolutePathBuf,
pub environment: Arc<Environment>,
pub turn_environment: TurnEnvironment,
pub shell_mode: UnifiedExecShellMode,
pub network: Option<NetworkProxy>,
pub tty: bool,