Commit Graph

4502 Commits

  • Fix codex exec --profile handling (#14524)
    PR #14005 introduced a regression whereby `codex exec --profile`
    overrides were dropped when starting or resuming a thread. That causes
    the thread to miss profile-scoped settings like
    `model_instructions_file`.
    
    This PR preserve the active profile in the thread start/resume config
    overrides so the
    app-server rebuild sees the same profile that exec resolved. 
    
    Fixes #14515
  • Reapply "Pass more params to compaction" (#14298) (#14521)
    This reverts commit 8af97ce4b08fdedadc6037851b5e20cc653e9536.
    
    Confirmed that this runs locally without the previous issues with tool
    use
  • Expose code-mode tools through globals (#14517)
    Summary
    - make all code-mode tools accessible as globals so callers only need
    `tools.<name>`
    - rename text/image helpers and key globals (store, load, ALL_TOOLS,
    etc.) to reflect the new shared namespace
    - update the JS bridge, runners, descriptions, router, and tests to
    follow the new API
    
    Testing
    - Not run (not requested)
  • Persist js_repl codex helpers across cells (#14503)
    ## Summary
    
    This changes `js_repl` so saved references to `codex.tool(...)` and
    `codex.emitImage(...)` keep working across cells.
    
    Previously, those helpers were recreated per exec and captured that
    exec's `message.id`. If a persisted object or saved closure reused an
    old helper in a later cell, the nested tool/image call could fail with
    `js_repl exec context not found`.
    
    This patch:
    - keeps stable `codex.tool` and `codex.emitImage` helper identities in
    the kernel
    - resolves the current exec dynamically at call time using
    `AsyncLocalStorage`
    - adds regression coverage for persisted helper references across cells
    - updates the js_repl docs and project-doc instructions to describe the
    new behavior and its limits
    
    ## Why
    
    We already support persistent top-level bindings across `js_repl` cells,
    so persisted objects should be able to reuse `codex` helpers in later
    active cells. The bug was that helper identity was exec-scoped, not
    kernel-scoped.
    
    Using `AsyncLocalStorage` fixes the cross-cell reuse case without
    falling back to a single global active exec that could accidentally
    attribute stale background callbacks to the wrong cell.
  • Update tool search prompts (#14500)
    - [x] Add mentions of connectors because model always think in connector
    terms in its CoT.
    - [x] Suppress list_mcp_resources in favor of tool search for available
    apps.
  • Rename exec session IDs to cell IDs (#14510)
    - Update the code-mode executor, wait handler, and protocol plumbing to
    use cell IDs instead of session IDs for node communication
    - Switch tool metadata, wait description, and suite tests to refer to
    cell IDs so user-visible messages match the new terminology
    
    **Testing**
    - Not run (not requested)
  • memories: focus write prompts on user preferences (#14493)
    ## Summary
    - update `codex-rs/core/templates/memories/stage_one_system.md` so phase
    1 captures stronger user-preference signals, richer task summaries, and
    cwd provenance without branch-specific fields
    - update `codex-rs/core/templates/memories/consolidation.md` so phase 2
    keeps separate sections for user preferences, reusable knowledge, and
    failure shields while staying cwd-aware but branchless
    - document the `codex` prompt-template maintenance rule in
    `codex-rs/core/src/memories/README.md`: the undated templates are
    canonical here and should be edited in place
    
    ## Testing
    - cargo test -p codex-core memories --manifest-path codex-rs/Cargo.toml
  • Fix MCP tool calling (#14491)
    Properly escape mcp tool names and make tools only available via
    imports.
  • Skip nested tool call parallel test on Windows (#14505)
    **Summary**
    - disable the `code_mode_nested_tool_calls_can_run_in_parallel` test on
    Windows where `exec_command` is unavailable
    
    **Testing**
    - Not run (not requested)
  • Fix js_repl hangs on U+2028/U+2029 dynamic tool responses (#14421)
    ## Summary
    Dynamic tool responses containing literal U+2028 / U+2029 would cause
    await codex.tool(...) to hang even though the response had already
    arrived. This PR replaces the kernel’s readline-based stdin handling
    with byte-oriented JSONL framing that handles these characters properly.
    
    ## Testing
    - `cargo test -p codex-core`
    - tested the binary on a repro case and confirmed it's fixed
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Reuse tool runtime for code mode worker (#14496)
    ## Summary
    - create the turn-scoped `ToolCallRuntime` before starting the code mode
    worker so the worker reuses the same runtime and router
    - thread the shared runtime through the code mode service/worker path
    and use it for nested tool calls
    - model aborted tool calls as a concrete `ToolOutput` so aborted
    responses still produce valid tool output shapes
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-core` (still running locally)
  • fix turn_start_jsonrpc_span_parents_core_turn_spans flakiness (#14490)
    This makes the test less flaky by checking the core invariant instead of
    the full span chain.
    
    Before, the test waited for several specific internal spans
    (`submission_dispatch`, `session_task.turn`, `run_turn`) and asserted
    their exact relationships. That was brittle because those spans are
    exported asynchronously and are more of an implementation detail than
    the thing we actually care about.
    
    Now, the test only checks that:
    - `turn/start` is on the expected remote trace with the expected remote
    parent
    - at least one representative core turn span on that same trace descends
    from it
    
    That keeps the sanity-check we want while making the test less sensitive
    to timing and internal refactors.
  • chore(app-server): stop exporting EventMsg schemas (#14478)
    Follow up to https://github.com/openai/codex/pull/14392, stop exporting
    EventMsg types to TypeScript and JSON schema since we no longer emit
    them.
  • Add parallel tool call test (#14494)
    Summary
    - pin tests to `test-gpt-5.1-codex` so code-mode suites exercise that
    model explicitly
    - add a regression test that ensures nested tool calls can execute in
    parallel and assert on timing
    - refresh `codex-rs/Cargo.lock` for the updated dependency tree (add
    `codex-utils-pty`, drop `codex-otel`)
    
    Testing
    - Not run (not requested)
  • Add default code-mode yield timeout (#14484)
    Summary
    - expose the default yield timeout through code mode runtime so the
    handler, wait tool, and protocol share the same 10s value that matches
    unified exec
    - document the timeout change in the tool descriptions and propagate the
    value all the way into the runner metadata
    - adjust Cargo.lock to keep the dependency tree in sync with the added
    code mode tool dependency
    
    Testing
    - Not run (not requested)
  • use scopes_supported for OAuth when present on MCP servers (#14419)
    Fixes [#8889](https://github.com/openai/codex/issues/8889).
    
    ## Summary
    - Discover and use advertised MCP OAuth `scopes_supported` when no
    explicit or configured scopes are present.
    - Apply the same scope precedence across `mcp add`, `mcp login`, skill
    dependency auto-login, and app-server MCP OAuth login.
    - Keep discovered scopes ephemeral and non-persistent.
    - Retry once without scopes for CLI and skill auto-login flows if the
    OAuth provider rejects discovered scopes.
    
    ## Motivation
    Some MCP servers advertise the scopes they expect clients to request
    during OAuth, but Codex was ignoring that metadata and typically
    starting OAuth with no scopes unless the user manually passed `--scopes`
    or configured `server.scopes`.
    
    That made compliant MCP servers harder to use out of the box and is the
    behavior described in
    [#8889](https://github.com/openai/codex/issues/8889).
    
    This change also brings our behavior in line with the MCP authorization
    spec's scope selection guidance:
    
    https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#scope-selection-strategy
    
    ## Behavior
    Scope selection now follows this order everywhere:
    1. Explicit request scopes / CLI `--scopes`
    2. Configured `server.scopes`
    3. Discovered `scopes_supported`
    4. Legacy empty-scope behavior
    
    Compatibility notes:
    - Existing working setups keep the same behavior because explicit and
    configured scopes still win.
    - Discovered scopes are never written back into config or token storage.
    - If discovery is missing, malformed, or empty, behavior falls back to
    the previous empty-scope path.
    - App-server login gets the same precedence rules, but does not add a
    transparent retry path in this change.
    
    ## Implementation
    - Extend streamable HTTP OAuth discovery to parse and normalize
    `scopes_supported`.
    - Add a shared MCP scope resolver in `core` so all login entrypoints use
    the same precedence rules.
    - Preserve provider callback errors from the OAuth flow so CLI/skill
    flows can safely distinguish provider rejections from other failures.
    - Reuse discovered scopes from the existing OAuth support check where
    possible instead of persisting new config.
  • Do not allow unified_exec for sandboxed scenarios on Windows (#14398)
    as reported in https://github.com/openai/codex/issues/14367 users can
    explicitly enable unified_exec which will bypass the sandbox even when
    it should be enabled.
    
    Until we support unified_exec with the Windows Sandbox, we will disallow
    it unless the sandbox is disabled
  • Handle malformed agent role definitions nonfatally (#14488)
    ## Summary
    - make malformed agent role definitions nonfatal during config loading
    - drop invalid agent roles and record warnings in `startup_warnings`
    - forward startup warnings through app-server `configWarning`
    notifications
    
    ## Testing
    - `cargo test -p codex-core agent_role_ -- --nocapture`
    - `just fix -p codex-core`
    - `just fmt`
    - `cargo test -p codex-app-server config_warning -- --nocapture`
    
    Co-authored-by: Codex <noreply@openai.com>
  • Cleanup code_mode tool descriptions (#14480)
    Move to separate files and clarify a bit.
  • fix: preserve split filesystem semantics in linux sandbox (#14173)
    ## Stack
    
       fix: fail closed for unsupported split windows sandboxing #14172
    -> fix: preserve split filesystem semantics in linux sandbox #14173
       fix: align core approvals with split sandbox policies #14171
       refactor: centralize filesystem permissions precedence #14174
    
    ## Summary
    ## Summary
    - Preserve Linux split filesystem carveouts in bubblewrap by applying
    mount masks in the right order, so narrower rules still win under
    broader writable roots.
    - Preserve unreadable ancestors of writable roots by masking them first
    and then rebinding the narrower writable descendants.
    - Stop rejecting legacy-plus-split Linux configs that are
    sandbox-equivalent after `cwd` resolution by comparing semantics instead
    of raw legacy structs.
    - Fail closed when callers provide partial split policies, mismatched
    legacy-plus-split policies, or force `--use-legacy-landlock` for
    split-only shapes that legacy Landlock cannot enforce.
    - Add Linux regressions for overlapping writable, read-only, and denied
    paths, and document the supported split-policy enforcement path.
    
    ## Example
    Given a split filesystem policy like:
    
    ```toml
    [permissions.dev.filesystem]
    ":root" = "read"
    "/code" = "write"
    "/code/.git" = "read"
    "/code/secrets" = "none"
    "/code/secrets/tmp" = "write"
    ```
    
    this PR makes Linux enforce the intended result under bubblewrap:
    
    - `/code` stays writable
    - `/code/.git` stays read-only
    - `/code/secrets` stays denied
    - `/code/secrets/tmp` can still be reopened as writable if explicitly
    allowed
    
    Before this, Linux could lose one of those carveouts depending on mount
    order or legacy-policy fallback. This PR keeps the split-policy
    semantics intact and rejects configurations that legacy Landlock cannot
    represent safely.
  • rename spawn_csv feature flag to enable_fanout (#14475)
    ## Summary
    - rename the public feature flag for `spawn_agents_on_csv()` from
    `spawn_csv` to `enable_fanout`
    - regenerate the config schema so only `enable_fanout` is advertised
    - keep the behavior the same: enabling `enable_fanout` still pulls in
    `multi_agent`
    
    ## Notes
    - this is a hard rename with no `spawn_csv` compatibility alias
    - the internal enum remains `Feature::SpawnCsv` to keep the patch small
    
    ## Testing
    - `cd codex-rs && just fmt`
    - `cd codex-rs && cargo test -p codex-core` (running locally;
    `suite::agent_jobs::*` and rename-specific coverage passed so far)
  • Move code mode tool files under tools/code_mode and split functionality (#14476)
    - **Summary**
    - migrate the code mode handler, service, worker, process, runner, and
    bridge assets into the `tools/code_mode` module tree
    - split Execution, protocol, and handler logic into dedicated files and
    relocate the tool definition into `code_mode/spec.rs`
    - update core references and tests to stitch the new organization
    together
    - **Testing**
      - Not run (not requested)
  • Fix stdio-to-uds peer-close flake (#13882)
    ## What changed
    - `codex-stdio-to-uds` now tolerates `NotConnected` when
    `shutdown(Write)` happens after the peer has already closed.
    - The socket test was rewritten to send stdin from a fixture file and to
    read an exact request payload length instead of waiting on EOF timing.
    
    ## Why this fixes the flake
    - This one exposed a real cross-platform runtime edge case: on macOS,
    the peer can close first after a successful exchange, and
    `shutdown(Write)` can report `NotConnected` even though the interaction
    already succeeded.
    - Treating that specific ordering as a harmless shutdown condition
    removes the production-level false failure.
    - The old test compounded the problem by depending on EOF timing, which
    varies by platform and scheduler. Exact-length IO makes the test
    deterministic and focused on the actual data exchange.
    
    ## Scope
    - Production logic change with matching test rewrite.
  • fix(cli): support legacy use_linux_sandbox_bwrap flag (#14473)
    ## Summary
    - restore `use_linux_sandbox_bwrap` as a removed feature key so older
    `--enable` callers parse again
    - keep it as a no-op by leaving runtime behavior unchanged
    - add regression coverage for the legacy `--enable` path
    
    ## Testing
    - Not run (updated and pushed quickly)
  • Add Python app-server SDK (#14435)
    ## TL;DR
    Bring the Python app-server SDK from `main-with-prs-13953-and-14232`
    onto current `main` as a standalone SDK-only PR.
    
    - adds the new `sdk/python` and `sdk/python-runtime` package trees
    - keeps the scope to the SDK payload only, without the unrelated
    branch-history or workflow changes from the source branch
    - regenerates `sdk/python/src/codex_app_server/generated/v2_all.py`
    against current `main` schema so the extracted SDK matches today's
    protocol definitions
    
    ## Validation
    - `PYTHONPATH=sdk/python/src python3 -m pytest sdk/python/tests`
    
    Co-authored-by: Codex <noreply@openai.com>
  • Dispatch tools when code mode is not awaited directly (#14437)
    ## Summary
    - start a code mode worker once per turn and let it pump nested tool
    calls through a dedicated queue
    - simplify code mode request/response dispatch around request ids and
    generic runner-unavailable errors
    - clean up the code mode process API and runner protocol plumbing
    
    ## Testing
    - not run yet
  • fix: move inline codex-rs/core unit tests into sibling files (#14444)
    ## Why
    PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This
    applies the same extraction pattern across the rest of `codex-rs/core`
    so the production modules stay focused on runtime code instead of large
    inline test blocks.
    
    Keeping the tests in sibling files also makes follow-up edits easier to
    review because product changes no longer have to share a file with
    hundreds or thousands of lines of test scaffolding.
    
    ## What changed
    - replaced each inline `mod tests { ... }` in `codex-rs/core/src/**`
    with a path-based module declaration
    - moved each extracted unit test module into a sibling `*_tests.rs`
    file, using `mod_tests.rs` for `mod.rs` modules
    - preserved the existing `cfg(...)` guards and module-local structure so
    the refactor remains structural rather than behavioral
    
    ## Testing
    - `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`)
    - `just fix -p codex-core`
    - `cargo fmt --check`
    - `cargo shear`
  • [elicitation] User-friendly tool call messages. (#14403)
    - [x] Add a curated set of tool call messages and human-readable tool
    param names.
  • fix: follow up on linux sandbox review nits (#14440)
    ## Summary
    - address the follow-up review nits from #13996 in a separate PR
    - make the approvals test command a raw string and keep the
    managed-network path using env proxy routing
    - inline `--apply-seccomp-then-exec` in the Linux sandbox inner command
    builder
    - remove the bubblewrap-specific sandbox metric tag path and drop the
    `use_legacy_landlock` shim from `sandbox_tag`/`TurnMetadataState::new`
    - restore the `Feature` import that `origin/main` currently still needs
    in `connectors.rs`
    
    ## Testing
    - `cargo test -p codex-linux-sandbox`
    - focused `codex-core` tests were rerun/started, but the final
    verification pass was interrupted when I pushed at request
  • refactor: make bubblewrap the default Linux sandbox (#13996)
    ## Summary
    - make bubblewrap the default Linux sandbox and keep
    `use_legacy_landlock` as the only override
    - remove `use_linux_sandbox_bwrap` from feature, config, schema, and
    docs surfaces
    - update Linux sandbox selection, CLI/config plumbing, and related
    tests/docs to match the new default
    - fold in the follow-up CI fixes for request-permissions responses and
    Linux read-only sandbox error text
  • feat: refactor on openai-curated plugins. (#14427)
    - Curated repo sync now uses GitHub HTTP, not local git.
    - Curated plugin cache/versioning now uses commit SHA instead of local.
    - Startup sync now always repairs or refreshes curated plugin cache from
    tmp (auto update to the lastest)
  • Support waiting for code_mode sessions (#14295)
    ## Summary
    - persist the code mode runner process in the session-scoped code mode
    store
    - switch the runner protocol from `init` to `start` with explicit
    session ids
    - handle runner-side session processing without the init waiter queue
    
    ## Validation
    - just fmt
    - cargo check -p codex-core
    - node --check codex-rs/core/src/tools/code_mode_runner.cjs
  • Clarify spawn agent authorization (#14432)
    - Clarify that spawn_agent requires explicit user permission for
    delegation or parallel agent work.
    - Add a regression test covering the new description text.
  • [apps] Add tool_suggest tool. (#14287)
    - [x] Add tool_suggest tool.
    - [x] Move chatgpt/src/connectors.rs and core/src/connectors.rs into a
    dedicated mod so that we have all the logic and global cache in one
    place.
    - [x] Update TUI app link view to support rendering the installation
    view for mcp elicitation.
    
    ---------
    
    Co-authored-by: Shaqayeq <shaqayeq@openai.com>
    Co-authored-by: Eric Traut <etraut@openai.com>
    Co-authored-by: pakrym-oai <pakrym@openai.com>
    Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
    Co-authored-by: guinness-oai <guinness@openai.com>
    Co-authored-by: Eugene Brevdo <ebrevdo@users.noreply.github.com>
    Co-authored-by: Charlie Guo <cguo@openai.com>
    Co-authored-by: Fouad Matin <fouad@openai.com>
    Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
    Co-authored-by: xl-openai <xl@openai.com>
    Co-authored-by: alexsong-oai <alexsong@openai.com>
    Co-authored-by: Owen Lin <owenlin0@gmail.com>
    Co-authored-by: sdcoffey <stevendcoffey@gmail.com>
    Co-authored-by: Codex <noreply@openai.com>
    Co-authored-by: Won Park <won@openai.com>
    Co-authored-by: Dylan Hurd <dylan.hurd@openai.com>
    Co-authored-by: celia-oai <celia@openai.com>
    Co-authored-by: gabec-openai <gabec@openai.com>
    Co-authored-by: joeytrasatti-openai <joey.trasatti@openai.com>
    Co-authored-by: Leo Shimonaka <leoshimo@openai.com>
    Co-authored-by: Rasmus Rygaard <rasmus@openai.com>
    Co-authored-by: maja-openai <163171781+maja-openai@users.noreply.github.com>
    Co-authored-by: pash-openai <pash@openai.com>
    Co-authored-by: Josh McKinney <joshka@openai.com>
  • chore: use AVAILABLE and ON_INSTALL as default plugin install and auth policies (#14407)
    make `AVAILABLE` the default plugin installPolicy when unset in
    `marketplace.json`. similarly, make `ON_INSTALL` the default authPolicy.
    
    this means, when unset, plugins are available to be installed (but not
    auto-installed), and the contained connectors will be authed at
    install-time.
    
    updated tests.
  • feat(app-server): propagate traces across tasks and core ops (#14387)
    ## Summary
    
    This PR keeps app-server RPC request trace context alive for the full
    lifetime of the work that request kicks off (e.g. for `thread/start`,
    this is `app-server rpc handler -> tokio background task -> core op
    submissions`). Previously we lose trace lineage once the request handler
    returns or hands work off to background tasks.
    
    This approach is especially relevant for `thread/start` and other RPC
    handlers that run in a non-blocking way. In the near future we'll most
    likely want to make all app-server handlers run in a non-blocking way by
    default, and only queue operations that must operate in order (e.g.
    thread RPCs per thread?), so we want to make sure tracing in app-server
    just generally works.
    
    Depends on https://github.com/openai/codex/pull/14300
    
    **Before**
    <img width="155" height="207" alt="image"
    src="https://github.com/user-attachments/assets/c9487459-36f1-436c-beb7-fafeb40737af"
    />
    
    
    **After**
    <img width="299" height="337" alt="image"
    src="https://github.com/user-attachments/assets/727392b2-d072-4427-9dc4-0502d8652dea"
    />
    
    ## What changed
    
    - Keep request-scoped trace context around until we send the final
    response or error, or the connection closes.
    - Thread that trace context through detached `thread/start` work so
    background startup stays attached to the originating request.
    - Pass request trace context through to downstream core operations,
    including:
      - thread creation
      - resume/fork flows
      - turn submission
      - review
      - interrupt
      - realtime conversation operations
    - Add tracing tests that verify:
      - remote W3C trace context is preserved for `thread/start`
      - remote W3C trace context is preserved for `turn/start`
      - downstream core spans stay under the originating request span
      - request-scoped tracing state is cleaned up correctly
    - Clean up shutdown behavior so detached background tasks and spawned
    threads are drained before process exit.
  • Include spawn agent model metadata in app-server items (#14410)
    - add model and reasoning effort to app-server collab spawn items and
    notifications
    - regenerate app-server protocol schemas for the new fields
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • fix: align core approvals with split sandbox policies (#14171)
    ## Stack
    
       fix: fail closed for unsupported split windows sandboxing #14172
       fix: preserve split filesystem semantics in linux sandbox #14173
    -> fix: align core approvals with split sandbox policies #14171
       refactor: centralize filesystem permissions precedence #14174
    
    ## Why This PR Exists
    
    This PR is intentionally narrower than the title may suggest.
    
    Most of the original split-permissions migration already landed in the
    earlier `#13434 -> #13453` stack. In particular:
    
    - `#13439` already did the broad runtime plumbing for split filesystem
    and network policies.
    - `#13445` already moved `apply_patch` safety onto filesystem-policy
    semantics.
    - `#13448` already switched macOS Seatbelt generation to split policies.
    - `#13449` and `#13453` already handled Linux helper and bubblewrap
    enforcement.
    - `#13440` already introduced the first protocol-side helpers for
    deriving effective filesystem access.
    
    The reason this PR still exists is that after the follow-on
    `[permissions]` work and the new shared precedence helper in `#14174`, a
    few core approval paths were still deciding behavior from the legacy
    `SandboxPolicy` projection instead of the split filesystem policy that
    actually carries the carveouts.
    
    That means this PR is mostly a cleanup and alignment pass over the
    remaining core consumers, not a fresh sandbox backend migration.
    
    ## What Is Actually New Here
    
    - make unmatched-command fallback decisions consult
    `FileSystemSandboxPolicy` instead of only legacy `DangerFullAccess` /
    `ReadOnly` / `WorkspaceWrite` categories
    - thread `file_system_sandbox_policy` into the shell, unified-exec, and
    intercepted-exec approval paths so they all use the same split-policy
    semantics
    - keep `apply_patch` safety on the same effective-access rules as the
    shared protocol helper, rather than letting it drift through
    compatibility projections
    - add loader-level regression coverage proving legacy `sandbox_mode`
    config still builds split policies and round-trips back without semantic
    drift
    
    ## What This PR Does Not Do
    
    This PR does not introduce new platform backend enforcement on its own.
    
    - Linux backend parity remains in `#14173`.
    - Windows fail-closed handling remains in `#14172`.
    - The shared precedence/model changes live in `#14174`.
    
    ## Files To Focus On
    
    - `core/src/exec_policy.rs`: unmatched-command fallback and approval
    rendering now read the split filesystem policy directly
    - `core/src/tools/sandboxing.rs`: default exec-approval requirement keys
    off `FileSystemSandboxPolicy.kind`
    - `core/src/tools/handlers/shell.rs`: shell approval requests now carry
    the split filesystem policy
    - `core/src/unified_exec/process_manager.rs`: unified-exec approval
    requests now carry the split filesystem policy
    - `core/src/tools/runtimes/shell/unix_escalation.rs`: intercepted exec
    fallback now uses the same split-policy approval semantics
    - `core/src/safety.rs`: `apply_patch` safety keeps using effective
    filesystem access rather than legacy sandbox categories
    - `core/src/config/config_tests.rs`: new regression coverage for legacy
    `sandbox_mode` no-drift behavior through the split-policy loader
    
    ## Notes
    
    - `core/src/codex.rs` and `core/src/codex_tests.rs` are just small
    fallout updates for `RequestPermissionsResponse.scope`; they are not the
    point of the PR.
    - If you reviewed the earlier `#13439` / `#13445` stack, the main review
    question here is simply: “are there any remaining approval or
    patch-safety paths that still reconstruct semantics from legacy
    `SandboxPolicy` instead of consuming the split filesystem policy
    directly?”
    
    ## Testing
    - cargo test -p codex-core
    legacy_sandbox_mode_config_builds_split_policies_without_drift
    - cargo test -p codex-core request_permissions
    - cargo test -p codex-core intercepted_exec_policy
    - cargo test -p codex-core
    restricted_sandbox_requires_exec_approval_on_request
    - cargo test -p codex-core
    unmatched_on_request_uses_split_filesystem_policy_for_escalation_prompts
    - cargo test -p codex-core explicit_
    - cargo clippy -p codex-core --tests -- -D warnings
  • chore(app-server): delete unused rpc methods from v1.rs (#14394)
    ## Description
    
    This PR trims `app-server-protocol`'s v1 surface down to the small set
    of legacy types we still actually use.
    
    Unfortunately, we can't delete all of them yet because:
    - a few one-off v1 RPCs are still used by the Codex app
    - a few of these app-server-protocol v1 types are actually imported by
    core crates
    
    This change deletes that unused RPC surface, keeps the remaining
    compatibility types in place, and makes the crate root re-export only
    the v1 structs that downstream crates still depend on.
    
    ## Why
    
    The main goal here is to make the legacy protocol surface match reality.
    Leaving a large pile of dead v1 structs in place makes it harder to tell
    which compatibility paths are still intentional, and it keeps old
    schema/types around even though nothing should be building against them
    anymore.
    
    This also gives us a cleaner boundary for future cleanup. Instead of
    re-exporting all of `protocol::v1::*`, the crate now explicitly exposes
    only the v1 types that are still live, which makes it much easier to see
    what remains and delete more safely later.
    
    ## What changed
    
    - Deleted the unused v1 RPC/request/response structs from
    `app-server-protocol/src/protocol/v1.rs`.
    - Kept the small set of v1 compatibility types that are still live,
    including:
      - `initialize`
      - `getConversationSummary`
      - `getAuthStatus`
      - `gitDiffToRemote`
      - legacy approval payloads
      - config-related structs still used by downstream crates
    - Replaced the blanket `pub use protocol::v1::*` export in
    `app-server-protocol/src/lib.rs` with an explicit list of the remaining
    supported v1 types.
    - Regenerated the schema/type artifacts, which also updated the
    `InitializeCapabilities` opt-out example to use `thread/started` instead
    of the old `codex/event/session_configured` example.
    
    ## Validation
    
    - `just write-app-server-schema`
    - `cargo test -p codex-app-server-protocol`
    
    ## Follow-up
    
    The next cleanup is to keep shrinking the remaining v1 compatibility
    surface as callers migrate off it. Once the remaining consumers stop
    importing these legacy types, we should be able to remove more of the v1
    module and eventually stop exporting it from the crate root entirely.
  • refactor: centralize filesystem permissions precedence (#14174)
    ## Stack
    
       fix: fail closed for unsupported split windows sandboxing #14172
       fix: preserve split filesystem semantics in linux sandbox #14173
       fix: align core approvals with split sandbox policies #14171
    -> refactor: centralize filesystem permissions precedence #14174
    
    ## Summary
    - add a shared per-path split filesystem precedence helper in
    `FileSystemSandboxPolicy`
    - derive readable, writable, and unreadable roots from the same
    most-specific resolution rules
    - add regression coverage for nested `write` / `read` / `none` carveouts
    and legacy bridge enforcement detection
    
    ## Testing
    - cargo test -p codex-protocol
    - cargo clippy -p codex-protocol --tests -- -D warnings
  • feat: search_tool migrate to bring you own tool of Responses API (#14274)
    ## Why
    
    to support a new bring your own search tool in Responses
    API(https://developers.openai.com/api/docs/guides/tools-tool-search#client-executed-tool-search)
    we migrating our bm25 search tool to use official way to execute search
    on client and communicate additional tools to the model.
    
    ## What
    - replace the legacy `search_tool_bm25` flow with client-executed
    `tool_search`
    - add protocol, SSE, history, and normalization support for
    `tool_search_call` and `tool_search_output`
    - return namespaced Codex Apps search results and wire namespaced
    follow-up tool calls back into MCP dispatch
  • chore(app-server): stop emitting codex/event/ notifications (#14392)
    ## Description
    
    This PR stops emitting legacy `codex/event/*` notifications from the
    public app-server transports.
    
    It's been a long time coming! app-server was still producing a raw
    notification stream from core, alongside the typed app-server
    notifications and server requests, for compatibility reasons. Now,
    external clients should no longer be depending on those legacy
    notifications, so this change removes them from the stdio and websocket
    contract and updates the surrounding docs, examples, and tests to match.
    
    ### Caveat
    I left the "in-process" version of app-server alone for now, since
    `codex exec` was recently based on top of app-server via this in-process
    form here: https://github.com/openai/codex/pull/14005
    
    Seems like `codex exec` still consumes some legacy notifications
    internally, so this branch only removes `codex/event/*` from app-server
    over stdio and websockets.
    
    ## Follow-up
    
    Once `codex exec` is fully migrated off `codex/event/*` notifications,
    we'll be able to stop emitting them entirely entirely instead of just
    filtering it at the external transport boundary.
  • check for large binaries in CI (#14382)
    Prevent binaries >500KB from being committed. And maintain an allowlist
    if we need to bypass on a case-by-case basis.
    
    I checked the currently tracked binary-like assets in the repo. There
    are only 5 obvious committed binaries by extension/MIME type:
    - `.github/codex-cli-splash.png`: `838,131` bytes, about `818 KiB`
    - `codex-rs/vendor/bubblewrap/bubblewrap.jpg`: `40,239` bytes, about `39
    KiB`
    -
    `codex-rs/skills/src/assets/samples/skill-creator/assets/skill-creator.png`:
    `1,563` bytes
    - `codex-rs/skills/src/assets/samples/openai-docs/assets/openai.png`:
    `1,429` bytes
    -
    `codex-rs/skills/src/assets/samples/skill-installer/assets/skill-installer.png`:
    `1,086` bytes
    
    So `500 KB` looks like a good default for this repo. It would only trip
    on one existing intentional asset, which keeps the allowlist small and
    the policy easy to understand.
    
    Here's a smoke-test from a throwaway branch that tries to commit a large
    binary:
    https://github.com/openai/codex/actions/runs/22971558828/job/66689330435?pr=14383
  • Let models opt into original image detail (#14175)
    ## Summary
    
    This PR narrows original image detail handling to a single opt-in
    feature:
    
    - `image_detail_original` lets the model request `detail: "original"` on
    supported models
    - Omitting `detail` preserves the default resized behavior
    
    The model only sees `detail: "original"` guidance when the active model
    supports it:
    
    - JS REPL instructions include the guidance and examples only on
    supported models
    - `view_image` only exposes a `detail` parameter when the feature and
    model can use it
    
    The image detail API is intentionally narrow and consistent across both
    paths:
    
    - `view_image.detail` supports only `"original"`; otherwise omit the
    field
    - `codex.emitImage(..., detail)` supports only `"original"`; otherwise
    omit the field
    - Unsupported explicit values fail clearly at the API boundary instead
    of being silently reinterpreted
    - Unsupported explicit `detail: "original"` requests fall back to normal
    behavior when the feature is disabled or the model does not support
    original detail