Commit Graph
3510 Commits
Author SHA1 Message Date
Ahmed Ibrahim e0edbe022f Merge remote-tracking branch 'origin/main' into codex/model-info-multi-agent-version
# Conflicts:
#	codex-rs/core/src/thread_manager.rs
#	codex-rs/thread-store/src/types.rs
2026-05-29 13:14:46 -07:00
Ahmed Ibrahim 91d87fcd09 Persist resolved multi-agent version per thread 2026-05-29 13:12:44 -07:00
Ahmed Ibrahim fb3905f59d Fix explicit V2 spawn test thread ids 2026-05-29 12:42:13 -07:00
Ahmed Ibrahim f41333434c Remove test-only multi-agent flag resolution 2026-05-29 12:33:31 -07:00
Ahmed Ibrahim 3abb77151d Reuse spawn options for fork runtime version 2026-05-29 12:30:50 -07:00
Ahmed Ibrahim 6a6a67f96a Fix direct session constructor test fixtures 2026-05-29 12:20:04 -07:00
Ahmed Ibrahim 1385f9d03f Carry resolved multi-agent version into child sessions 2026-05-29 12:08:26 -07:00
sayan-oai 1f93706e99 [codex] Require model for standalone web search (#25131)
## Why

The standalone `/v1/alpha/search` request now requires a `model`, but
the `web.run` extension currently omits it.

Adds `model` to extension `ToolCall` invocation.

Follow-up to #23823.

## What changed

- Make `SearchRequest.model` required.
- Expose the effective per-turn model on extension tool calls and pass
it in standalone web-search requests.
- Assert the model is forwarded in the app-server round-trip test.

## Testing

- `just test -p codex-api -p codex-tools -p codex-web-search-extension
-p codex-memories-extension -p codex-goal-extension`
- `just test -p codex-core -E
'test(passes_turn_fields_and_scoped_turn_item_emitter_to_extension_call)'`
- `just test -p codex-app-server -E
'test(standalone_web_search_round_trips_encrypted_output)'`
2026-05-29 12:03:04 -07:00
Michael Bolin a1ecf0cf1c thread-store: store permission profiles (#23165)
## Why

`SandboxPolicy` is the legacy compatibility shape, but
`codex-thread-store` still exposed it through `StoredThread`,
`ThreadMetadataPatch`, and live metadata sync. That kept thread-store
consumers tied to the legacy representation and meant richer permission
profile data could not round-trip through thread metadata or cold
rollout reconciliation.

## What Changed

- Replaced thread-store `sandbox_policy` API fields with canonical
`PermissionProfile` fields.
- Persist new permission-profile metadata as canonical JSON in the
existing SQLite metadata slot while continuing to read older legacy
sandbox policy values.
- Updated local, in-memory, live metadata sync, and rollout extraction
paths to propagate `TurnContextItem::permission_profile()`.
- Re-materialize legacy permission metadata against the final rollout
cwd when rollout-derived metadata replaces stale SQLite summaries.
- Updated affected app-server and core test constructors to build
`PermissionProfile` values directly.

## Test Plan

- `cargo test -p codex-state`
- `cargo test -p codex-thread-store`
- `cargo test -p codex-app-server
summary_from_stored_thread_preserves_millisecond_precision --lib`
- `cargo test -p codex-core realtime_context --lib`
2026-05-29 11:55:31 -07:00
Ahmed Ibrahim 6f931a9cf1 Keep multi-agent depth separate from runtime version 2026-05-29 11:43:11 -07:00
Channing Conger c9dc0f6338 code-mode: introduce durable session interface (#24180)
## Summary

Introduce a `CodeModeSession` interface for executing and managing
code-mode cells.

This moves cell lifecycle, callback delegation, termination, and
shutdown behind a session abstraction, while continuing to use the
existing in-process implementation, and the ability to implement an
external process one behind this interface.

A Codex session owns one `CodeModeSession`, which in turn owns its
running cells and stored code-mode state. Each cell is represented to
the caller as a `StartedCell`, exposing its cell ID and initial
response.

It also introduces a `CodeModeSessionDelegate` callback interface. A
session uses the delegate to invoke nested host tools and emit
notifications while a cell is running, allowing the runtime to
communicate with its owning Codex session without depending directly on
core turn handling.

<img width="2121" height="1001" alt="image"
src="https://github.com/user-attachments/assets/c349a819-2a59-485c-bda4-2caf68ac4c31"
/>
2026-05-29 11:42:52 -07:00
Ahmed Ibrahim ada487fb3d Import multi-agent runtime resolver in session tests 2026-05-29 11:30:00 -07:00
Owen Lin fc9cf62efb Add subagent lineage metadata for responsesapi (#24161)
## Why

We recently added `forked_from_thread_id` which lets us trace where a
thread's _context_ comes from, but we also want to understand subagent
lineage (e.g. which parent thread spawned this subagent? what kind of
subagent is it?) which is orthogonal.

This PR adds `parent_thread_id` and `subagent_kind` to the
`x-codex-turn-metadata` header sent to ResponsesAPI.

## What changed

- Adds `parent_thread_id` and `subagent_kind` to core-owned
`x-codex-turn-metadata`.
- Restores persisted `SessionSource` and `ThreadSource` from resumed
session metadata so cold-resumed subagent threads keep their lineage on
later Responses API requests.
- Centralizes parent-thread extraction on `SessionSource` /
`SubAgentSource` and reuses it in the Responses client, analytics, agent
control, and state parsing paths.
- Extends reserved-key, git-enrichment, thread-spawn, and app-server v2
metadata coverage for the new lineage fields.

## Verification

- Not run locally per request.
- Added focused coverage in `core/src/turn_metadata_tests.rs` and
`app-server/tests/suite/v2/client_metadata.rs`.
2026-05-29 11:28:12 -07:00
Ahmed Ibrahim 9abd55660e Centralize resolved multi-agent runtime version 2026-05-29 11:22:02 -07:00
Ahmed Ibrahim 7de051e1ec Keep multi-agent thread limits in config resolution 2026-05-29 11:09:42 -07:00
Ahmed Ibrahim d926f6c05e Simplify inherited multi-agent runtime handling 2026-05-29 11:05:59 -07:00
iceweasel-oai cb9178e8b3 Add Windows sandbox provisioning setup command (#24831)
## Why

Some Windows users do not have local admin access, so they cannot
complete the elevated portion of the Windows sandbox setup when Codex
first needs it. This adds an alpha provisioning path that an admin or IT
deployment script can run ahead of time for the Codex user.

The intended managed-deployment shape is:

```powershell
codex sandbox setup --elevated --user "$env:COMPUTERNAME\Alice" --codex-home "C:\Users\Alice\.codex"
```

`--elevated` is treated as the requested sandbox setup level, not as
proof that the process is elevated. The Windows sandbox setup
orchestration still checks that the caller is actually elevated before
launching the helper without a UAC prompt.

## What changed

- Added `codex sandbox setup --elevated` with explicit user selection
via either `--current-user` or `--user ... --codex-home ...`.
- Moved the CLI implementation into `cli/src/sandbox_setup.rs` instead
of growing `cli/src/main.rs`.
- Added a Windows sandbox `ProvisionOnly` helper mode that runs the
elevation-required provisioning work without requiring a workspace cwd
or runtime sandbox policy.
- Reused the existing elevated helper path for creating/updating sandbox
users, configuring firewall/WFP rules, and applying sandbox directory
ACLs.
- Persisted `windows.sandbox = "elevated"` into the target `CODEX_HOME`
so the desktop app does not show the initial sandbox setup banner after
pre-provisioning succeeds.

## Validation

- `cargo fmt -p codex-windows-sandbox -p codex-core -p codex-cli`
- `cargo test -p codex-cli sandbox_setup --target-dir
target\sandbox-setup-check`
- `cargo test -p codex-windows-sandbox
payload_accepts_provision_only_mode --target-dir
target\sandbox-setup-check`
- `git diff --check`
- Manual Windows alpha flow with a standard local user (`Mandi Lavida`):
ran the new setup command from an admin shell, verified the target
`.codex` contents, sandbox marker/secrets, ACLs, firewall rules, and
desktop startup without the sandbox setup banner once experimental
network proxy requirements were disabled.

## Notes

This intentionally does not solve later elevated update coordination for
IT-managed deployments. The setup command can still apply provisioning
updates when run again, but a broader coordination/process story is out
of scope for this alpha.
2026-05-29 11:01:44 -07:00
Ahmed Ibrahim e9ef90c361 Keep fork spawn options within clippy argument limit 2026-05-29 10:43:24 -07:00
Won Park 10b0399034 Route extension image generation through the native image completion pipeline (#24972)
## Why

The standalone `image_gen.imagegen` extension should behave like native
image generation for artifact persistence and UI completion, while
returning its save-location guidance as part of the tool result instead
of injecting a developer message.

## What Changed

- Added an image-generation completion hook for extension tools so core
can persist generated images and emit the existing `ImageGeneration`
lifecycle events.
- Reused core image artifact persistence for extension output and
removed extension-local save-path/file-writing logic.
- Split shared image persistence from built-in finalization so native
image generation keeps its existing developer-message instruction
behavior.
- Returned the generated image save-location instruction through the
extension `FunctionCallOutput`, alongside the generated image input for
model follow-up.
- Preserved the existing image-generation event shape for current UI and
replay compatibility.
- Avoided cloning the full generated-image base64 payload when emitting
the in-progress image item.
- Removed dependencies no longer needed after moving persistence out of
the extension crate.

## Fast Follow
- Adjust the existing Extension API and add a general `TurnItem`
finalization path for re-usability of code

## Validation

- Ran `just fmt`.
- Ran `just bazel-lock-update`.
- Ran `just bazel-lock-check`.
- Ran `just test -p codex-tools -p codex-extension-api -p
codex-image-generation-extension`.
- Ran `just test -p codex-core
image_generation_publication_is_finalized_by_core`.
- Ran `just test -p codex-core
handle_output_item_done_records_image_save_history_message`.
- Ran `just fix -p codex-tools -p codex-extension-api -p codex-core -p
codex-image-generation-extension`.
2026-05-29 17:33:13 +00:00
Ahmed Ibrahim 8193bcf143 Make spawned agents inherit parent multi-agent runtime 2026-05-29 10:31:46 -07:00
Adam Perry @ OpenAI 3e666dd32a [codex] Wait for MCP readiness in core integration tests (#24964)
Ensures MCP-backed `codex-core` integration tests exercise initialized
servers instead of racing server startup.

I've been idly investigating a few flakes and the failure modes are much
more confusing when a tool call fails because of a failed server start
than when the failed server start causes the test to fail directly.
2026-05-29 10:22:27 -07:00
Ahmed Ibrahim 7e7a9eb340 Use resolved multi-agent version across runtime 2026-05-29 10:19:34 -07:00
jif-oai f4e9d2caac Move config document helpers into their own module (#25110)
## Why

`core/src/config/edit.rs` owns the config edit state machine, but it
also carried the TOML document helper code inline as a nested module.
Moving those helpers into their own file keeps the edit orchestration
easier to scan without changing the config persistence behavior.

## What changed

- Moved the existing `document_helpers` module from
`core/src/config/edit.rs` into
`core/src/config/edit/document_helpers.rs`.
- Added `mod document_helpers;` so the existing `pub(super)` helper API
remains available to the rest of `config::edit`.

## Testing

Not run; this is a refactor-only module extraction with no intended
behavior change.
2026-05-29 18:49:21 +02:00
Ahmed Ibrahim abca78f62e Merge remote-tracking branch 'origin/main' into codex/model-info-multi-agent-version
# Conflicts:
#	codex-rs/app-server/tests/common/models_cache.rs
#	codex-rs/codex-api/tests/models_integration.rs
#	codex-rs/core/src/session/review.rs
#	codex-rs/core/src/session/turn_context.rs
#	codex-rs/core/src/tools/spec_plan.rs
#	codex-rs/core/src/tools/spec_plan_tests.rs
#	codex-rs/core/tests/suite/model_runtime_selectors.rs
#	codex-rs/core/tests/suite/model_switching.rs
#	codex-rs/core/tests/suite/models_cache_ttl.rs
#	codex-rs/core/tests/suite/personality.rs
#	codex-rs/core/tests/suite/remote_models.rs
#	codex-rs/core/tests/suite/rmcp_client.rs
#	codex-rs/core/tests/suite/spawn_agent_description.rs
#	codex-rs/core/tests/suite/view_image.rs
#	codex-rs/models-manager/src/model_info.rs
#	codex-rs/protocol/src/openai_models.rs
#	codex-rs/tools/src/tool_config_tests.rs
2026-05-29 09:14:58 -07:00
Ahmed Ibrahim aad293503c codex: address PR review feedback (#25032) 2026-05-29 09:06:20 -07:00
Ahmed Ibrahim 5577a9e148 [codex] Add model tool mode selector (#25031)
## Why
Some models need to select their code-execution behavior through model
catalog metadata. Models without that metadata must continue to follow
the existing `CodeMode` and `CodeModeOnly` feature flags, including when
a newer server sends an enum value this client does not recognize.

## What changed
- add optional `ModelInfo.tool_mode` metadata with `direct`,
`code_mode`, and `code_mode_only`
- treat omitted and unknown wire values as `None`
- resolve `None` from the existing feature flags
- carry the resolved `ToolMode` directly on `TurnContext`, outside
`Config`
- use the resolved value for turn creation, model switches, review
turns, tool planning, and code execution

## Coverage
- add protocol coverage for omitted, known, and unknown enum values
- add focused coverage for flag fallback and explicit metadata
overriding feature flags
- add core integration coverage that fetches remote model metadata
through `/v1/models` and verifies the outbound `/responses` tools for
explicit `direct` and `code_mode_only` selectors

## Stack
- followed by #25032
2026-05-29 09:05:05 -07:00
jif-oai 1c55bb2702 [codex] Improve built-in tool schema docs (#24794)
## Summary
- Clarify default, omission, and bounded behavior across built-in tool
schemas, including unified exec, classic shell, Code Mode exec/wait,
multi-agent, agent job, MCP resource, image, goal, plan, tool_search,
and test-sync fields.
- Convert update_plan status to an enum and add short field descriptions
where the schema previously relied on surrounding context.
- Remove the dedicated permission-approval schema test and keep only
updates to existing expected-spec tests.

## Validation
- Ran `just fmt`.
- Ran `git diff --check`.
- Did not run clippy or tests, per request.

Regression has been eval
[here](https://openai.slack.com/archives/C09GDSP1J9X/p1779905065496949)
and we proved there are no regressions
2026-05-29 13:32:19 +02:00
jif-oai 8f6a945ec9 Use inject_if_running for active goal steering (#24924)
## Why

This PR is stacked on #24918, which moves goal steering onto
source-labeled internal model context fragments. Active-turn goal
steering should use the same running-turn injection path as other
runtime steering, so those fragments enter the pending input queue as
`ResponseItem`s through the existing
[`Session::inject_if_running`](https://github.com/openai/codex/blob/8d6f6cdf69b055c27682e7cdea9caf72a3e2ee7f/codex-rs/core/src/session/inject.rs#L12-L27)
behavior instead of through a goal-specific conversion wrapper.

## What Changed

- Exposes a narrow `CodexThread::inject_if_running` bridge for callers
that only hold a thread handle.
- Changes `ext/goal` active-turn steering to pass `ResponseItem`s
directly.
- Builds goal steering prompts as contextual internal model context
`ResponseItem`s before injecting them into the running turn.

## Testing

Not run locally; PR metadata update only.
2026-05-29 11:24:39 +02:00
Ahmed Ibrahim ebe85c8af5 codex: assert serialized v1 namespace tool order 2026-05-29 01:31:33 -07:00
Ahmed Ibrahim 6261f33a4f codex: fix CI failure on PR #25032 2026-05-29 01:30:58 -07:00
Ahmed Ibrahim a50eb62cd0 [codex] Add multi-agent selector integration coverage 2026-05-29 01:30:58 -07:00
Ahmed Ibrahim 581291bf68 [codex] Inline multi-agent version resolution 2026-05-29 01:30:58 -07:00
Ahmed Ibrahim 129b77b71b [codex] Resolve multi-agent version on turn context 2026-05-29 01:30:58 -07:00
Ahmed Ibrahim 512655e4b0 [codex] Simplify multi-agent version selection 2026-05-29 01:30:57 -07:00
Ahmed Ibrahim 1f68c3dbdd [codex] Add model multi-agent version selector 2026-05-29 01:30:57 -07:00
Ahmed Ibrahim e558c37be5 codex: assert direct selector behavior independent of shell family 2026-05-29 01:30:56 -07:00
jif-oai 740d942f90 Use internal model context fragments for goal steering (#24918)
## Why

Goal steering is one form of runtime-owned model context, but the old
`<goal_context>` wrapper made the contextual-fragment hiding path
goal-specific. Using a source-labeled internal context fragment gives
core and extensions a shared shape for hidden model steering while
keeping those prompts out of visible turn history.

The change also keeps legacy `<goal_context>` messages recognized as
hidden contextual input so existing stored history does not start
rendering old goal-steering prompts as user-visible turn items.

## What Changed

- Replaces `GoalContext` with `InternalModelContextFragment` plus a
validated `InternalContextSource`.
- Renders goal steering as `<codex_internal_context
source="goal">...</codex_internal_context>`.
- Updates core goal steering and `ext/goal` steering to inject the new
internal-context fragment.
- Updates contextual-fragment, event-mapping, goal, and session tests
for the new wrapper.

## Test Coverage

- Adds coverage for detecting the new internal model context fragment.
- Preserves coverage for hiding legacy `<goal_context>` fragments.
- Verifies invalid internal context sources are rejected and arbitrary
context tags are not hidden.
- Updates goal steering/session assertions to expect the new
`source="goal"` wrapper.
2026-05-29 10:28:25 +02:00
Ahmed Ibrahim 79de1ac6f7 codex: preserve model switch in selector integration test 2026-05-29 01:23:24 -07:00
Ahmed Ibrahim 1657ac2983 codex: refresh remote model fixture in selector integration test 2026-05-29 01:10:58 -07:00
Ahmed Ibrahim b030e34870 codex: fix CI failure on PR #25031 2026-05-29 00:57:20 -07:00
Ahmed Ibrahim dbf5762796 [codex] Expose selector integration response body 2026-05-29 00:48:07 -07:00
Ahmed Ibrahim ad9ab6eb34 [codex] Add tool mode selector integration coverage 2026-05-29 00:46:37 -07:00
Ahmed Ibrahim c1713608ac [codex] Inline tool mode resolution 2026-05-29 00:40:33 -07:00
Ahmed Ibrahim b138a8a992 [codex] Use ToolMode as resolved runtime value 2026-05-29 00:18:53 -07:00
Ahmed Ibrahim 7c264fbbd2 [codex] Keep tool mode runtime state out of config 2026-05-29 00:07:40 -07:00
Ahmed Ibrahim 1756422e41 [codex] Add model tool mode metadata selector 2026-05-29 00:00:20 -07:00
Michael Bolin 6e10142199 fix: preserve deny-read sandboxing for safe commands (#23943)
## Why

Permission profiles can mark filesystem entries as unreadable with
`deny` rules, including glob patterns. Several shell execution paths
treated known-safe commands or execpolicy `allow` rules as sufficient to
run outside the filesystem sandbox. That is not valid for read-capable
commands: for example, `cat` or `ls` may be reasonable to allow
generally, but dropping the sandbox would also drop deny-read
constraints such as `**/*.env`.

## What changed

- Added a shared check that treats active deny-read restrictions as
incompatible with unsandboxed execution.
- Kept first-attempt execution sandboxed for explicit escalation and
execpolicy allow bypasses when deny-read entries are present.
- Prevented no-sandbox retry after a sandbox denial when the active
filesystem policy contains deny-read entries.
- Updated the zsh-fork execve path so prefix-rule `allow` decisions
continue inside the current sandbox when deny-read restrictions are
active.

## Verification

- `cargo test -p codex-core tools::sandboxing::tests`
- `cargo test -p codex-core
tools::runtimes::shell::unix_escalation::tests`
- `cargo test -p codex-core
shell_command_enforces_glob_deny_read_policy`
2026-05-28 22:49:37 -07:00
viyatb-oai bf72be5927 fix(config): use deny for Unix socket permissions (#24970)
## Why

Unix socket permissions still accepted and displayed `"none"` while file
permissions use the clearer `"deny"` spelling. This keeps network Unix
socket policy vocabulary consistent with filesystem policy vocabulary.

## What changed

- Replace the Unix socket permission variant and serialized spelling
from `none` to `deny` across config, feature configuration, and network
proxy types.
- Update app-server v2 serialization, TUI debug output, focused tests,
and generated schemas to expose `"deny"`.
- Add coverage for denied Unix socket entries in managed requirements
and profile overlay behavior.

## Security

This is a vocabulary change for explicit Unix socket rejection, not a
network access expansion. Denied entries continue to be omitted from the
effective allowlist.

## Validation

- `just fmt`
- `just write-config-schema`
- `just write-app-server-schema`
- `just test -p codex-config -p codex-core -p codex-app-server-protocol
-p codex-tui -E
'test(network_requirements_are_preserved_as_constraints_with_source) |
test(network_permission_containers_project_allowed_and_denied_entries) |
test(network_toml_overlays_unix_socket_permissions_by_path) |
test(permissions_profiles_resolve_extends_parent_first_with_child_overrides)
| test(network_requirements_serializes_canonical_and_legacy_fields) |
test(debug_config_output_formats_unix_socket_permissions)'`\n- Automatic
`bench-smoke` follow-up from `just test`\n- `cargo clippy -p
codex-config -p codex-core -p codex-features -p codex-network-proxy -p
codex-app-server-protocol -p codex-app-server -p codex-tui --all-targets
-- -D warnings`
2026-05-28 23:53:26 +00:00
Michael Bolin 986c60467b windows-sandbox: pass workspace roots to runner (#24108)
## Why

#23813 switches the Windows sandbox runner path to `PermissionProfile`,
but it still left one runtime anchor for resolving symbolic
`:workspace_roots` entries. That is not enough once a turn has multiple
effective workspace roots: exact entries and deny globs under
`:workspace_roots` need to be materialized for every runtime root before
the command runner chooses token mode or builds ACL plans.

## What Changed

- Replaces the Windows runner/setup `permission_profile_cwd` plumbing
with `workspace_roots: Vec<AbsolutePathBuf>`.
- Resolves Windows-local `PermissionProfile` data with
`materialize_project_roots_with_workspace_roots(...)` instead of the
single-cwd helper.
- Threads `Config::effective_workspace_roots()` through core execution,
unified exec, TUI setup/read-grant flows, app-server setup, app-server
`command/exec`, and `debug sandbox` on Windows.
- Preserves those workspace roots through the zsh-fork escalation
executor instead of rebuilding them from `sandbox_policy_cwd`.
- Makes `ExecRequest::new(...)` and the remaining
`build_exec_request(...)` helper path take
`windows_sandbox_workspace_roots` explicitly so new call sites cannot
silently fall back to `vec![cwd]`.
- Clarifies the `debug sandbox` non-Windows comment: remaining
cwd-dependent resolution still uses `sandbox_policy_cwd`, while
`:workspace_roots` entries are already materialized from config roots.
- Updates elevated runner IPC `SpawnRequest` to send `workspace_roots`
and bumps the framed IPC protocol version to `3` for the payload shape
change.
- Adds Windows-local resolver coverage for expanding exact and glob
`:workspace_roots` entries across multiple roots, plus core helper
coverage proving explicit roots are preserved.

## Verification

- `cargo check -p codex-windows-sandbox -p codex-core -p codex-tui -p
codex-cli -p codex-app-server`
- `cargo test -p codex-windows-sandbox`
- `cargo test -p codex-core windows_sandbox`
- `cargo test -p codex-core unix_escalation`
- `cargo test -p codex-app-server windows_sandbox`
- `cargo test -p codex-tui windows_sandbox`
- `cargo test -p codex-cli debug_sandbox`
- `just test -p codex-core unified_exec`
- `just test -p codex-core
build_exec_request_preserves_windows_workspace_roots`
- `env -u CODEX_NETWORK_PROXY_ACTIVE -u
CODEX_NETWORK_ALLOW_LOCAL_BINDING just test -p codex-app-server --lib
command_exec`
- `just test -p codex-windows-sandbox`
- `just test -p codex-exec sandbox`
- `just fix -p codex-core -p codex-app-server -p codex-windows-sandbox`

A local macOS cross-check with `cargo check --target
x86_64-pc-windows-msvc ...` did not reach crate Rust code because native
dependencies require Windows SDK headers (`windows.h` / `assert.h`) in
this environment; Windows CI remains the real target validation.

Two local targeted filters compile but do not run assertions on macOS:
`env -u CODEX_NETWORK_PROXY_ACTIVE -u CODEX_NETWORK_ALLOW_LOCAL_BINDING
just test -p codex-app-server --lib command_exec_processor` matched zero
tests, and `just test -p codex-linux-sandbox landlock` matched zero
tests because the landlock suite is Linux-only.
2026-05-28 15:26:55 -07:00
Michael Bolin e7dda8070e Surface filesystem permission profiles in prompt context (#23924)
## Summary
Some permission profiles can encode filesystem reads that should remain
unavailable to the agent. Before this change, the model-visible context
and automatic approval review prompt summarized the effective
permissions as a legacy sandbox mode, which can omit permission-profile
filesystem entries from escalation decisions.

For example, a profile can grant workspace access while denying a
private subtree across every workspace root:

```toml
default_permissions = "restricted-workspace"

[permissions.restricted-workspace.workspace_roots]
"/Users/alice/project" = true
"/Users/alice/other-project" = true

[permissions.restricted-workspace.filesystem]
":minimal" = "read"

[permissions.restricted-workspace.filesystem.":workspace_roots"]
"." = "write"
"private" = "deny"
"private/**" = "deny"
```

The context window now describes the workspace roots and effective
filesystem side of the `PermissionProfile` directly, with deny entries
marked as non-escalatable:

```xml
<environment_context>
  <cwd>/Users/alice/project</cwd>
  <shell>zsh</shell>
  <filesystem><workspace_roots><root>/Users/alice/project</root><root>/Users/alice/other-project</root></workspace_roots><permission_profile type="managed"><file_system type="restricted"><entry access="read"><special>:minimal</special></entry><entry access="write"><path>/Users/alice/project</path></entry><entry access="write"><path>/Users/alice/other-project</path></entry><entry access="deny" escalatable="false"><path>/Users/alice/project/private</path></entry><entry access="deny" escalatable="false"><path>/Users/alice/other-project/private</path></entry><entry access="deny" escalatable="false"><glob>/Users/alice/project/private/**</glob></entry><entry access="deny" escalatable="false"><glob>/Users/alice/other-project/private/**</glob></entry></file_system></permission_profile></filesystem>
</environment_context>
```

Managed requirements can impose the same kind of deny-read restriction:

```toml
[permissions.filesystem]
deny_read = [
  "/Users/alice/project/private",
  "/Users/alice/project/private/**",
]
```

The automatic approval review prompt also receives the parent turn's
denied-read context, so review decisions can account for the active
permission profile.

## What Changed
- Render the effective filesystem profile in `<environment_context>`,
including profile type, filesystem entries, workspace roots, and
non-escalatable deny entries.
- Persist effective `workspace_roots` in `TurnContextItem` so
resumed/replayed context does not have to bind `:workspace_roots`
through legacy `cwd` fallback.
- Add explicit permission instructions that denied reads are policy
restrictions, not escalation targets.
- Pass the parent turn's denied-read context into automatic approval
reviews.
- Add targeted coverage for prompt rendering, workspace-root
materialization, replay context, and review prompt context.
- Keep the prompt-context test expectations platform-aware so the same
filesystem rendering assertions pass on Unix and Windows paths.

## Testing
- `just test -p codex-core
context::environment_context::tests::serialize_environment_context_with_full_filesystem_profile`
- `just test -p codex-core
context::environment_context::tests::turn_context_item_filesystem_uses_workspace_roots_instead_of_cwd`
- `just test -p codex-core
context::permissions_instructions::permissions_instructions_tests::builds_permissions_from_profile_with_denied_reads`
- `just fix -p codex-core`

I also attempted `just test -p codex-core`; the changed prompt-context
tests passed, but the full local run did not complete cleanly in this
sandboxed macOS environment due unrelated user-shell `CODEX_SANDBOX*`
expectations and integration-test timeouts.
2026-05-28 14:56:53 -07:00