## Why
Spawning a subagent before an environment was ready dropped the starting environment from the child's selections. The child needs to retain that environment and receive its configuration or failure when preparation finishes.
## What changed
- Pass the spawning step's environment snapshot to children, preserving ready and starting environments and configuration ownership.
- Propagate the original owner's first configuration result through descendants, applying each session's validation and leaving independently configured children unchanged.
- Preserve pending configuration waits across executor retries. Later owner updates do not overwrite the child's inherited configuration.
## Testing
Add regression coverage for fresh and forked subagents, readiness through turn-settings updates, failure propagation to children and grandchildren, child configuration precedence, and executor retries. Add a request snapshot showing a child using `wait_for_environment` before execution tools become available.
GitOrigin-RevId: a2afed740391f88d195596cfe28e418332b60d43
## Why
Private IP destinations always bypassed inherited upstream proxies, preventing their use for private networks reachable through an upstream VPN proxy.
## What changed
- Add `codex exec-server --proxy-private-ips-via-upstream`, also configurable with `CODEX_EXEC_SERVER_PROXY_PRIVATE_IPS_VIA_UPSTREAM=true`. The setting defaults to disabled.
- Allow permitted RFC 1918, carrier-grade NAT, and IPv6 unique-local destinations to use an applicable upstream proxy. Loopback and link-local destinations retain direct routing, and destination access policy still applies.
- Keep connections direct when no valid upstream proxy applies or `allow_upstream_proxy=false`. Errors after selecting an upstream proxy do not trigger a direct retry.
- Rename `ExecServerRuntimePaths` to `ExecServerRuntimeOptions` and carry the routing setting from executor startup into the managed network proxy.
## Testing
Add routing coverage for private address ranges, special-use addresses, and public targets with the option enabled and disabled. Verify that HTTP and CONNECT requests still enforce destination allowlists and denylists, and update the CLI help snapshot.
GitOrigin-RevId: b7c9cc7da0e0f545694a6521b74c9b36b7b92769
## Why
Legacy shell snapshots could retain exports excluded by `shell_environment_policy` and restore captured values over explicit overrides when replayed.
## What changed
- Build snapshots with the resolved environment's policy and omit filtered exports and original values for variables overridden by `set`.
- Skip eager snapshot creation when configuration is unavailable, and reject snapshots whose policy differs from the current turn's policy.
## Testing
Add a regression test covering default and custom exclusions, `include_only`, preservation of multiline values, and `set` overrides that survive snapshot replay. Verify excluded and overridden captured values are absent from the snapshot file.
GitOrigin-RevId: 4b785130f6c5a4d268ab86fd36ab9d77d8c4a3b9
## What changed
- Add `environments` to `TurnSettingsUpdate` to replace the selection for subsequent steps without changing future turns.
- Capture model settings and environments together so combined updates apply or reject atomically, while existing steps retain their captured selection.
- Validate environment IDs, working directories, configuration ownership, and permission requirements against the running turn's selections.
- Preserve executor startup behavior when switching environments and use the step's local working directory for tool hooks.
## Testing
Add coverage for workspace switching and restoration on the next turn, atomic model and environment updates, permission validation, executor connection waits, and replacement of pending environment selections.
GitOrigin-RevId: 02b5c57a78fd594b2aed84fc09d9e99eb97be28c
## Why
Thread permission updates could affect later steps of a running turn. Keep inherited environment settings consistent throughout the turn and apply saved updates when the next turn starts.
## What changed
Store active thread defaults alongside selected environments and refresh them when activating a new turn, even when its environment selections are unchanged. Resolve new selections from those active defaults while preserving owner-provided configuration, selection workspace roots, and the local Windows sandbox type.
## Testing
Add a regression test that changes permissions during a paused turn and verifies that both steps retain restricted filesystem access while the next turn receives unrestricted access. Update session and MCP elicitation tests to check that permission changes take effect on the next turn.
GitOrigin-RevId: 37ee44198fa40c138d140974dc90c4177d8c1f4c
## What changed
Add the default-off `features.prefer_mxc` flag to select MXC for local Windows execution when native support is available and effective network settings do not explicitly forbid local binding. Otherwise, retain the configured backend and legacy setup behavior.
Resolve the preference during config loading and use the effective local backend for execution, network proxy setup, sandbox diagnostics, and `windowsSandbox/readiness`. Preserve the configured backend for remote executors and `config/read`. Explicit `windows.sandbox = "mxc"` remains strict, and command failures do not trigger backend fallback.
## Testing
Add coverage for preference resolution, startup readiness without rewriting configuration, local and remote backend selection across environment updates and child threads, and workspace-write permission context in an agent turn.
GitOrigin-RevId: b51178f0371d38ebb58e41af54a068fca67fa316
## Why
Concurrent credential refreshes could restore a removed environment by overwriting the selection list with stale state. Unpolled snapshot futures could also keep pending configuration alive after an environment was removed.
## What changed
- Protect environment selections with a mutex and update them in place to serialize selection changes, configuration refreshes, and connection listener setup.
- Capture only selection metadata and resolution futures in snapshots so they do not retain pending configuration senders.
## Testing
Add regression tests for removal during credential refresh and cancellation while an unpolled snapshot is held. Strengthen the pending attachment integration test to check that `wait_for_environment` returns the expected environment ID and `ready` status.
GitOrigin-RevId: c6f933e8d3031b05335ddcfed00ab400aa5bad2a
## Why
When a selected environment is unavailable, permission fallbacks can use the turn's initial environment and workspace roots. Daemon recovery can also miss a local environment that finishes starting after the turn begins.
## What changed
- Resolve fallback permissions from thread defaults using the captured selection's workspace root URIs, including when setup is starting or has failed.
- Apply this resolution to Guardian reviews, permission instructions, and sandbox context selection.
- Capture daemon recovery from the latest step inputs and refresh environment readiness before checking recovery eligibility.
## Testing
Add regression tests for Guardian resolving project-root restrictions against an unavailable captured environment's workspace and for daemon recovery including a local environment that finishes starting during a turn.
GitOrigin-RevId: c76d83d786fdc9c444b78ecbc335b02a20805c58
## What changed
- Remove the private-desktop opt-out from elevated and unelevated Windows sandbox launches.
- Remove `windows.sandbox_private_desktop` and its managed requirement and API fields. Warn users to remove the obsolete setting.
- Require a private desktop name when launching through the Windows sandbox wrapper and command runner.
## Testing
Add coverage for the obsolete-setting migration warning and update wrapper tests to verify a live private desktop is passed and a missing desktop name is rejected.
GitOrigin-RevId: c7135f8d211aac8d812180691c2c1e433d77cde4
## Why
Environment settings saved for the next turn must not change MCP tool availability during the active turn.
## What changed
- Use one captured environment snapshot for MCP policy evaluation and runtime publication, including selections that are still starting or have failed.
- Compare both captured selections and ready environment handles when deciding whether to refresh the runtime, and rebuild the startup configuration when resolved selections change.
- Preserve the configuration origin of failed selections so MCP authority evaluation retains whether configuration comes from the thread.
- Box the MCP refresh future to keep it off the sampling request's stack.
## Testing
Add a regression test that updates the environment MCP policy while a turn waits for user input, verifies the tool remains visible when that turn resumes, and verifies it disappears on the next turn. Extend snapshot tests to cover starting and failed selections.
GitOrigin-RevId: cc2744b5137be69f000d70b0c7009b14079f39ae
## Why
Updating environment selections while a turn is running must not redirect its tools or prevent its pending environment setup from completing.
## What changed
- Store future environment selections separately from active environments, and activate them when preparing new work with no task running.
- Keep turn contexts and MCP workspace roots tied to the active environment snapshot. Report saved selections through thread settings and `environment_selections()`.
- Route environment configuration and failure callbacks to matching active or future selections so each can finish setup independently.
- Stop the running task before manual compaction adopts the saved environments.
## Testing
Add regression tests that preserve a running task's working directory and workspace roots, then adopt the saved selection for the next task. Add remote environment coverage showing that future setup can complete while the active turn waits, with each turn receiving its own capability roots.
GitOrigin-RevId: 09a6b90131d2ab2441ce2fe9b0368a3668889f31
## What changed
- Accept `windows.sandbox = "mxc"` and preserve the selected backend through environment configuration, command execution, patch writes, and sandbox metadata.
- Treat MXC as enabled in the TUI and report Windows sandbox readiness as `ready`, avoiding legacy setup prompts.
- Keep `allowed_sandbox_implementations` scoped to the legacy elevated and unelevated backends without restricting MXC.
- Default `windows.sandbox_private_desktop` to `false` for MXC while retaining `true` for legacy sandboxes.
## Testing
Add coverage for MXC configuration precedence, legacy requirement handling, sandbox selection, and TUI state. Add a Wine integration test that verifies command and patch routing fails when native MXC is unavailable and reports `windows_mxc` in turn metadata.
GitOrigin-RevId: e2162447d0750f60753864c92a20e02a7f297bca
## Why
Removing the selected working directory can prevent filesystem sandbox helpers from launching, even when the requested absolute paths remain accessible. Permission rules must stay anchored to the selected directory while those operations continue.
## What changed
- Require a policy `cwd` in `FileSystemSandboxContext` and launch filesystem helpers from the filesystem root while preserving the policy directory and workspace roots.
- Carry explicit `policyContext` in filesystem RPCs, preserving legacy wire fields and resolving omitted directories from older clients at executor ingress.
- Keep permission paths as executor file URIs and validate host compatibility where they are enforced.
- Bind Windows relative denial globs to the policy directory before changing the helper's launch directory, preserving home-relative patterns.
## Testing
Add regression coverage for `apply_patch` after working-directory removal, legacy RPC directory fallbacks, cross-platform permission URI transport, and Windows relative read denials. The patch regression verifies that an allowed file is updated while an explicitly denied file remains unreadable and unchanged.
GitOrigin-RevId: b0f4db722b27cb72ec129fc297c85732afac11f7
## Why
Executor profile roots can use path conventions that are not native to the current host. Converting them to host paths during configuration or turn reconstruction can reject or drop those roots, while case-insensitive comparison can hide Windows path spelling changes.
## What changed
- Store profile roots as URI-backed `ProfileWorkspaceRoot` values throughout permission snapshots and thread settings, preserving spelling in equality and deduplication.
- Keep effective workspace roots as `PathUri` values for permission materialization and status summaries. Convert Windows sandbox root hints to native paths only at native Windows sandbox boundaries, rejecting incompatible roots.
- Omit the legacy rollout `workspace_roots` field when profile roots cannot be represented as host paths, retaining the compiled permission profile.
## Testing
Add regression coverage for Windows and UNC root spelling changes, settings restoration and turn recording with foreign roots, executor-root status display, and backend-specific Windows root conversion.
GitOrigin-RevId: 903c068fd74959bdd10e7cb1141aa42b953a59a4
## What changed
- Accept `disabledPluginIds` in `thread/settings/update` and `turn/start`. A supplied list replaces the saved selection; omission or `null` preserves it, and `[]` clears it.
- Return the selection in thread start, resume, and fork responses and `thread/settings/updated` notifications. Update generated schemas and client types.
- Restore disabled plugin IDs from the history retained at the requested fork boundary, preserving explicit overrides.
The selection persists across resume but does not yet filter plugin capabilities.
## Testing
Add coverage for replacing, preserving, and clearing selections without inference; turn-start notifications; resume; and fork boundaries across legacy and paginated history, with loaded and restarted parents. Add a core regression test for history restoration and explicit clearing.
GitOrigin-RevId: 654a8c2a0527228d422c0dd4919228447e2663db
## Why
Failed environments were omitted from environment context, and `wait_for_environment` returned a generic failure or treated an already-failed environment as unselected. The model needs the failure reason to explain problems such as an empty repository.
## What changed
- Preserve the selected environment and error when startup or configuration fails.
- Include failed status and XML-escaped error details in environment context, and return the reason from `wait_for_environment` for failures detected before or during a wait.
- Limit error details to 256 bytes per environment and 512 bytes total in context, preserving UTF-8 boundaries. Limit wait failure details to 256 bytes.
## Testing
Add coverage for failures before a turn and while waiting, verifying that the model receives the reason and the turn completes. Add unit tests for XML escaping, incremental context updates, clearing errors on recovery, and UTF-8-safe truncation.
GitOrigin-RevId: 093ab9b447c7b3243fbb53b665180db95479f2a7
## Why
Credential-brokered commands rebuild shell snapshots on every invocation. Snapshot capture failures can also include credential-bearing startup output, and descendants holding output pipes need cleanup even after the shell exits.
## What changed
- Cache successful protected snapshots per environment, keyed by working directory, shell, login mode, and sandbox configuration. Rebuild missing or stale snapshots while keeping concurrent captures independently cancellable.
- Invalidate snapshots when shell settings or credential broker configuration change, and retry capture once if broker configuration changes during startup.
- Restore credentials and associated provider context while respecting environment policy filters and explicit overrides.
- Keep full-buffer capture subject to timeout and cancellation through output draining, clean up descendants on capture expiration or drain failure, and omit startup output from snapshot errors.
## Testing
Add regression coverage for snapshot reuse, invalidation, recovery after storage failure, concurrent cancellation, credential-safe errors, and descendant cleanup. Verify that successful background startup and output beyond the shell output cap remain supported.
GitOrigin-RevId: 7c7c8455bf6e3b9ca173dbb4277783469f0b45e6
## Why
Shell startup files can introduce credentials or overwrite brokered dummy values. Snapshot capture and replay need to respect the command's sandbox and environment policy without persisting real credentials.
## What changed
- Capture and validate brokered snapshots per command using its requested shell, working directory, login mode, sandbox, and environment policy.
- Discover shell-initialized credentials and prepare snapshot exports for brokered replay. Preserve shell functions and aliases while preventing startup files from overwriting dummy credentials during replay.
- Rebuild snapshots as credential broker state changes and retain each command's snapshot for the lifetime of its process.
- Reject brokered POSIX shell execution when a protected snapshot cannot be created, and reject brokerage with `shell_zsh_fork`. Restore real credentials and remove brokerage markers for unsupported PowerShell and Cmd execution; escalated commands bypass protected snapshots.
## Testing
Add regression coverage for credential discovery and redaction, environment filtering, readonly exports, shell function and heredoc replay, command working directories and login modes, sandbox enforcement, and missing or disabled snapshots.
GitOrigin-RevId: 685356cb9e80f11cf69d053e4d239ee6ccf43a9e
## What changed
- Store the shared `GuardianReviewSessionManager` in thread extension data and let the Guardian extension spawn and fork reviewers through `ThreadManager`, independently of async scorer startup.
- Preserve reviewer reuse, concurrent forks, cancellation, inherited environments, and user instructions. Gate managed reviewer startup on parent registration and remove terminated reviewers from the manager.
- Retain the `guardian` subagent identity in saved conversations. Reject resume of live Guardian reviewers and reject client archive or delete of live owner-managed workers with JSON-RPC error `-32600`; allow normal access after the owner releases them.
- Keep standalone reviewer support for inline delegates and remove duplicated extension prompt and configuration code.
## Testing
Add app-server tests covering reviewer reuse and concurrent forks, inherited instructions and prompt cache keys, live resume and removal rejection, saved reviewer discovery and resume after parent shutdown, and strict Guardian assessment inside an inline review.
GitOrigin-RevId: 4f9893c1ade151eacb4c11ffeae3d9e9ec019187
## Why
Full Access already combines `approvalPolicy: "never"` with unrestricted
permissions, so confirmation-only actions do not require a model review.
## What changed
- Detect Full Access consistently across the thread and every selected
environment. Pending, failed, or restricted environments are not treated as
Full Access.
- Approve confirmation-only Guardian and MCP requests without synchronous
review, sampler prewarming, or background scoring. Cancellation, explicit
denials, and forms that require user input keep their existing behavior.
- Re-evaluate the active permission state on each turn so an existing thread
can enter or leave Full Access safely.
## Testing
Added coverage for switching approval modes, strict sensitive MCP
confirmations, failed and pending environments, and suppression of Guardian
requests and background-scoring connections.
GitOrigin-RevId: 089ab4296dde473b8e33ab8324be79c5446c46f6
## What changed
- Add the optional `platformOs` field to exec-server environment metadata, with
local exec servers reporting `std::env::consts::OS` and legacy servers
remaining compatible when the field is absent.
- Preserve the reported OS in each selected turn environment, including the
local environment.
## Testing
- Extend protocol serialization and environment-selection coverage for remote
and local platform values.
GitOrigin-RevId: 0f325f6cb83cd8f8c7ec1ce2a4041f45a29e8f38
## What changed
- Report the executor's user home in environment metadata.
- Cache the reported home on selected turn environments and include it in
filesystem sandbox contexts, including `apply_patch` requests.
- Preserve compatibility with executors that do not report a home directory.
## Testing
- Cover local, remote, inherited, serialized, and `apply_patch` sandbox
contexts.
GitOrigin-RevId: ea65e68e33a80bc9bcfc7c53b1486ab944699470
## What changed
- Add effective workspace roots to `EnvironmentConfig` and use them when
materializing permission profiles and filesystem context.
- Preserve selection roots for thread-owned configurations while allowing a
ready environment attachment to supply its resolved roots.
- Propagate resolved roots to child environments and validate both command and
`apply_patch` writes in owner-provided secondary workspaces.
GitOrigin-RevId: 1832c168ce1fc37fa67efc2a472998ab4f448c70
## Why
Filesystem policies containing `:tmpdir` need executor-local directory bindings,
including when execution occurs in a remote environment.
## What changed
- Cache temporary directories reported by remote executors and discover the
equivalent directories for local environments.
- Preserve the cached directories across inherited environment selection and
include them in `FileSystemSandboxContext`.
- Add `FileSystemSandboxPolicyContext` and a context accessor so filesystem
policy entries can be resolved with the executor-owned current directory,
workspace roots, and temporary directories.
## Testing
Extend environment-selection tests to cover local, remote, and inherited
temporary-directory policy context.
GitOrigin-RevId: 36335af3465c529f024bf69293af288803dd582d
## What changed
- Add Windows sandbox mode, private-desktop behavior, and legacy Landlock selection to each `EnvironmentConfig`.
- Centralize sandbox context construction on `TurnEnvironment`, preserving environment-owned permissions, paths, and backend settings while applying additional permission grants.
- Use the environment-derived context for project instructions, capability discovery, file uploads, and filesystem-oriented tools.
## Testing
- Verify capability discovery uses the selected environment's permission profile and sandbox backends when they differ from the thread defaults.
GitOrigin-RevId: 7ae2fed90c8ada950f2e8431e571e9b2c793c291
## What changed
- Add the under-development `shell_snapshot_v2` feature and advertise executor support through environment capabilities.
- Use executor-managed, in-memory snapshots for eligible direct `bash`, `zsh`, and `sh` login commands, while applying the configured shell environment policy and avoiding duplicate automatic startup-file effects.
- Keep file-backed snapshots available for user-shell commands and fall back to the existing execution path when in-memory snapshots are unsupported or inapplicable.
## Testing
- Cover policy filtering, snapshot reuse without snapshot files, automatic startup files, local and remote execution, and legacy user-shell snapshots.
GitOrigin-RevId: 4ad6cdf13824913ac8c393ba38b9844230677579
## Why
Resumed threads can carry a persisted capability-root location that no longer
matches the location reported by the attached executor.
## What changed
- Refresh matching thread-owned capability roots from the live environment while
preserving persisted roots when the executor reports none.
- Use the same merge behavior for capability-root inspection and per-step MCP
resolution, without changing owner-configured root precedence.
## Testing
Extend the remote-environment resume test to cover both an executor-provided
replacement root and the persisted-root fallback.
GitOrigin-RevId: 0c66195b2406f431a2e156e00d5225a8d22d18b2
## Why
Environment-owned permission profiles and workspace roots must remain effective
without being persisted or restored as thread-owned settings.
## What changed
- Keep thread settings snapshots and restore data separate from the effective
configuration supplied by the primary environment.
- Use resolved environment permissions, active profiles, workspace roots, and
network policy when building turn context and session events.
- Preserve environment selections when agents are evicted, resumed, or spawned,
and validate owner configuration when it becomes ready.
- Start memory initialization only after the primary environment is configured.
## Testing
- Extend remote-environment and multi-agent tests to cover settings persistence,
owner permission profiles, workspace roots, spawning, eviction, and resume.
GitOrigin-RevId: d82f126981cd0190233020bbdd61d96c70558868
## What changed
- Add environment-provided MCP restrictions for configured and plugin-provided servers.
- Disable attachment-scoped servers while their environment configuration is pending, failed, or unselected, while preserving selected-plugin access and the controller-owned Apps server.
- Apply the resolved policy to runtime startup, model tool exposure, telemetry, OAuth flows, and skill dependency installation.
## Testing
- Cover policy filtering for configured and plugin servers, environment state transitions, Apps ownership, and managed OAuth rejection.
GitOrigin-RevId: 7ca5d4dda14068e758497f88835d5cba685e159e
## What changed
- Add spans for environment resolution, readiness waits, and environment info,
including fields for the selected environment and resolution state.
- Propagate the active span and tracing subscriber into spawned resolution,
startup, and shell-snapshot tasks.
- Verify that blocking snapshots retain the expected nested environment spans.
GitOrigin-RevId: 3c47e9ec1ebf45dbe1250b9ff76e2983d2a8df2a
## What changed
- Add `EnvironmentNetworkPolicy` as a serializable view of portable domain,
Unix-socket, upstream-proxy, and local-binding restrictions without exposing
controller-owned proxy runtime settings.
- Add an optional `network_policy` field to `EnvironmentConfig` and re-export
the policy and related permission types through the core APIs.
- Reject owner-provided network policies during environment preview and
readiness until runtime enforcement is implemented, while preserving the
existing controller policy when the field is absent.
## Testing
- Cover rejection through both environment preview and readiness, including
preservation of the existing environment selection.
GitOrigin-RevId: 80ad4cf4d4a45632daa7a823e6cf568eb0e8bb80
## What changed
- Add an optional restrictive execution policy to `EnvironmentConfig` and merge it over the active command policy for shell execution and approval decisions.
- Reject environment policies that contain allow rules, so environment configuration can only tighten command access.
- Include the environment policy fingerprint in cached approval keys so policy changes require fresh session approvals.
## Testing
- Cover restrictions overriding saved prefix approvals, policy changes invalidating session approvals, and environment overlays remaining effective when model-specific prefix filtering is active.
GitOrigin-RevId: e94f877549ed5e0f577b8cb52f3c1872c58f029d
## What changed
- Carry `ShellEnvironmentPolicy` in each resolved `EnvironmentConfig` and use
the selected turn environment's policy for shell commands, user shell tasks,
and unified exec.
- Infer the policy from the thread configuration when an environment does not
provide its own resolved configuration.
- Redact the policy from `EnvironmentConfig` debug output because it can contain
explicit environment variable values.
## Testing
- Verify shell handlers and unified exec filter inherited variables according
to the selected environment while preserving its explicit overrides.
GitOrigin-RevId: 9f6a52aa4af60e5f17251a0e1b11e1926b779055
## Why
An environment connection can be available before its owner has supplied the
configuration for a particular thread attachment. Threads need to start without
blocking while ensuring turns do not use that attachment prematurely.
## What changed
- Accept `Pending` environment configuration and resolve each attachment only
after both its shared executor connection and owner configuration are ready.
- Add a `Failed` configuration state and `environment_failed` callback so an
owner can fail one thread's attachment without affecting other threads.
- Keep pending and failed attachments out of capability-root inspection and turn
environments, and allow failed attachments to recover through a ready update.
- Apply owner configuration before waking a waiting turn so its permission
profile, login-shell policy, capability roots, and tools are immediately
consistent.
## Testing
Add an integration test covering non-blocking thread startup, independent ready
and failed callbacks, waiting-turn resumption, installed capability and tool
configuration, and recovery from failure.
GitOrigin-RevId: d587e2025d584c867d782d470b18bf5a1a27b76c
## Why
Environment attachments can either inherit configuration from their thread or
provide their own. Later thread setting updates must refresh inherited
configuration without overwriting attachment-owned permissions and capability
roots.
## What changed
- Resolve each attachment's configuration when it is selected and retain
whether it came from the thread or the attachment owner.
- Apply subsequent thread configuration updates only to thread-owned
attachments, while preserving ownership across snapshots and child threads.
- Keep the resolved configuration with the environment selection so runtime
consumers use a single canonical value.
## Testing
- Extend remote-environment coverage to verify that thread-owned permissions
follow thread updates while owner-provided read-only permissions remain in
effect.
- Cover configuration inheritance, attachment replacement, and owner-configured
capability roots.
GitOrigin-RevId: fe70c4be5f151432b69bf4b141e316faa89036ae
## What changed
- Add a resolved `permission_profile` to each `EnvironmentConfig` and use the
complete attachment config for execution and capability-root selection.
- Let `Ready` environment configurations override thread permissions while
`FromThread` selections continue to inherit them.
- Restrict inherited Guardian environment profiles to read-only permissions.
## Testing
- Add coverage proving that a read-only environment blocks writes even when
the thread permits workspace writes.
- Update environment inheritance, Guardian review, and capability-root tests
for the resolved attachment configuration.
GitOrigin-RevId: 1a313b9e4892b1a579a0e880e322a782b4f6c0a7
## What changed
- Add `EnvironmentConfigState` to `TurnEnvironmentSelection` so each environment attachment can inherit thread configuration or carry ready configuration for its login-shell policy and selected capability roots.
- Apply ready configuration during thread creation and thread-settings updates while reusing the existing environment connection.
- Validate selection configuration before applying settings, rejecting unsupported pending state and invalid capability roots.
## Testing
- Cover attachment-scoped capability roots, ready configuration at thread startup and turn updates, and rejection of invalid selections without changing existing settings.
GitOrigin-RevId: 86cf8f2148fdaa746ea0dd12890ab7b1577d7587
## What changed
- Store `TurnEnvironmentSelection` directly on each resolved `TurnEnvironment`
instead of copying its environment ID, working directory, and workspace roots
into separate fields.
- Update environment resolution, tool execution, approvals, and related tests to
access selection state through the retained value.
GitOrigin-RevId: ab723d21e112b8af5bcaf1f772a5e376553312bc
## What changed
- Make `ThreadEnvironments` the source of truth for live environment selections and use it when building configuration snapshots, permission profiles, per-turn configuration, and MCP refresh inputs.
- Keep settings previews side-effect free while applying accepted environment updates consistently to subsequent turns.
- Move `EnvironmentConfig` into `codex-protocol` so environment ownership no longer depends on a core-only type.
## Testing
- Cover environment previews and snapshots, accepted and rejected steer updates, and active-turn environment stability.
GitOrigin-RevId: 7bcf8fb5df1215f720e4e9c419541a51a871aa5e
## What changed
- Add `http_headers_helper` configuration for local streamable HTTP MCP servers. The configured shell command runs once per connection and returns a JSON object of headers that is cached across requests.
- Apply helper headers to MCP startup and OAuth flows while restricting them to the server origin, stopping redirects, rejecting reserved or duplicate headers, and enforcing output and execution limits.
- Reject helpers for remote or managed-disabled servers, use the local environment working directory, and redact helper commands from `codex mcp list` and `codex mcp get` output.
## Testing
- Cover configuration validation, helper lifecycle and output parsing, origin isolation, OAuth discovery and token refresh, managed requirements, environment selection, and CLI redaction.
GitOrigin-RevId: 84e0e26ce75520b0869d37c72b1678e033bd6818
## Why
Threads that share an executor environment can require different capability roots and login-shell policies. Treating readiness configuration as executor-wide can expose one thread's settings to another.
## What changed
- Add `CodexThread::environment_ready` and `EnvironmentConfig` so hosts can install capability roots and login-shell policy for an exact thread, environment, and working-directory attachment.
- Validate attachment readiness updates, merge ready attachment roots with persisted thread roots, and refresh MCP capabilities when those roots change.
- Preserve installed environment policy across thread settings updates and child-thread inheritance while resetting it when the selected working directory changes.
## Testing
- Cover attachment config inheritance and reset behavior.
- Verify that threads sharing an executor retain independent model-visible capability roots and login-shell tool schemas across updates.
GitOrigin-RevId: 60e7a296b3e41b835b0413aa2837451e8a55c230
## What changed
- Rename `EnvironmentConfig` to `TurnEnvironmentConfig` to make its scope explicit.
- Rename the corresponding `SessionConfiguration` accessor and update all call sites.
GitOrigin-RevId: f47d745566199e699bd8e7c671c313eaf3bba79e
## What changed
- Include the current permission profile in each turn environment's configuration.
- Refresh retained environment configurations when session settings change, while preserving the configuration already captured by active turns.
- Keep environment connection and shell snapshot resolution reusable across configuration updates.
## Testing
- Cover permission profile updates applied through both session settings updates and per-turn updates.
- Verify that pending environment resolutions use the configuration captured by their turn and that configuration-only updates do not retry failed environments.
GitOrigin-RevId: 923694f0729b87a118d7635ade3a8ca9bcd4e7b1
## What changed
- Store the effective `allow_login_shell` setting on each turn environment, including inherited environments whose child thread has a different policy.
- Expose the `login` argument for shell tools when any selected environment permits login shells.
- Validate each command against the policy of its selected environment instead of the turn-wide configuration.
## Testing
- Cover tool schema generation for single and multiple environments.
- Cover login-shell rejection by both the command handler and the unified exec integration.
GitOrigin-RevId: 5a93149a5c86f4087f2b92d663ebc33feff8a57c
## Why
The TUI must inspect the default execution environment before loading its final
configuration. Initializing the environment manager at that point can give
startup services the bootstrap HTTP policy instead of the effective policy after
managed requirements are applied.
## What changed
- Split environment discovery from manager construction so callers can inspect
the default environment without starting remote connections.
- Build the environment manager after final configuration loading and pass its
resolved `HttpClientFactory` through all construction paths.
- Add shared test support for managers that use the legacy default HTTP policy.
## Testing
- Cover connection-free environment discovery and explicit HTTP policy
propagation.
- Verify TUI startup services use the final managed `respect_system_proxy` value.
GitOrigin-RevId: 928fa31e6b4bcfbe1a121cade2f351427fdfa0f4
## Why
With deferred execution enabled, rebuilding a step context from the latest
thread environment snapshot could apply a settings update to a turn that was
already in progress.
## What changed
- Preserve each turn's captured environment selections when creating later
step contexts.
- Refresh only the readiness of environments that were already starting, while
retaining their original selection order.
- Apply updated environment selections to the next turn.
## Testing
Add coverage for changing the selected workspace while a turn is paused,
verifying that the active turn keeps its original working directory and the
next turn uses the new one.
GitOrigin-RevId: c6f4388c843384ef045b7abdbc303dcfca11d230
## What changed
- Track connected and disconnected states across initial remote exec-server connections and reconnection attempts.
- Emit experimental `thread/environment/connected` and `thread/environment/disconnected` app-server notifications for each thread selecting the environment. Each payload identifies the thread and environment; current state is not replayed when a thread starts.
- Stop forwarding connection events when an environment selection is removed or replaced.
## Testing
- Cover connection, disconnection, reconnection, shared-environment notifications, and replacement of a selected environment.
GitOrigin-RevId: 5dd767372363c4a2a8319fc16164be117d5bd20c
## What changed
Add named tracing spans around step environment snapshots, capability and
executor plugin resolution, `AGENTS.md` refreshes, and MCP runtime projection
and refresh operations. Skip recording function arguments to keep these spans
focused on timing and execution flow.
GitOrigin-RevId: 73a452ef1b5da6f7f2b00d24421a815c5d514eaf
## 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
## Why
`selectedCapabilityRoots` is durable thread intent: “use this capability
root from environment `worker`.”
The important product assumption is:
> One environment ID always names the same logical executor and stable
contents.
`worker` does not silently change from executor A to an unrelated
executor B. The process-local connection handle for `worker` can still
be replaced while Codex is running, though, for example when
`environment/add` registers a fresh handle for the same logical
environment.
The thread should persist only the stable selection. Each model step
should pair that selection with the exact ready handle captured for that
step.
## The boundary
```text
persisted thread intent
plugin@1 -> environment "worker"
|
| capture the current step
v
model-step view
unavailable, or
plugin@1 + worker's exact captured ready handle
```
The environment ID is the stable identity and cache key. The
`Arc<Environment>` is only a process-local handle retained so consumers
of one model step use the same captured environment. It is never
persisted and it does not imply different environment contents.
## What changes
### Persist the stable selection
Selected roots are written into `SessionMeta` and restored with the
thread. Forked subagents inherit the same selections, including
bounded-history forks.
Only stable data is persisted: root ID, environment ID, and root path.
### Capture readiness together with the exact handle
The environment snapshot records:
```rust
environment_id -> Some(Arc<Environment>) // ready in this step
environment_id -> None // still starting in this step
```
This prevents readiness and execution from coming from different
registry snapshots.
For example:
```text
step snapshot: worker -> handle A, ready
environment/add: worker -> fresh handle B for the same logical environment
current step: plugin@1 still uses captured handle A
```
Without carrying handle A in the snapshot, the resolver could combine “A
was ready” with handle B and treat B as ready before it had finished
starting.
This does not change cache invalidation. Stable capability metadata
remains identified by environment ID and capability root. Replacing a
process-local handle under the same stable environment ID does not
invalidate or rediscover that metadata.
### Resolve availability per model step
- A ready captured environment produces resolved roots using its
captured handle.
- A starting, missing, or failed environment is omitted from that step.
- A selected lazy environment that is outside the turn's captured
environment set is asked to start, and a later step can observe it as
ready.
- No capability files are scanned here.
Transient transport disconnects remain the remote client's reconnect
concern. This PR models initial attachment/readiness; it does not add
live socket-connectivity state.
## Example
```text
thread selection: plugin@1 -> environment "worker"
step 1: worker is starting -> plugin@1 unavailable
step 2: worker is ready -> plugin@1 resolves through worker's captured handle
step 3: fresh local handle -> current step remains pinned; a later step captures its own view
```
Temporary unavailability does not discard the durable selection. Later
PRs can retain stable metadata caches while projecting only currently
available capabilities into model-visible World State.
## Compatibility
The app-server request shape does not change. Older rollouts without
`selected_capability_roots` deserialize to an empty list.
## Stack
1. **This PR:** persist stable selected roots and resolve them through
an exact model-step handle.
2. #29960: cache stable skill metadata and project available skills into
World State.
3. #29946: cache stable plugin declarations and manage the separate live
MCP runtime.