Commit Graph

171 Commits

  • Apply argument comment lint across codex-rs (#14652)
    ## Why
    
    Once the repo-local lint exists, `codex-rs` needs to follow the
    checked-in convention and CI needs to keep it from drifting. This commit
    applies the fallback `/*param*/` style consistently across existing
    positional literal call sites without changing those APIs.
    
    The longer-term preference is still to avoid APIs that require comments
    by choosing clearer parameter types and call shapes. This PR is
    intentionally the mechanical follow-through for the places where the
    existing signatures stay in place.
    
    After rebasing onto newer `main`, the rollout also had to cover newly
    introduced `tui_app_server` call sites. That made it clear the first cut
    of the CI job was too expensive for the common path: it was spending
    almost as much time installing `cargo-dylint` and re-testing the lint
    crate as a representative test job spends running product tests. The CI
    update keeps the full workspace enforcement but trims that extra
    overhead from ordinary `codex-rs` PRs.
    
    ## What changed
    
    - keep a dedicated `argument_comment_lint` job in `rust-ci`
    - mechanically annotate remaining opaque positional literals across
    `codex-rs` with exact `/*param*/` comments, including the rebased
    `tui_app_server` call sites that now fall under the lint
    - keep the checked-in style aligned with the lint policy by using
    `/*param*/` and leaving string and char literals uncommented
    - cache `cargo-dylint`, `dylint-link`, and the relevant Cargo
    registry/git metadata in the lint job
    - split changed-path detection so the lint crate's own `cargo test` step
    runs only when `tools/argument-comment-lint/*` or `rust-ci.yml` changes
    - continue to run the repo wrapper over the `codex-rs` workspace, so
    product-code enforcement is unchanged
    
    Most of the code changes in this commit are intentionally mechanical
    comment rewrites or insertions driven by the lint itself.
    
    ## Verification
    
    - `./tools/argument-comment-lint/run.sh --workspace`
    - `cargo test -p codex-tui-app-server -p codex-tui`
    - parsed `.github/workflows/rust-ci.yml` locally with PyYAML
    
    ---
    
    * -> #14652
    * #14651
  • Move TUI on top of app server (parallel code) (#14717)
    This PR replicates the `tui` code directory and creates a temporary
    parallel `tui_app_server` directory. It also implements a new feature
    flag `tui_app_server` to select between the two tui implementations.
    
    Once the new app-server-based TUI is stabilized, we'll delete the old
    `tui` directory and feature flag.
  • Reuse guardian session across approvals (#14668)
    ## Summary
    - reuse a guardian subagent session across approvals so reviews keep a
    stable prompt cache key and avoid one-shot startup overhead
    - clear the guardian child history before each review so prior guardian
    decisions do not leak into later approvals
    - include the `smart_approvals` -> `guardian_approval` feature flag
    rename in the same PR to minimize release latency on a very tight
    timeline
    - add regression coverage for prompt-cache-key reuse without
    prior-review prompt bleed
    
    ## Request
    - Bug/enhancement request: internal guardian prompt-cache and latency
    improvement request
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • [apps] Add tool call meta. (#14647)
    - [x] Add resource_uri and other things to _meta to shortcut resource
    lookup and speed things up.
  • Add Smart Approvals guardian review across core, app-server, and TUI (#13860)
    ## Summary
    - add `approvals_reviewer = "user" | "guardian_subagent"` as the runtime
    control for who reviews approval requests
    - route Smart Approvals guardian review through core for command
    execution, file changes, managed-network approvals, MCP approvals, and
    delegated/subagent approval flows
    - expose guardian review in app-server with temporary unstable
    `item/autoApprovalReview/{started,completed}` notifications carrying
    `targetItemId`, `review`, and `action`
    - update the TUI so Smart Approvals can be enabled from `/experimental`,
    aligned with the matching `/approvals` mode, and surfaced clearly while
    reviews are pending or resolved
    
    ## Runtime model
    This PR does not introduce a new `approval_policy`.
    
    Instead:
    - `approval_policy` still controls when approval is needed
    - `approvals_reviewer` controls who reviewable approval requests are
    routed to:
      - `user`
      - `guardian_subagent`
    
    `guardian_subagent` is a carefully prompted reviewer subagent that
    gathers relevant context and applies a risk-based decision framework
    before approving or denying the request.
    
    The `smart_approvals` feature flag is a rollout/UI gate. Core runtime
    behavior keys off `approvals_reviewer`.
    
    When Smart Approvals is enabled from the TUI, it also switches the
    current `/approvals` settings to the matching Smart Approvals mode so
    users immediately see guardian review in the active thread:
    - `approval_policy = on-request`
    - `approvals_reviewer = guardian_subagent`
    - `sandbox_mode = workspace-write`
    
    Users can still change `/approvals` afterward.
    
    Config-load behavior stays intentionally narrow:
    - plain `smart_approvals = true` in `config.toml` remains just the
    rollout/UI gate and does not auto-set `approvals_reviewer`
    - the deprecated `guardian_approval = true` alias migration does
    backfill `approvals_reviewer = "guardian_subagent"` in the same scope
    when that reviewer is not already configured there, so old configs
    preserve their original guardian-enabled behavior
    
    ARC remains a separate safety check. For MCP tool approvals, ARC
    escalations now flow into the configured reviewer instead of always
    bypassing guardian and forcing manual review.
    
    ## Config stability
    The runtime reviewer override is stable, but the config-backed
    app-server protocol shape is still settling.
    
    - `thread/start`, `thread/resume`, and `turn/start` keep stable
    `approvalsReviewer` overrides
    - the config-backed `approvals_reviewer` exposure returned via
    `config/read` (including profile-level config) is now marked
    `[UNSTABLE]` / experimental in the app-server protocol until we are more
    confident in that config surface
    
    ## App-server surface
    This PR intentionally keeps the guardian app-server shape narrow and
    temporary.
    
    It adds generic unstable lifecycle notifications:
    - `item/autoApprovalReview/started`
    - `item/autoApprovalReview/completed`
    
    with payloads of the form:
    - `{ threadId, turnId, targetItemId, review, action? }`
    
    `review` is currently:
    - `{ status, riskScore?, riskLevel?, rationale? }`
    - where `status` is one of `inProgress`, `approved`, `denied`, or
    `aborted`
    
    `action` carries the guardian action summary payload from core when
    available. This lets clients render temporary standalone pending-review
    UI, including parallel reviews, even when the underlying tool item has
    not been emitted yet.
    
    These notifications are explicitly documented as `[UNSTABLE]` and
    expected to change soon.
    
    This PR does **not** persist guardian review state onto `thread/read`
    tool items. The intended follow-up is to attach guardian review state to
    the reviewed tool item lifecycle instead, which would improve
    consistency with manual approvals and allow thread history / reconnect
    flows to replay guardian review state directly.
    
    ## TUI behavior
    - `/experimental` exposes the rollout gate as `Smart Approvals`
    - enabling it in the TUI enables the feature and switches the current
    session to the matching Smart Approvals `/approvals` mode
    - disabling it in the TUI clears the persisted `approvals_reviewer`
    override when appropriate and returns the session to default manual
    review when the effective reviewer changes
    - `/approvals` still exposes the reviewer choice directly
    - the TUI renders:
    - pending guardian review state in the live status footer, including
    parallel review aggregation
      - resolved approval/denial state in history
    
    ## Scope notes
    This PR includes the supporting core/runtime work needed to make Smart
    Approvals usable end-to-end:
    - shell / unified-exec / apply_patch / managed-network / MCP guardian
    review
    - delegated/subagent approval routing into guardian review
    - guardian review risk metadata and action summaries for app-server/TUI
    - config/profile/TUI handling for `smart_approvals`, `guardian_approval`
    alias migration, and `approvals_reviewer`
    - a small internal cleanup of delegated approval forwarding to dedupe
    fallback paths and simplify guardian-vs-parent approval waiting (no
    intended behavior change)
    
    Out of scope for this PR:
    - redesigning the existing manual approval protocol shapes
    - persisting guardian review state onto app-server `ThreadItem`s
    - delegated MCP elicitation auto-review (the current delegated MCP
    guardian shim only covers the legacy `RequestUserInput` path)
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Stabilize multi-agent feature flag (#14622)
    - make multi_agent stable and enabled by default
    - update feature and tool-spec coverage to match the new default
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Add code_mode_only feature (#14617)
    Summary
    - add the code_mode_only feature flag/config schema and wire its
    dependency on code_mode
    - update code mode tool descriptions to list nested tools with detailed
    headers
    - restrict available tools for prompt and exec descriptions when
    code_mode_only is enabled and test the behavior
    
    Testing
    - Not run (not requested)
  • Use subagents naming in the TUI (#14618)
    - rename user-facing TUI multi-agent wording to subagents
    - rename the surfaced slash command to `subagents` and update
    tests/snapshots
    
    Co-authored-by: Codex <noreply@openai.com>
  • Unify realtime v1/v2 session config (#14606)
    ## Summary
    - unify realtime websocket settings under `[realtime]` (`version` and
    `type`)
    - remove `realtime_conversation_v2` and select parser/session mode from
    config
    
    ## Testing
    - not run (per request)
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Add realtime v2 event parser behind feature flag (#14537)
    - Add a feature-flagged realtime v2 parser on the existing
    websocket/session pipeline.
    - Wire parser selection from core feature flags and map the codex
    handoff tool-call path into existing handoff events.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • 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)
  • 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)
  • 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`
  • 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
  • [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>
  • 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
  • Split spawn_csv from multi_agent (#14282)
    - make `spawn_csv` a standalone feature for CSV agent jobs
    - keep `spawn_csv -> multi_agent` one-way and preserve restricted
    subagent disable paths
  • [apps] Fix apps enablement condition. (#14011)
    - [x] Fix apps enablement condition to check both the feature flag and
    that the user is not an API key user.
  • start of hooks engine (#13276)
    (Experimental)
    
    This PR adds a first MVP for hooks, with SessionStart and Stop
    
    The core design is:
    
    - hooks live in a dedicated engine under codex-rs/hooks
    - each hook type has its own event-specific file
    - hook execution is synchronous and blocks normal turn progression while
    running
    - matching hooks run in parallel, then their results are aggregated into
    a normalized HookRunSummary
    
    On the AppServer side, hooks are exposed as operational metadata rather
    than transcript-native items:
    
    - new live notifications: hook/started, hook/completed
    - persisted/replayed hook results live on Turn.hookRuns
    - we intentionally did not add hook-specific ThreadItem variants
    
    Hooks messages are not persisted, they remain ephemeral. The context
    changes they add are (they get appended to the user's prompt)
  • Add code_mode experimental feature (#13418)
    A much narrower and more isolated (no node features) version of js_repl
  • guardian initial feedback / tweaks (#13897)
    ## Summary
    - remove the remaining model-visible guardian-specific `on-request`
    prompt additions so enabling the feature does not change the main
    approval-policy instructions
    - neutralize user-facing guardian wording to talk about automatic
    approval review / approval requests rather than a second reviewer or
    only sandbox escalations
    - tighten guardian retry-context handling so agent-authored
    `justification` stays in the structured action JSON and is not also
    injected as raw retry context
    - simplify guardian review plumbing in core by deleting dead
    prompt-append paths and trimming some request/transcript setup code
    
    ## Notable Changes
    - delete the dead `permissions/approval_policy/guardian.md` append path
    and stop threading `guardian_approval_enabled` through model-facing
    developer-instruction builders
    - rename the experimental feature copy to `Automatic approval review`
    and update the `/experimental` snapshot text accordingly
    - make approval-review status strings generic across shell, patch,
    network, and MCP review types
    - forward real sandbox/network retry reasons for shell and unified-exec
    guardian review, but do not pass agent-authored justification as raw
    retry context
    - simplify `guardian.rs` by removing the one-field request wrapper,
    deduping reasoning-effort selection, and cleaning up transcript entry
    collection
    
    ## Testing
    - `just fmt`
    - full validation left to CI
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Add request permissions tool (#13092)
    Adds a built-in `request_permissions` tool and wires it through the
    Codex core, protocol, and app-server layers so a running turn can ask
    the client for additional permissions instead of relying on a static
    session policy.
    
    The new flow emits a `RequestPermissions` event from core, tracks the
    pending request by call ID, forwards it through app-server v2 as an
    `item/permissions/requestApproval` request, and resumes the tool call
    once the client returns an approved subset of the requested permission
    profile.
  • Add guardian approval MVP (#13692)
    ## Summary
    - add the guardian reviewer flow for `on-request` approvals in command,
    patch, sandbox-retry, and managed-network approval paths
    - keep guardian behind `features.guardian_approval` instead of exposing
    a public `approval_policy = guardian` mode
    - route ordinary `OnRequest` approvals to the guardian subagent when the
    feature is enabled, without changing the public approval-mode surface
    
    ## Public model
    - public approval modes stay unchanged
    - guardian is enabled via `features.guardian_approval`
    - when that feature is on, `approval_policy = on-request` keeps the same
    approval boundaries but sends those approval requests to the guardian
    reviewer instead of the user
    - `/experimental` only persists the feature flag; it does not rewrite
    `approval_policy`
    - CLI and app-server no longer expose a separate `guardian` approval
    mode in this PR
    
    ## Guardian reviewer
    - the reviewer runs as a normal subagent and reuses the existing
    subagent/thread machinery
    - it is locked to a read-only sandbox and `approval_policy = never`
    - it does not inherit user/project exec-policy rules
    - it prefers `gpt-5.4` when the current provider exposes it, otherwise
    falls back to the parent turn's active model
    - it fail-closes on timeout, startup failure, malformed output, or any
    other review error
    - it currently auto-approves only when `risk_score < 80`
    
    ## Review context and policy
    - guardian mirrors `OnRequest` approval semantics rather than
    introducing a separate approval policy
    - explicit `require_escalated` requests follow the same approval surface
    as `OnRequest`; the difference is only who reviews them
    - managed-network allowlist misses that enter the approval flow are also
    reviewed by guardian
    - the review prompt includes bounded recent transcript history plus
    recent tool call/result evidence
    - transcript entries and planned-action strings are truncated with
    explicit `<guardian_truncated ... />` markers so large payloads stay
    bounded
    - apply-patch reviews include the full patch content (without
    duplicating the structured `changes` payload)
    - the guardian request layout is snapshot-tested using the same
    model-visible Responses request formatter used elsewhere in core
    
    ## Guardian network behavior
    - the guardian subagent inherits the parent session's managed-network
    allowlist when one exists, so it can use the same approved network
    surface while reviewing
    - exact session-scoped network approvals are copied into the guardian
    session with protocol/port scope preserved
    - those copied approvals are now seeded before the guardian's first turn
    is submitted, so inherited approvals are available during any immediate
    review-time checks
    
    ## Out of scope / follow-ups
    - the sandbox-permission validation split was pulled into a separate PR
    and is not part of this diff
    - a future follow-up can enable `serde_json` preserve-order in
    `codex-core` and then simplify the guardian action rendering further
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Allow full web search tool config (#13675)
    Previously, we could only configure whether web search was on/off.
    
    This PR enables sending along a web search config, which includes all
    the stuff responsesapi supports: filters, location, etc.
  • chore(otel): rename OtelManager to SessionTelemetry (#13808)
    ## Summary
    This is a purely mechanical refactor of `OtelManager` ->
    `SessionTelemetry` to better convey what the struct is doing. No
    behavior change.
    
    ## Why
    
    `OtelManager` ended up sounding much broader than what this type
    actually does. It doesn't manage OTEL globally; it's the session-scoped
    telemetry surface for emitting log/trace events and recording metrics
    with consistent session metadata (`app_version`, `model`, `slug`,
    `originator`, etc.).
    
    `SessionTelemetry` is a more accurate name, and updating the call sites
    makes that boundary a lot easier to follow.
    
    ## Validation
    
    - `just fmt`
    - `cargo test -p codex-otel`
    - `cargo test -p codex-core`
  • [elicitations] Switch to use MCP style elicitation payload for mcp tool approvals. (#13621)
    - [x] Switch to use MCP style elicitation payload for mcp tool
    approvals.
    - [ ] TODO: Update the UI to support the full spec.
  • image-gen-core (#13290)
    Core tool-calling for image-gen, handles requesting and receiving logic
    for images using response API
  • config: enforce enterprise feature requirements (#13388)
    ## Why
    
    Enterprises can already constrain approvals, sandboxing, and web search
    through `requirements.toml` and MDM, but feature flags were still only
    configurable as managed defaults. That meant an enterprise could suggest
    feature values, but it could not actually pin them.
    
    This change closes that gap and makes enterprise feature requirements
    behave like the other constrained settings. The effective feature set
    now stays consistent with enterprise requirements during config load,
    when config writes are validated, and when runtime code mutates feature
    flags later in the session.
    
    It also tightens the runtime API for managed features. `ManagedFeatures`
    now follows the same constraint-oriented shape as `Constrained<T>`
    instead of exposing panic-prone mutation helpers, and production code
    can no longer construct it through an unconstrained `From<Features>`
    path.
    
    The PR also hardens the `compact_resume_fork` integration coverage on
    Windows. After the feature-management changes,
    `compact_resume_after_second_compaction_preserves_history` was
    overflowing the libtest/Tokio thread stacks on Windows, so the test now
    uses an explicit larger-stack harness as a pragmatic mitigation. That
    may not be the ideal root-cause fix, and it merits a parallel
    investigation into whether part of the async future chain should be
    boxed to reduce stack pressure instead.
    
    ## What Changed
    
    Enterprises can now pin feature values in `requirements.toml` with the
    requirements-side `features` table:
    
    ```toml
    [features]
    personality = true
    unified_exec = false
    ```
    
    Only canonical feature keys are allowed in the requirements `features`
    table; omitted keys remain unconstrained.
    
    - Added a requirements-side pinned feature map to
    `ConfigRequirementsToml`, threaded it through source-preserving
    requirements merge and normalization in `codex-config`, and made the
    TOML surface use `[features]` (while still accepting legacy
    `[feature_requirements]` for compatibility).
    - Exposed `featureRequirements` from `configRequirements/read`,
    regenerated the JSON/TypeScript schema artifacts, and updated the
    app-server README.
    - Wrapped the effective feature set in `ManagedFeatures`, backed by
    `ConstrainedWithSource<Features>`, and changed its API to mirror
    `Constrained<T>`: `can_set(...)`, `set(...) -> ConstraintResult<()>`,
    and result-returning `enable` / `disable` / `set_enabled` helpers.
    - Removed the legacy-usage and bulk-map passthroughs from
    `ManagedFeatures`; callers that need those behaviors now mutate a plain
    `Features` value and reapply it through `set(...)`, so the constrained
    wrapper remains the enforcement boundary.
    - Removed the production loophole for constructing unconstrained
    `ManagedFeatures`. Non-test code now creates it through the configured
    feature-loading path, and `impl From<Features> for ManagedFeatures` is
    restricted to `#[cfg(test)]`.
    - Rejected legacy feature aliases in enterprise feature requirements,
    and return a load error when a pinned combination cannot survive
    dependency normalization.
    - Validated config writes against enterprise feature requirements before
    persisting changes, including explicit conflicting writes and
    profile-specific feature states that normalize into invalid
    combinations.
    - Updated runtime and TUI feature-toggle paths to use the constrained
    setter API and to persist or apply the effective post-constraint value
    rather than the requested value.
    - Updated the `core_test_support` Bazel target to include the bundled
    core model-catalog fixtures in its runtime data, so helper code that
    resolves `core/models.json` through runfiles works in remote Bazel test
    environments.
    - Renamed the core config test coverage to emphasize that effective
    feature values are normalized at runtime, while conflicting persisted
    config writes are rejected.
    - Ran `compact_resume_after_second_compaction_preserves_history` inside
    an explicit 8 MiB test thread and Tokio runtime worker stack, following
    the existing larger-stack integration-test pattern, to keep the Windows
    `compact_resume_fork` test slice from aborting while a parallel
    investigation continues into whether some of the underlying async
    futures should be boxed.
    
    ## Verification
    
    - `cargo test -p codex-config`
    - `cargo test -p codex-core feature_requirements_ -- --nocapture`
    - `cargo test -p codex-core
    load_requirements_toml_produces_expected_constraints -- --nocapture`
    - `cargo test -p codex-core
    compact_resume_after_second_compaction_preserves_history -- --nocapture`
    - `cargo test -p codex-core compact_resume_fork -- --nocapture`
    - Re-ran the built `codex-core` `tests/all` binary with
    `RUST_MIN_STACK=262144` for
    `compact_resume_after_second_compaction_preserves_history` to confirm
    the explicit-stack harness fixes the deterministic low-stack repro.
    - `cargo test -p codex-core`
    - This still fails locally in unrelated integration areas that expect
    the `codex` / `test_stdio_server` binaries or hit existing `search_tool`
    wiremock mismatches.
    
    ## Docs
    
    `developers.openai.com/codex` should document the requirements-side
    `[features]` table for enterprise and MDM-managed configuration,
    including that it only accepts canonical feature keys and that
    conflicting config writes are rejected.
  • Add under-development original-resolution view_image support (#13050)
    ## Summary
    
    Add original-resolution support for `view_image` behind the
    under-development `view_image_original_resolution` feature flag.
    
    When the flag is enabled and the target model is `gpt-5.3-codex` or
    newer, `view_image` now preserves original PNG/JPEG/WebP bytes and sends
    `detail: "original"` to the Responses API instead of using the legacy
    resize/compress path.
    
    ## What changed
    
    - Added `view_image_original_resolution` as an under-development feature
    flag.
    - Added `ImageDetail` to the protocol models and support for serializing
    `detail: "original"` on tool-returned images.
    - Added `PromptImageMode::Original` to `codex-utils-image`.
      - Preserves original PNG/JPEG/WebP bytes.
      - Keeps legacy behavior for the resize path.
    - Updated `view_image` to:
    - use the shared `local_image_content_items_with_label_number(...)`
    helper in both code paths
      - select original-resolution mode only when:
        - the feature flag is enabled, and
        - the model slug parses as `gpt-5.3-codex` or newer
    - Kept local user image attachments on the existing resize path; this
    change is specific to `view_image`.
    - Updated history/image accounting so only `detail: "original"` images
    use the docs-based GPT-5 image cost calculation; legacy images still use
    the old fixed estimate.
    - Added JS REPL guidance, gated on the same feature flag, to prefer JPEG
    at 85% quality unless lossless is required, while still allowing other
    formats when explicitly requested.
    - Updated tests and helper code that construct
    `FunctionCallOutputContentItem::InputImage` to carry the new `detail`
    field.
    
    ## Behavior
    
    ### Feature off
    - `view_image` keeps the existing resize/re-encode behavior.
    - History estimation keeps the existing fixed-cost heuristic.
    
    ### Feature on + `gpt-5.3-codex+`
    - `view_image` sends original-resolution images with `detail:
    "original"`.
    - PNG/JPEG/WebP source bytes are preserved when possible.
    - History estimation uses the GPT-5 docs-based image-cost calculation
    for those `detail: "original"` images.
    
    
    #### [git stack](https://github.com/magus/git-stack-cli)
    - 👉 `1` https://github.com/openai/codex/pull/13050
    -  `2` https://github.com/openai/codex/pull/13331
    -  `3` https://github.com/openai/codex/pull/13049
  • feat: presentation artifact p1 (#13341)
    Part 1 of presentation tool artifact
  • add fast mode toggle (#13212)
    - add a local Fast mode setting in codex-core (similar to how model id
    is currently stored on disk locally)
    - send `service_tier=priority` on requests when Fast is enabled
    - add `/fast` in the TUI and persist it locally
    - feature flag
  • feat: load from plugins (#12864)
    Support loading plugins.
    
    Plugins can now be enabled via [plugins.<name>] in config.toml. They are
    loaded as first-class entities through PluginsManager, and their default
    skills/ and .mcp.json contributions are integrated into the existing
    skills and MCP flows.
  • Reduce js_repl Node version requirement to 22.22.0 (#12857)
    ## Summary
    
    Lower the `js_repl` minimum Node version from `24.13.1` to `22.22.0`.
    
    This updates the enforced minimum in `codex-rs/node-version.txt` and the
    corresponding user-facing `/experimental` description for the JavaScript
    REPL feature.
    
    ## Rationale
    
    The previous `24.13.1` floor was stricter than necessary for `js_repl`.
    I validated the REPL kernel behavior under Node `22.22.0` still works.
    
    ## Why `22.22.0`
    
    `22.22.0` is a current, widely packaged Node 22 release across common
    developer environments and distros, including Homebrew `node@22`, Fedora
    `nodejs22`, Arch `nodejs-lts-jod`, and Debian testing. That makes it a
    better exact floor than guessing at an older `22.x` patch we have not
    validated.
    
    `22.x` is also a maintenance branch that will be supported through April
    2027, where the previous maintenance branch of `20.x` is only supported
    through April of this year.
    
    ## Changes
    
    - Update `codex-rs/node-version.txt` from `24.13.1` to `22.22.0`
    - Update the `/experimental` JavaScript REPL description to say
    `Requires Node >= v22.22.0 installed.`
  • Revert "Add skill approval event/response (#12633)" (#12811)
    This reverts commit https://github.com/openai/codex/pull/12633. We no
    longer need this PR, because we favor sending normal exec command
    approval server request with `additional_permissions` of skill
    permissions instead
  • Remove steer feature flag (#12026)
    All code should go in the direction that steer is enabled
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Enable request_user_input in Default mode (#12735)
    ## Summary
    - allow `request_user_input` in Default collaboration mode as well as
    Plan
    - update the Default-mode instructions to prefer assumptions first and
    use `request_user_input` only when a question is unavoidable
    - update request_user_input and app-server tests to match the new
    Default-mode behavior
    - refactor collaboration-mode availability plumbing into
    `CollaborationModesConfig` for future mode-related flags
    
    ## Codex author
    `codex resume 019c9124-ed28-7c13-96c6-b916b1c97d49`
  • Promote js_repl to experimental with Node requirement (#12712)
    ## Summary
    
    - Promote `js_repl` to an experimental feature that users can enable
    from `/experimental`.
    - Add `js_repl` experimental metadata, including the Node prerequisite
    and activation guidance.
    - Add regression coverage for the feature metadata and the
    `/experimental` popup.
    
    ## What Changed
    
    - Changed `Feature::JsRepl` from `Stage::UnderDevelopment` to
    `Stage::Experimental`.
    - Added experimental metadata for `js_repl` in `core/src/features.rs`:
      - name: `JavaScript REPL`
    - description: calls out interactive website debugging, inline
    JavaScript execution, and the required Node version (`>= v24.13.1`)
    - announcement: tells users to enable it, then start a new chat or
    restart Codex
    - Added a core unit test that verifies:
      - `js_repl` is experimental
      - `js_repl` is disabled by default
    - the hardcoded Node version in the description matches
    `node-version.txt`
    - Added a TUI test that opens the `/experimental` popup and verifies the
    rendered `js_repl` entry includes the Node requirement text.
    
    ## Testing
    
    - `just fmt`
    - `cargo test -p codex-tui`
    - `cargo test -p codex-core` (unit-test phase passed; stopped during the
    long `tests/all.rs` integration suite)
  • Add TUI realtime conversation mode (#12687)
    - Add a hidden `realtime_conversation` feature flag and `/realtime`
    slash command for start/stop live voice sessions.
    - Reuse transcription composer/footer UI for live metering, stream mic
    audio, play assistant audio, render realtime user text events, and
    force-close on feature disable.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat(sleep-inhibitor): add Linux and Windows idle-sleep prevention (#11766)
    ## Background
    - follow-up to previous macOS-only PR:
    https://github.com/openai/codex/pull/11711
    - follow-up macOS refactor PR (current structural approach used here):
    https://github.com/openai/codex/pull/12340
    
    ## Summary
    - extend `codex-utils-sleep-inhibitor` with Linux and Windows backends
    while preserving existing macOS behavior
    - Linux backend:
      - use `systemd-inhibit` (`--what=idle --mode=block`) when available
    - fall back to `gnome-session-inhibit` (`--inhibit idle`) when available
      - keep no-op behavior if neither backend exists on host
    - Windows backend:
    - use Win32 power request handles (`PowerCreateRequest` +
    `PowerSetRequest` / `PowerClearRequest`) with
    `PowerRequestSystemRequired`
    - make `prevent_idle_sleep` Experimental on macOS/Linux/Windows; keep
    under development on other targets
    
    ## Testing
    - `just fmt`
    - `cargo test -p codex-utils-sleep-inhibitor`
    - `cargo test -p codex-core features::tests::`
    - `cargo test -p codex-tui chatwidget::tests::`
    - `just fix -p codex-utils-sleep-inhibitor`
    - `just fix -p codex-core`
    
    ## Semantics and API references
    - Goal remains: prevent idle system sleep while a turn is running.
    - Linux:
      - `systemd-inhibit` / login1 inhibitor model:
    -
    https://www.freedesktop.org/software/systemd/man/latest/systemd-inhibit.html
    -
    https://www.freedesktop.org/software/systemd/man/org.freedesktop.login1.html
        - https://systemd.io/INHIBITOR_LOCKS/
      - xdg-desktop-portal Inhibit (relevant for sandboxed apps):
    -
    https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit.html
    - Windows:
      - `PowerCreateRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powercreaterequest
      - `PowerSetRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest
      - `PowerClearRequest`:
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powerclearrequest
      - `SetThreadExecutionState` (alternative baseline API):
    -
    https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
    
    ## Chromium vs this PR
    - Chromium Linux backend:
    -
    https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
    - Chromium Windows backend:
    -
    https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
    - Electron powerSaveBlocker entry point:
    -
    https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc
    
    ## Why we differ from Chromium
    - Linux implementation mechanism:
    - Chromium uses in-process D-Bus APIs plus UI-integrated screen-saver
    suspension.
    - This PR uses command-based inhibitor backends (`systemd-inhibit`,
    `gnome-session-inhibit`) instead of linking a Linux D-Bus client in this
    crate.
    - Reason: keep `codex-utils-sleep-inhibitor` dependency-light and avoid
    Linux CI/toolchain fragility from new native D-Bus linkage, while
    preserving the same runtime intent (hold an inhibitor while a turn
    runs).
    - Linux UI integration scope:
    - Chromium also uses `display::Screen::SuspendScreenSaver()` in its UI
    stack.
    - Codex `codex-rs` does not have that display abstraction in this crate,
    so this PR scopes Linux behavior to process-level sleep inhibition only.
    - Windows wake-lock type breadth:
    - Chromium supports both display/system wake-lock types and extra
    display-specific handling for some pre-Win11 scenarios.
    - Codex’s feature is scoped to turn execution continuity (not forcing
    display on), so this PR uses `PowerRequestSystemRequired` only.
  • feat(core) Introduce Feature::RequestPermissions (#11871)
    ## Summary
    Introduces the initial implementation of Feature::RequestPermissions.
    RequestPermissions allows the model to request that a command be run
    inside the sandbox, with additional permissions, like writing to a
    specific folder. Eventually this will include other rules as well, and
    the ability to persist these permissions, but this PR is already quite
    large - let's get the core flow working and go from there!
    
    <img width="1279" height="541" alt="Screenshot 2026-02-15 at 2 26 22 PM"
    src="https://github.com/user-attachments/assets/0ee3ec0f-02ec-4509-91a2-809ac80be368"
    />
    
    ## Testing
    - [x] Added tests
    - [x] Tested locally
    - [x] Feature
  • Add skill approval event/response (#12633)
    Set the stage for skill-level permission approval in addition to
    command-level.
    
    Behind a feature flag.
  • voice transcription (#3381)
    Adds voice transcription on press-and-hold of spacebar.
    
    
    https://github.com/user-attachments/assets/85039314-26f3-46d1-a83b-8c4a4a1ecc21
    
    ---------
    
    Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
    Co-authored-by: David Zbarsky <zbarsky@openai.com>
  • remove feature flag collaboration modes (#12028)
    All code should go in the direction that steer is enabled
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • chore: rename memory feature flag (#12580)
    `memory_tool` -> `memories`
  • chore: move config diagnostics out of codex-core (#12427)
    ## Why
    
    Compiling `codex-rs/core` is a bottleneck for local iteration, so this
    change continues the ongoing extraction of config-related functionality
    out of `codex-core` and into `codex-config`.
    
    The goal is not just to move code, but to reduce `codex-core` ownership
    and indirection so more code depends on `codex-config` directly.
    
    ## What Changed
    
    - Moved config diagnostics logic from
    `core/src/config_loader/diagnostics.rs` into
    `config/src/diagnostics.rs`.
    - Updated `codex-core` to use `codex-config` diagnostics types/functions
    directly where possible.
    - Removed the `core/src/config_loader/diagnostics.rs` shim module
    entirely; the remaining `ConfigToml`-specific calls are in
    `core/src/config_loader/mod.rs`.
    - Moved `CONFIG_TOML_FILE` into `codex-config` and updated existing
    references to use `codex_config::CONFIG_TOML_FILE` directly.
    - Added a direct `codex-config` dependency to `codex-cli` for its
    `CONFIG_TOML_FILE` use.
  • Skip removed features during metrics emission (#12253)
    Summary
    - avoid emitting metrics for features marked as `Stage::Removed`
    - keep feature metrics aligned with active and planned states only
    
    Testing
    - Not run (not requested)