Commit Graph

105 Commits

  • [codex] Remove remote compaction failure log (#27106)
    ## Why
    
    `log_remote_compact_failure` was the only consumer of the
    compact-request logging payload and most of the token-usage breakdown
    fields. Once that failure log is removed, keeping the surrounding
    carrier types leaves dead plumbing in the compaction path and context
    manager.
    
    ## What changed
    
    - Remove `log_remote_compact_failure`, `CompactRequestLogData`, and the
    v2 wrapper that only fed that log.
    - Let both remote compaction implementations return the original
    compaction error directly.
    - Replace `TotalTokenUsageBreakdown` with a narrow helper that returns
    only the remaining value needed by compaction analytics.
    - Keep `estimate_response_item_model_visible_bytes` private to the
    context manager implementation.
    
    ## Validation
    
    - `cargo check -p codex-core`
  • Encrypt multi-agent v2 message payloads (#26210)
    ## Why
    
    Multi-agent v2 currently routes agent instructions through normal tool
    arguments and inter-agent context. That means the parent model can emit
    plaintext task text, Codex can persist it in history/rollouts, and the
    recipient can receive it as ordinary assistant-message JSON.
    
    This changes the v2 path so agent instructions stay encrypted between
    model calls: Responses encrypts the `message` argument returned by the
    model, Codex forwards only that ciphertext, and Responses decrypts it
    internally for the recipient model.
    
    ## What changed
    
    - Mark the v2 `message` parameter as encrypted for `spawn_agent`,
    `send_message`, and `followup_task`.
    - Treat multi-agent v2 tool `message` values as ciphertext
    unconditionally.
    - Store v2 inter-agent task text in
    `InterAgentCommunication.encrypted_content` with empty plaintext
    `content`.
    - Convert encrypted inter-agent communications into the Responses
    `agent_message` input item before sending the child request.
    - Preserve `agent_message` items across history, rollout, compaction,
    telemetry, and app-server schema paths.
    - Leave multi-agent v1 unchanged.
    
    ## Message shape
    
    The model still calls the v2 tools with a `message` argument, but that
    value is now ciphertext:
    
    ```json
    {
      "name": "spawn_agent",
      "arguments": {
        "task_name": "worker",
        "message": "<ciphertext>"
      }
    }
    ```
    
    Codex stores the task as encrypted inter-agent communication:
    
    ```json
    {
      "author": "/root",
      "recipient": "/root/worker",
      "content": "",
      "encrypted_content": "<ciphertext>",
      "trigger_turn": true
    }
    ```
    
    When Codex builds the recipient request, it forwards the ciphertext
    using the new Responses input item:
    
    ```json
    {
      "type": "agent_message",
      "author": "/root",
      "recipient": "/root/worker",
      "content": [
        {
          "type": "encrypted_content",
          "encrypted_content": "<ciphertext>"
        }
      ]
    }
    ```
    
    Responses decrypts that item internally for the recipient model.
    
    ## Context impact
    
    - Parent context no longer carries plaintext v2 agent task instructions
    from these tool arguments.
    - Codex rollout/history stores ciphertext for v2 agent instructions.
    - Recipient requests receive an `agent_message` item instead of
    assistant commentary JSON for encrypted task delivery.
    - Plaintext completion/status notifications are still plaintext because
    they are Codex-generated status messages, not encrypted model tool
    arguments.
    
    ## Validation
    
    - `just test -p codex-tools`
    - `just test -p codex-protocol`
    - `just test -p codex-rollout`
    - `just test -p codex-rollout-trace`
    - `just test -p codex-otel`
    - `just write-app-server-schema`
  • Rewrite oversized tool outputs during remote compaction (#26251)
    ## Why
    
    When trying to fit history under compaction limit rewrite output items
    instead of removing them entirely. Otherwise we're breaking
    incrementality in relation to the previous response.
  • Add multi-agent runtime metadata types (#25720)
    Stack split from #25708. Original PR intentionally left open. This first
    PR adds the multi-agent runtime metadata types and catalog plumbing used
    by the rest of the stack.
  • 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.
  • Expose conversation history to extension tools (#23963)
    ## Why
    
    Extension tools that need conversation context should be able to read it
    from the live tool invocation instead of reaching into thread
    persistence themselves.
    
    ## What changed
    
    - Add a `ConversationHistory` snapshot to extension `ToolCall`s and
    populate it from the current raw in-memory response history.
    - Expose all history items at this boundary so each extension can filter
    and bound the subset it needs before consuming or forwarding it.
    - Cover the adapter and registry dispatch paths and update existing
    extension tests that construct `ToolCall` literals.
    
    ## Test plan
    
    - `cargo test -p codex-tools`
    - `cargo test -p codex-extension-api`
    - `cargo test -p codex-goal-extension`
    - `cargo test -p codex-memories-extension`
    - `cargo test -p codex-core passes_turn_fields_to_extension_call`
    - `cargo test -p codex-core
    extension_tool_executors_are_model_visible_and_dispatchable`
  • add encryptedcontent to functioncalloutput (#23500)
    add new `EncryptedContent` variant to `FunctionCallOutputContentItem`
    ahead of standalone websearch.
    
    we need to be able to receive and pass encrypted function call output
    from the new web search endpoint back to responsesapi, as we cannot
    expose direct search results.
  • [codex] Trim unused TurnContextItem fields (#22709)
    ## Why
    
    `TurnContextItem` is the durable baseline used to reconstruct context
    diffs across resume/fork. Most of the old persisted-only fields on it
    are no longer read, so keeping them in rollout snapshots adds schema
    surface and state that can drift without affecting reconstruction.
    
    `summary` is the exception: older Codex versions require it to
    deserialize `turn_context` records, so keep writing a default
    compatibility value until that schema surface can be removed safely.
    
    ## What changed
    
    - Removed the unused persisted fields from `TurnContextItem`: trace ids,
    user/developer instructions, output schema, and truncation policy.
    - Kept `summary` with a compatibility comment and made
    `TurnContext::to_turn_context_item` write `ReasoningSummary::Auto`
    instead of live turn state.
    - Updated rollout/context reconstruction fixtures for the retained
    summary field.
    
    ## Verification
    
    - `cargo test -p codex-protocol --lib turn_context_item`
    - `cargo test -p codex-rollout
    resume_candidate_matches_cwd_reads_latest_turn_context`
    - `cargo test -p codex-state turn_context`
    - `cargo test -p codex-core --lib
    new_default_turn_captures_current_span_trace_id`
    - `cargo test -p codex-core --lib
    record_initial_history_resumed_turn_context_after_compaction_reestablishes_reference_context_item`
    - `cargo test -p codex-core --test all
    emits_warning_when_resumed_model_differs`
    - `git diff --check`
  • [codex] Use compaction_trigger item for remote compaction v2 (#22809)
    ## Why
    
    Remote compaction v2 was still using `context_compaction` as both the
    request trigger and the compacted output shape. The Responses API now
    has the landed contract for this flow: Codex sends a dedicated `{
    "type": "compaction_trigger" }` input item, and the backend returns the
    standard `compaction` output item with encrypted content.
    
    This aligns the v2 path with that wire contract while preserving the
    existing local compacted-history post-processing behavior.
    
    ## What changed
    
    - Add `ResponseItem::CompactionTrigger` and regenerate the app-server
    protocol schema fixtures.
    - Send `compaction_trigger` from `remote_compaction_v2` instead of a
    payload-less `context_compaction`.
    - Collect exactly one backend `compaction` output item, then reuse the
    existing compacted-history rebuilding path.
    - Treat the trigger item as a transient request marker rather than model
    output or persisted rollout/memory content.
    
    ## Verification
    
    - `cargo test -p codex-protocol compaction_trigger`
    - `cargo test -p codex-core remote_compact_v2`
    - `cargo test -p codex-core compact_remote_v2`
    - `cargo test -p codex-core
    responses_websocket_sends_response_processed_after_remote_compaction_v2`
    - `just write-app-server-schema`
    - `cargo test -p codex-app-server-protocol schema_fixtures`
  • Deprecate TurnContext cwd and resolve_path (#22519)
    ## Why
    
    `TurnContext::cwd` and `TurnContext::resolve_path` are being phased out
    in favor of using the selected turn environment cwd directly.
    Deprecating both APIs makes any new direct dependency visible while
    preserving the existing migration path for current callers.
    
    ## What Changed
    
    - Marked `TurnContext::cwd` and `TurnContext::resolve_path` as
    deprecated with guidance to use the selected turn environment cwd
    instead.
    - Added exact `#[allow(deprecated)]` suppressions at each existing
    direct usage site, including tests, rather than adding crate-wide
    suppression.
    - Kept the change behavior-preserving: current cwd reads, writes, and
    path resolution continue to use the same values.
    
    ## Verification
    
    - `just fmt`
    - `cargo check -p codex-core`
    - `cargo check -p codex-core --tests`
    - `git diff --check`
  • chore(config) include_collaboration_mode_instructions (#22383)
    ## Summary
    Adds include_collaboration_mode_instructions, which is a config
    equivalent to include_permissions_instructions for collaboration modes.
    Desired for situations where we want to disable this instruction from
    entering the context
    
    ## Testing
    - [x] Added unit test
  • Avoid hard-coded environment context shell (#21390)
    ## Summary
    - make resolved turn environment shell metadata optional instead of
    hard-coding bash
    - render environment context shells from explicit environment metadata
    when present, falling back to the existing session shell
    - update environment context tests for inherited PowerShell-style
    fallback and explicit per-environment shell override
    
    ## Testing
    - Not run (not requested; formatted with `just fmt`).
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat: add remote compaction v2 Responses client path (#20773)
    ## Why
    
    This adds the `remote_compaction_v2` client path so remote compaction
    can run through the normal Responses stream and install a
    `context_compaction` item that trigger a compaction.
    
    The goal is to migrate some of the compaction logic on the client side
    
    We keeps the v2 transport behind a feature flag while letting follow-up
    requests reuse the compacted context instead of falling back to the
    legacy compaction item shape.
    
    ## What changed
    
    - add `ResponseItem::ContextCompaction` and refresh the generated
    app-server / schema / TypeScript fixtures that expose response items on
    the wire
    - add `core/src/compact_remote_v2.rs` to send compaction through the
    standard streamed Responses client, require exactly one
    `context_compaction` output item, and install that item into compacted
    history
    - route manual compact and auto-compaction through the v2 path when
    `remote_compaction_v2` is enabled, while keeping the existing remote
    compaction path as the fallback
    - preserve the new item type across history retention, follow-up request
    construction, telemetry, rollout persistence, and rollout-trace
    normalization
    - add targeted coverage for the feature flag, `context_compaction`
    serialization, rollout-trace normalization, and remote-compaction
    follow-up behavior
    
    ## Verification
    
    - added protocol tests for `context_compaction`
    serialization/deserialization in `protocol/src/models.rs`
    - added rollout-trace coverage for `context_compaction` normalization in
    `rollout-trace/src/reducer/conversation_tests.rs`
    - added remote compaction integration coverage for v2 follow-up reuse
    and mixed compaction output streams in
    `core/tests/suite/compact_remote.rs`
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Surface multi-environment choices in environment context (#20646)
    ## Why
    The model needs a way to see which environments are available during a
    multi-environment turn without changing the legacy single-environment
    prompt surface or pulling replay/persistence changes into the same
    review.
    
    ## Stack
    1. https://github.com/openai/codex/pull/20646 - `EnvironmentContext`
    rendering for selected environments (this PR)
    2. https://github.com/openai/codex/pull/20669 - selected-environment
    ownership and tool config prep
    3. https://github.com/openai/codex/pull/20647 - process-tool
    `environment_id` routing
    
    ## What Changed
    - extend `environment_context` so multi-environment turns render an
    `<environments>` block with the selected environment ids and cwd values
    - keep zero- and single-environment turns on the existing cwd-only
    render path
    - keep replay and persistence paths on the legacy surface for now so
    this PR stays scoped to live prompt rendering
    - add focused coverage in
    `codex-rs/core/src/context/environment_context_tests.rs`
    
    ## Testing
    - CI
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • fix(core): truncate large mcp tool outputs in rollouts (#20260)
    ## Why
    Large MCP tool call outputs can make rollout JSONL files enormous. In
    the session that motivated this change, the biggest JSONL records were:
    - `event_msg/mcp_tool_call_end`
    - `response_item/function_call_output`
    
    both containing the same unbounded MCP payloads - just 3 MCP tool calls
    that each were multi-hundred MBs 😱
    
    This PR truncates both of those JSONL records.
    
    ## How
    
    #### For `response_item/function_call_output`
    Unified exec already bounds tool output before it is injected into
    model-facing history, which also keeps the corresponding rollout
    `response_item/function_call_output` records small.
    
    MCP should follow the same pattern: truncate the model-facing tool
    output at the tool-output boundary, while leaving code-mode/raw hook
    consumers alone.
    
    #### For `event_msg/mcp_tool_call_end`
    `McpToolCallEnd` also needs its own bounded event copy because it is the
    app-server/replay/UI event shape that backs `ThreadItem::McpToolCall`.
    Unfortunately this is _not_ downstream of the `ToolOutput` trait.
    
    ## Model behavior 
    Model behavior is actually unchanged as a result of this PR. 
    
    Before this PR, MCP output was:
    1. Converted to `FunctionCallOutput`.
    2. Recorded into in-memory history.
    3. Truncated by `ContextManager::record_items()` before later model
    turns saw it.
    
    After this branch, MCP output is truncated earlier, in
    `McpToolOutput::response_payload()`, using the same helper. Then
    `ContextManager::record_items()` sees an already-truncated output and
    effectively has little/no additional work to do.
    
    So the model should still see the same kind of truncated function-call
    output. The practical difference is where truncation happens: earlier,
    before rollout persistence/app-server emission can see the giant
    payload.
    
    ## Verification
    
    - `cargo test -p codex-core mcp_tool_output`
    - `cargo test -p codex-core
    mcp_tool_call::tests::truncate_mcp_tool_result_for_event`
    - `cargo test -p codex-core
    mcp_post_tool_use_payload_uses_model_tool_name_args_and_result`
    - `just fmt`
    - `just fix -p codex-core`
    - `git diff --check`
  • Remove ghost snapshots (#19481)
    ## Summary
    - Remove `ghost_snapshot` / `GhostCommit` from the Responses API surface
    and generated SDK/schema artifacts.
    - Keep legacy config loading compatible, but make undo a no-op that
    reports the feature is unavailable.
    - Clean up core history, compaction, telemetry, rollout, and tests to
    stop carrying ghost snapshot items.
    
    ## Testing
    - Unit tests passed for `codex-protocol`, `codex-core` targeted undo and
    compaction flows, `codex-rollout`, and `codex-app-server-protocol`.
    - Regenerated config and app-server schemas plus Python SDK artifacts
    and verified they match the checked-in outputs.
  • Cap original-detail image token estimates (#19865)
    Clamp original-detail image patch estimates to the current 10k patch
    budget so large images cannot inflate local context accounting without
    bound. Add regression coverage for an over-budget image.
    
    Fixes openai/codex#19806.
  • permissions: make runtime config profile-backed (#19606)
    ## Why
    
    This supersedes #19391. During stack repair, GitHub marked #19391 as
    merged into a temporary stack branch rather than into `main`, so the
    runtime-config change needed a fresh PR.
    
    `PermissionProfile` is now the canonical permissions shape after #19231
    because it can distinguish `Managed`, `Disabled`, and `External`
    enforcement while also carrying filesystem rules that legacy
    `SandboxPolicy` cannot represent cleanly. Core config and session state
    still needed to accept profile-backed permissions without forcing every
    profile through the strict legacy bridge, which rejected valid runtime
    profiles such as direct write roots.
    
    The unrelated CI/test hardening that previously rode along with this PR
    has been split into #19683 so this PR stays focused on the permissions
    model migration.
    
    ## What Changed
    
    - Adds `Permissions.permission_profile` and
    `SessionConfiguration.permission_profile` as constrained runtime state,
    while keeping `sandbox_policy` as a legacy compatibility projection.
    - Introduces profile setters that keep `PermissionProfile`, split
    filesystem/network policies, and legacy `SandboxPolicy` projections
    synchronized.
    - Uses a compatibility projection for requirement checks and legacy
    consumers instead of rejecting profiles that cannot round-trip through
    `SandboxPolicy` exactly.
    - Updates config loading, config overrides, session updates, turn
    context plumbing, prompt permission text, sandbox tags, and exec request
    construction to carry profile-backed runtime permissions.
    - Preserves configured deny-read entries and `glob_scan_max_depth` when
    command/session profiles are narrowed.
    - Adds `PermissionProfile::read_only()` and
    `PermissionProfile::workspace_write()` presets that match legacy
    defaults.
    
    ## Verification
    
    - `cargo test -p codex-core direct_write_roots`
    - `cargo test -p codex-core runtime_roots_to_legacy_projection`
    - `cargo test -p codex-app-server
    requested_permissions_trust_project_uses_permission_profile_intent`
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19606).
    * #19395
    * #19394
    * #19393
    * #19392
    * __->__ #19606
  • rollout: persist turn permission profiles (#18281)
    ## Why
    
    Resume and reconstruction need to preserve the permissions that were
    active for each user turn. If rollouts only keep legacy sandbox fields,
    replay cannot faithfully represent profile-shaped overrides introduced
    earlier in the stack.
    
    ## What changed
    
    This records `permission_profile` on user-turn rollout events,
    reconstructs it through history/state extraction, and updates rollout
    reconstruction and related fixtures to keep the field explicit.
    
    ## Verification
    
    - `cargo test -p codex-core --test all permissions_messages --
    --nocapture`
    - `cargo test -p codex-core --test all request_permissions --
    --nocapture`
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18281).
    * #18288
    * #18287
    * #18286
    * #18285
    * #18284
    * #18283
    * #18282
    * __->__ #18281
  • Split DeveloperInstructions into individual fragments. (#18813)
    Split DeveloperInstructions into individual fragments.
  • Organize context fragments (#18794)
    Organize context fragments under `core/context`. Implement same trait on
    all of them.
  • Update image outputs to default to high detail (#18386)
    Do not assume the default `detail`.
  • Move codex module under session (#18249)
    ## Summary
    - rename the core codex module root to session/mod.rs without using
    #[path]
    - move the codex module directory and tests under core/src/session
    - remove session/mod.rs reexports so call sites use explicit child
    module paths
    
    ## Testing
    - cargo test -p codex-core --lib
    - cargo check -p codex-core --tests
    - just fmt
    - just fix -p codex-core
    - git diff --check
  • feat(permissions): add glob deny-read policy support (#15979)
    ## Summary
    - adds first-class filesystem policy entries for deny-read glob patterns
    - parses config such as :project_roots { "**/*.env" = "none" } into
    pattern entries
    - enforces deny-read patterns in direct read/list helpers
    - fails closed for sandbox execution until platform backends enforce
    glob patterns in #18096
    - preserves split filesystem policy in turn context only when it cannot
    be reconstructed from legacy sandbox policy
    
    ## Stack
    1. This PR - glob deny-read policy/config/direct-tool support
    2. #18096 - macOS and Linux sandbox enforcement
    3. #17740 - managed deny-read requirements
    
    ## Verification
    - just fmt
    - cargo check -p codex-core -p codex-sandboxing --tests
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat(guardian): send only transcript deltas on guardian followups (#17269)
    ## Description
    
    We reuse a guardian thread for a given user thread when we can. However,
    we had always sent the full transcript history every time we made a
    followup review request to an existing guardian thread.
    
    This is especially bad for long guardian threads since we keep
    re-appending old transcript entries instead of just what has changed.
    The fix is to just send what's new.
    
    **Caveat**: Whenever a thread is compacted or rolled back, we fall back
    to sending the full transcript to guardian again since the thread's
    history has been modified. However in the happy path we get a nice
    optimization.
    
    ## Before
    Initial guardian review sends the full parent transcript:
    
    ```
    The following is the Codex agent history whose request action you are assessing...
    >>> TRANSCRIPT START
    [1] user: Please check the repo visibility and push the docs fix if needed.
    [2] tool gh_repo_view call: {"repo":"openai/codex"}
    [3] tool gh_repo_view result: repo visibility: public
    [4] assistant: The repo is public; I now need approval to push the docs fix.
    >>> TRANSCRIPT END
    The Codex agent has requested the following action:
    >>> APPROVAL REQUEST START
    ...
    >>> APPROVAL REQUEST END
    ```
    
    And a followup to the same guardian thread would send the full
    transcript again (including items 1-4 we already sent):
    ```
    The following is the Codex agent history whose request action you are assessing...
    >>> TRANSCRIPT START
    [1] user: Please check the repo visibility and push the docs fix if needed.
    [2] tool gh_repo_view call: {"repo":"openai/codex"}
    [3] tool gh_repo_view result: repo visibility: public
    [4] assistant: The repo is public; I now need approval to push the docs fix.
    [5] user: Please push the second docs fix too.
    [6] assistant: I need approval for the second docs fix.
    >>> TRANSCRIPT END
    The Codex agent has requested the following action:
    >>> APPROVAL REQUEST START
    ...
    >>> APPROVAL REQUEST END
    ```
    
    ## After
    Initial guardian review sends the full parent transcript (this is
    unchanged):
    
    ```
    The following is the Codex agent history whose request action you are assessing...
    >>> TRANSCRIPT START
    [1] user: Please check the repo visibility and push the docs fix if needed.
    [2] tool gh_repo_view call: {"repo":"openai/codex"}
    [3] tool gh_repo_view result: repo visibility: public
    [4] assistant: The repo is public; I now need approval to push the docs fix.
    >>> TRANSCRIPT END
    The Codex agent has requested the following action:
    >>> APPROVAL REQUEST START
    ...
    >>> APPROVAL REQUEST END
    ```
    
    But a followup now sends:
    ```
    The following is the Codex agent history added since your last approval assessment. Continue the same review conversation...
    >>> TRANSCRIPT DELTA START
    [5] user: Please push the second docs fix too.
    [6] assistant: I need approval for the second docs fix.
    >>> TRANSCRIPT DELTA END
    The Codex agent has requested the following next action:
    >>> APPROVAL REQUEST START
    ...
    >>> APPROVAL REQUEST END
    ```
  • [codex] allow disabling environment context injection (#16745)
    This adds an `include_environment_context` config/profile flag that
    defaults on, and guards both initial injection and later environment
    updates to allow skipping injection of `<environment_context>`.
  • [codex] allow disabling prompt instruction blocks (#16735)
    This PR adds root and profile config switches to omit the generated
    `<permissions instructions>` and `<apps_instructions>` prompt blocks
    while keeping both enabled by default, and it gates both the initial
    developer-context injection and later permissions diff injection so
    turning the permissions block off stays effective across turn-context
    overrides.
    
    Also added a prompt debug tool that can be used as `codex debug
    prompt-input "hello"` and dumps the constructed items list.
  • chore: clean up argument-comment lint and roll out all-target CI on macOS (#16054)
    ## Why
    
    `argument-comment-lint` was green in CI even though the repo still had
    many uncommented literal arguments. The main gap was target coverage:
    the repo wrapper did not force Cargo to inspect test-only call sites, so
    examples like the `latest_session_lookup_params(true, ...)` tests in
    `codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path.
    
    This change cleans up the existing backlog, makes the default repo lint
    path cover all Cargo targets, and starts rolling that stricter CI
    enforcement out on the platform where it is currently validated.
    
    ## What changed
    
    - mechanically fixed existing `argument-comment-lint` violations across
    the `codex-rs` workspace, including tests, examples, and benches
    - updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and
    `tools/argument-comment-lint/run.sh` so non-`--fix` runs default to
    `--all-targets` unless the caller explicitly narrows the target set
    - fixed both wrappers so forwarded cargo arguments after `--` are
    preserved with a single separator
    - documented the new default behavior in
    `tools/argument-comment-lint/README.md`
    - updated `rust-ci` so the macOS lint lane keeps the plain wrapper
    invocation and therefore enforces `--all-targets`, while Linux and
    Windows temporarily pass `-- --lib --bins`
    
    That temporary CI split keeps the stricter all-targets check where it is
    already cleaned up, while leaving room to finish the remaining Linux-
    and Windows-specific target-gated cleanup before enabling
    `--all-targets` on those runners. The Linux and Windows failures on the
    intermediate revision were caused by the wrapper forwarding bug, not by
    additional lint findings in those lanes.
    
    ## Validation
    
    - `bash -n tools/argument-comment-lint/run.sh`
    - `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh`
    - shell-level wrapper forwarding check for `-- --lib --bins`
    - shell-level wrapper forwarding check for `-- --tests`
    - `just argument-comment-lint`
    - `cargo test` in `tools/argument-comment-lint`
    - `cargo test -p codex-terminal-detection`
    
    ## Follow-up
    
    - Clean up remaining Linux-only target-gated callsites, then switch the
    Linux lint lane back to the plain wrapper invocation.
    - Clean up remaining Windows-only target-gated callsites, then switch
    the Windows lint lane back to the plain wrapper invocation.
  • [codex] Defer fork context injection until first turn (#15699)
    ## Summary
    - remove the fork-startup `build_initial_context` injection
    - keep the reconstructed `reference_context_item` as the fork baseline
    until the first real turn
    - update fork-history tests and the request snapshot, and add a
    `TODO(ccunningham)` for remaining nondiffable initial-context inputs
    
    ## Why
    Fork startup was appending current-session initial context immediately
    after reconstructing the parent rollout, then the first real turn could
    emit context updates again. That duplicated model-visible context in the
    child rollout.
    
    ## Impact
    Forked sessions now behave like resume for context seeding: startup
    reconstructs history and preserves the prior baseline, and the first
    real turn handles any current-session context emission.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Move string truncation helpers into codex-utils-string (#15572)
    - move the shared byte-based middle truncation logic from `core` into
    `codex-utils-string`
    - keep token-specific truncation in `codex-core` so rollout can reuse
    the shared helper in the next stacked PR
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Move git utilities into a dedicated crate (#15564)
    - create `codex-git-utils` and move the shared git helpers into it with
    file moves preserved for diff readability
    - move the `GitInfo` helpers out of `core` so stacked rollout work can
    depend on the shared crate without carrying its own git info module
    
    ---------
    
    Co-authored-by: Ahmed Ibrahim <219906144+aibrahim-oai@users.noreply.github.com>
    Co-authored-by: Codex <noreply@openai.com>
  • Trim pre-turn context updates during rollback (#15577)
    ## Summary
    - trim contiguous developer/contextual-user pre-turn updates when
    rollback cuts back to a user turn
    - add a focused history regression test for the trim behavior
    - update the rollback request-boundary snapshots to show the fixed
    non-duplicating context shape
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • feat: communication pattern v2 (#15647)
    See internal communication
  • feat: disable notifier v2 and start turn on agent interaction (#15624)
    Make the inter-agent communication start a turn
    
    As part of this, we disable the v2 notifier to prevent some odd
    behaviour where the agent restart working while you're talking to it for
    example
  • feat: use serde to differenciate inter agent communication (#15560)
    Use `serde` to encode the inter agent communication to an assistant
    message and use the decode to see if this is such a message
    
    Note: this assume serde on small pattern is fast enough
  • feat: new op type for sub-agents communication (#15556)
    Add `InterAgentCommunication` for v2 agent communication
  • feat: structured multi-agent output (#15515)
    Send input now sends messages as assistant message and with this format:
    
    ```
    author: /root/worker_a
    recipient: /root/worker_a/tester
    other_recipients: []
    Content: bla bla bla. Actual content. Only text for now
    ```
  • chore(context) Include guardian approval context (#15366)
    ## Summary
    Include the guardian context in the developer message for approvals
    
    ## Testing
    - [x] Updated unit tests
  • Split features into codex-features crate (#15253)
    - Split the feature system into a new `codex-features` crate.
    - Cut `codex-core` and workspace consumers over to the new config and
    warning APIs.
    
    Co-authored-by: Ahmed Ibrahim <219906144+aibrahim-oai@users.noreply.github.com>
    Co-authored-by: Codex <noreply@openai.com>
  • [hooks] use a user message > developer message for prompt continuation (#14867)
    ## Summary
    
    Persist Stop-hook continuation prompts as `user` messages instead of
    hidden `developer` messages + some requested integration tests
    
    This is a followup to @pakrym 's comment in
    https://github.com/openai/codex/pull/14532 to make sure stop-block
    continuation prompts match training for turn loops
    
    - Stop continuation now writes `<hook_prompt hook_run_id="...">stop
    hook's user prompt<hook_prompt>`
    - Introduces quick-xml dependency, though we already indirectly depended
    on it anyway via syntect
    - This PR only has about 500 lines of actual logic changes, the rest is
    tests/schema
    
    ## Testing
    
    Example run (with a sessionstart hook and 3 stop hooks) - this shows
    context added by session start, then two stop hooks sending their own
    additional prompts in a new turn. The model responds with a single
    message addressing both. Then when that turn ends, the hooks detect that
    they just ran using `stop_hook_active` and decide not to infinite loop
    
    test files for this (unzip, move codex -> .codex):
    [codex.zip](https://github.com/user-attachments/files/26075806/codex.zip)
    
    ```
    › cats
    
    
    • Running SessionStart hook: lighting the observatory
    
    SessionStart hook (completed)
      warning: Hi, I'm a session start hook for wizard-tower (startup).
      hook context: A wimboltine stonpet is an exotic cuisine from hyperspace
    
    • Cats are tiny zen wizards, my friend: equal parts nap, mystery, and chaos. If you want, we can talk
      cat facts, cat breeds, cat names, or build something cat-themed in this repo.
    
    • Running Stop hook: checking the tower wards
    
    • Running Stop hook: sacking the guards
    
    • Running Stop hook: hiring the guards
    
    Stop hook (completed)
      warning: Wizard Tower Stop hook reviewed the completed reply (177 chars).
    
    Stop hook (blocked)
      warning: Wizard Tower Stop hook continuing conversation
      feedback: cook the stonpet
    
    Stop hook (blocked)
      warning: Wizard Tower Stop hook continuing conversation
      feedback: eat the cooked stonpet
    
    • Stonpet’s cooked, aloha style: flash-seared over a blue quasiflame, glazed with nebula salt, and
      rested until the hyperspace juices settle.
    
      Now we eat with gratitude, my friend. One mindful bite in, and the flavor is pure cosmic surf:
      smoky, bright, and totally out of this dimension.
    
    • Running Stop hook: checking the tower wards
    
    • Running Stop hook: sacking the guards
    
    • Running Stop hook: hiring the guards
    
    Stop hook (completed)
      warning: Wizard Tower Stop hook reviewed the completed reply (285 chars).
    
    Stop hook (completed)
      warning: Wizard Tower Stop hook saw a second pass and stayed calm to avoid a loop.
    
    Stop hook (completed)
      warning: Wizard Tower Stop hook saw a second pass and stayed calm to avoid a loop.
    ```
  • Add notify to code-mode (#14842)
    Allows model to send an out-of-band notification.
    
    The notification is injected as another tool call output for the same
    call_id.
  • 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
  • sending back imagaegencall response back to responseapi (#14558)
    Sending back the ResponseItem::ImageGenerationCall as is, because it is
    now supported from the API-side.
  • 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
  • Add realtime start instructions config override (#14270)
    - add `realtime_start_instructions` config support
    - thread it into realtime context updates, schema, docs, and tests
  • unifying all image saves to /tmp to bug-proof (#14149)
    image-gen feature will have the model saving to /tmp by default + at all
    times
  • pass on save info to model + ui tweaks (#14123)
    Passing on more information to the model for context purposes, to
    streamline image-identification.