438 Commits

  • add AWS_LC_SYS_NO_JITTER_ENTROPY=1 to release musl build step to unblock releases (#12720)
    linux musl build steps in `rust-release.yml` are [currently
    broken](https://github.com/openai/codex/actions/runs/22367312571)
    because of linking issues due to ubsan-calling types (`jitterentropy`)
    leaking into the build.
    
    add `AWS_LC_SYS_NO_JITTER_ENTROPY=1` to the musl build step to avoid
    linking those ubsan-calling types. this is a more temporary fix, we need
    to clean up ubsan usage upstream so they dont leak into release-build
    steps anyways.
    
    codex's more thorough explanation below:
    
    [pr 9859](https://github.com/openai/codex/pull/9859) added [MITM
    init](https://github.com/openai/codex/pull/9859/changes#diff-db782967007060c5520651633e1ea21681d64be21f2b791d3d84519860245b97R62-R68)
    in network-proxy, which wires in cert generation code (rcgen/rustls).
    this didnt bump/change dep versions, but it changed symbol reachability
    at link time.
    
    for musl builds, that made aws-lc-sys’s jitterentropy objects get pulled
    into the final link. those objects contain UBSan calls
    (__ubsan_handle_*). musl release linking is static (*-linux-musl-gcc,
    -nodefaultlibs) and does not link a musl UBSan runtime, so link fails
    with undefined __ubsan_*.
    
    before, our custom musl CI UBSan steps (install libubsan1, RUSTC_WRAPPER
    + LD_PRELOAD, partial flag scrubbing) masked some sanitizer issues.
    after this pr, more aws-lc code became link-reachable, and that band-aid
    wasn't enough.
  • refactor: delete exec-server and move execve wrapper into shell-escalation (#12632)
    ## Why
    
    We already plan to remove the shell-tool MCP path, and doing that
    cleanup first makes the follow-on `shell-escalation` work much simpler.
    
    This change removes the last remaining reason to keep
    `codex-rs/exec-server` around by moving the `codex-execve-wrapper`
    binary and shared shell test fixtures to the crates/tests that now own
    that functionality.
    
    ## What Changed
    
    ### Delete `codex-rs/exec-server`
    
    - Remove the `exec-server` crate, including the MCP server binary,
    MCP-specific modules, and its test support/test suite
    - Remove `exec-server` from the `codex-rs` workspace and update
    `Cargo.lock`
    
    ### Move `codex-execve-wrapper` into `codex-rs/shell-escalation`
    
    - Move the wrapper implementation into `shell-escalation`
    (`src/unix/execve_wrapper.rs`)
    - Add the `codex-execve-wrapper` binary entrypoint under
    `shell-escalation/src/bin/`
    - Update `shell-escalation` exports/module layout so the wrapper
    entrypoint is hosted there
    - Move the wrapper README content from `exec-server` to
    `shell-escalation/README.md`
    
    ### Move shared shell test fixtures to `app-server`
    
    - Move the DotSlash `bash`/`zsh` test fixtures from
    `exec-server/tests/suite/` to `app-server/tests/suite/`
    - Update `app-server` zsh-fork tests to reference the new fixture paths
    
    ### Keep `shell-tool-mcp` as a shell-assets package
    
    - Update `.github/workflows/shell-tool-mcp.yml` packaging so the npm
    artifact contains only patched Bash/Zsh payloads (no Rust binaries)
    - Update `shell-tool-mcp/package.json`, `shell-tool-mcp/src/index.ts`,
    and docs to reflect the shell-assets-only package shape
    - `shell-tool-mcp-ci.yml` does not need changes because it is already
    JS-only
    
    ## Verification
    
    - `cargo shear`
    - `cargo clippy -p codex-shell-escalation --tests`
    - `just clippy`
  • chore: better bazel test logs (#12576)
    ## Summary
    
    Improve Bazel CI failure diagnostics by printing the tail of each failed
    target’s test.log directly in the GitHub Actions output.
    
    Today, when a large Bazel test target fails (for example tests of
    `codex-core`), the workflow often only shows a target-level Exit 101
    plus a path to Bazel’s test.log. That makes it hard to see the actual
    failing Rust test and panic without digging into artifacts or
    reproducing locally.
    
    This change makes the workflow automatically surface that information
    inline.
    
      ## What Changed
    
    In .github/workflows/bazel.yml:
    
      - Capture Bazel console output via tee
      - Preserve the Bazel exit code when piping (PIPESTATUS[0])
      - On failure:
          - Parse failed Bazel test targets from FAIL: //... lines
          - Resolve Bazel test log directory via bazel info bazel-testlogs
          - Print tail -n 200 for each failed target’s test.log
          - Group each target’s output in GitHub Actions logs (::group::)
    
    ## Bonus
    Disable `experimental_remote_repo_contents_cache` to prevent "Permission
    Denied"
  • ci(bazel): install Node from node-version.txt in remote image (#12205)
    ## Summary
    Install Node in the Bazel remote execution image using the version
    pinned in `codex-rs/node-version.txt`.
    
    ## Why
    `js_repl` tests run under Bazel remote execution and require a modern
    Node runtime. Runner-level `setup-node` does not guarantee Node is
    available (or recent enough) inside the remote worker container.
    
    ## What changed
    - Updated `.github/workflows/Dockerfile.bazel` to install Node from
    official tarballs at image build time.
    - Added `xz-utils` for extracting `.tar.xz` archives.
    - Copied `codex-rs/node-version.txt` into the image build context and
    used it as the single source of truth for Node version.
    - Added architecture mapping for multi-arch builds:
      - `amd64 -> x64`
      - `arm64 -> arm64`
    - Verified install during image build with:
      - `node --version`
      - `npm --version`
    
    ## Impact
    - Bazel remote workers should now have the required Node version
    available for `js_repl` tests.
    - Keeps Node version synchronized with repo policy via
    `codex-rs/node-version.txt`.
    
    ## Testing
    - Verified Dockerfile changes and build steps locally (build-time
    commands are deterministic and fail fast on unsupported arch/version
    fetch issues).
    
    ## Follow-up
    - Rebuild and publish the Bazel runner image for both `linux/amd64` and
    `linux/arm64`.
    - Update image digests in `rbe.bzl` to roll out this runtime update in
    CI.
    
    
    #### [git stack](https://github.com/magus/git-stack-cli)
    -  `1` https://github.com/openai/codex/pull/12300
    -  `2` https://github.com/openai/codex/pull/12275
    - 👉 `3` https://github.com/openai/codex/pull/12205
    -  `4` https://github.com/openai/codex/pull/12185
    -  `5` https://github.com/openai/codex/pull/10673
  • fix(linux-sandbox): mount /dev in bwrap sandbox (#12081)
    ## Summary
    - Updates the Linux bubblewrap sandbox args to mount a minimal `/dev`
    using `--dev /dev` instead of only binding `/dev/null`. tools needing
    entropy (git, crypto libs, etc.) can fail.
    
    - Changed mount order so `--dev /dev` is added before writable-root
    `--bind` mounts, preserving writable `/dev/*` submounts like `/dev/shm`
    
    ## Why
    Fixes sandboxed command failures when reading `/dev/urandom` (and
    similar standard device-node access).
    
    
    Fixes https://github.com/openai/codex/issues/12056
  • fix(ci) Fix shell-tool-mcp.yml (#11969)
    ## Summary
    We're seeing failures for shell-tool-mcp.yml during git checkouts. This
    is a quick attempt to unblock releases - we should revisit this build
    pipeline since we've hit a number of errors.
  • bazel: enforce MODULE.bazel.lock sync with Cargo.lock (#11790)
    ## Why this change
    
    When Cargo dependencies change, it is easy to end up with an unexpected
    local diff in
    `MODULE.bazel.lock` after running Bazel. That creates noisy working
    copies and pushes lockfile fixes
    later in the cycle. This change addresses that pain point directly.
    
    ## What this change enforces
    
    The expected invariant is: after dependency updates, `MODULE.bazel.lock`
    is already in sync with
    Cargo resolution. In practice, running `bazel mod deps` should not
    mutate the lockfile in a clean
    state. If it does, the dependency update is incomplete.
    
    ## How this is enforced
    
    This change adds a single lockfile check script that snapshots
    `MODULE.bazel.lock`, runs
    `bazel mod deps`, and fails if the file changes. The same check is wired
    into local workflow
    commands (`just bazel-lock-update` and `just bazel-lock-check`) and into
    Bazel CI (Linux x86_64 job)
    so drift is caught early and consistently. The developer documentation
    is updated in
    `codex-rs/docs/bazel.md` and `AGENTS.md` to make the expected flow
    explicit.
    
    `MODULE.bazel.lock` is also refreshed in this PR to match the current
    Cargo dependency resolution.
    
    ## Expected developer workflow
    
    After changing `Cargo.toml` or `Cargo.lock`, run `just
    bazel-lock-update`, then run
    `just bazel-lock-check`, and include any resulting `MODULE.bazel.lock`
    update in the same change.
    
    ## Testing
    
    Ran `just bazel-lock-check` locally.
  • Improve GitHub issue deduplication reliability by introducing a stage… (#11769)
    …d two-pass Codex search strategy with deterministic fallback behavior,
    and remove an obsolete prompt file that was no longer used.
    
    ### Changes
    - Updated `workflows/issue-deduplicator.yml`:
    - Added richer issue input fields (`state`, `updatedAt`, `labels`) for
    model context.
      - Added two candidate pools:
        - `codex-existing-issues-all.json` (`--state all`)
        - `codex-existing-issues-open.json` (`--state open`)
    - Added body truncation during JSON preparation to reduce prompt noise.
      - Added **Pass 1** Codex run over all issues.
      - Added normalization/validation step for Pass 1 output:
        - tolerant JSON parsing
        - self-issue filtering
        - deduplication
        - cap to 5 results
    - Added **Pass 2 fallback** Codex run over open issues only, triggered
    only when Pass 1 has no usable matches.
    - Added normalization/validation step for Pass 2 output (same
    filtering/dedup/cap behavior).
      - Added final deterministic selector:
        - prefer pass 2 if it finds matches
        - otherwise use pass 1
        - otherwise return no matches
      - Added observability logs:
        - pool sizes
        - per-pass parse/match status
        - final pass selected and final duplicate count
      - Kept public issue-comment format unchanged.
    - Added comment documenting that prompt text now lives inline in
    workflow.
    
    - Deleted obsolete file:
      - `/prompts/issue-deduplicator.txt`
    
    ### Behavior Impact
    - Better duplicate recall when broad search fails by retrying against
    active issues only.
    - More deterministic/noise-resistant output handling.
    - No change to workflow trigger conditions, permissions, or issue
    comment structure.
  • fix(shell-tool-mcp) build dependencies (#11709)
    ## Summary
    Based on our most recent [release
    attempt](https://github.com/openai/codex/actions/runs/21980518940/job/63501739210)
    we are not building the shell-tool-mcp job correctly. This one is
    outside my expertise, but seems mostly reasonable.
    
    ## Testing
     - [x] We really need dry runs of these
  • fix(ci) lock rust toolchain at 1.93.0 to unblock (#11703)
    ## Summary
    CI is broken on main because our CI toolchain is trying to run 1.93.1
    while our rust toolchain is locked at 1.93.0. I'm sure it's likely safe
    to upgrade, but let's keep things stable for now.
    
    ## Testing
    - [x] CI should hopefully pass
  • feat(shell-tool-mcp): add patched zsh build pipeline (#11668)
    ## Summary
    - add `shell-tool-mcp/patches/zsh-exec-wrapper.patch` against upstream
    zsh `77045ef899e53b9598bebc5a41db93a548a40ca6`
    - add `zsh-linux` and `zsh-darwin` jobs to
    `.github/workflows/shell-tool-mcp.yml`
    - stage zsh binaries under `artifacts/vendor/<target>/zsh/<variant>/zsh`
    - include zsh artifact jobs in `package.needs`
    - mark staged zsh binaries executable during packaging
    
    ## Notes
    - zsh source is cloned from `https://git.code.sf.net/p/zsh/code`
    - workflow pins zsh commit `77045ef899e53b9598bebc5a41db93a548a40ca6`
    - zsh build runs `./Util/preconfig` before `./configure`
    
    ## Validation
    - parsed workflow YAML locally (`yaml-ok`)
    - validated zsh patch applies cleanly with `git apply --check` on a
    fresh zsh clone
  • rust-release: exclude cargo-timing.html from release assets (#11564)
    ## Why
    The `release` job in `.github/workflows/rust-release.yml` uploads
    `files: dist/**` via `softprops/action-gh-release`. The downloaded
    timing artifacts include multiple files with the same basename,
    `cargo-timing.html` (one per target), which causes release asset
    collisions/races and can fail with GitHub release-assets API `404 Not
    Found` errors.
    
    ## What Changed
    - Updated the existing cleanup step before `Create GitHub Release` to
    remove all `cargo-timing.html` files from `dist/`.
    - Removed any now-empty directories after deleting those timing files.
    
    Relevant change:
    -
    https://github.com/openai/codex/blob/daba003d32f299579e9b89240aa8ebdc9f161424/.github/workflows/rust-release.yml#L423
    
    ## Verification
    - Confirmed from failing release logs that multiple `cargo-timing.html`
    files were being included in `dist/**` and that the release step failed
    while operating on duplicate-named assets.
    - Verified the workflow now deletes those files before the release
    upload step, so `cargo-timing.html` is no longer part of the release
    asset set.
  • Fix linux-musl release link failures caused by glibc-only libcap artifacts (#11556)
    Problem:
    The `aarch64-unknown-linux-musl` release build was failing at link time
    with
    `/usr/bin/ld: cannot find -lcap` while building binaries that
    transitively pull
    in `codex-linux-sandbox`.
    
    Why this is the right fix:
    `codex-linux-sandbox` compiles vendored bubblewrap and links `libcap`.
    In the
    musl jobs, we were installing distro `libcap-dev`, which provides
    host/glibc
    artifacts. That is not a valid source of target-compatible static libcap
    for
    musl cross-linking, so the fix is to produce a target-compatible libcap
    inside
    the musl tool bootstrap and point pkg-config at it.
    
    This also closes the CI coverage gap that allowed this to slip through:
    the
    `rust-ci.yml` matrix did not exercise `aarch64-unknown-linux-musl` in
    `release`
    mode. Adding that target/profile combination to CI is the right
    regression
    barrier for this class of failure.
    
    What changed:
    - Updated `.github/scripts/install-musl-build-tools.sh` to install
    tooling
      needed to fetch/build libcap sources (`curl`, `xz-utils`, certs).
    - Added deterministic libcap bootstrap in the musl tool root:
      - download `libcap-2.75` from kernel.org
      - verify SHA256
      - build with the target musl compiler (`*-linux-musl-gcc`)
      - stage `libcap.a` and headers under the target tool root
      - generate a target-scoped `libcap.pc`
    - Exported target `PKG_CONFIG_PATH` so builds resolve the staged musl
    libcap
      instead of host pkg-config/lib paths.
    - Updated `.github/workflows/rust-ci.yml` to add a `release` matrix
    entry for
      `aarch64-unknown-linux-musl` on the ARM runner.
    - Updated `.github/workflows/rust-ci.yml` to set
    `CARGO_PROFILE_RELEASE_LTO=thin` for `release` matrix entries (and keep
    `fat`
    for non-release entries), matching the release-build tradeoff already
    used in
      `rust-release.yml` while reducing CI runtime.
    
    Verification:
    - Reproduced the original failure in CI-like containers:
      - `aarch64-unknown-linux-musl` failed with `cannot find -lcap`.
    - Verified the underlying mismatch by forcing host libcap into the link:
      - link then failed with glibc-specific unresolved symbols
        (`__isoc23_*`, `__*_chk`), confirming host libcap was unsuitable.
    - Verified the fix in CI-like containers after this change:
    - `cargo build -p codex-linux-sandbox --target
    aarch64-unknown-linux-musl --release` -> pass
    - `cargo build -p codex-linux-sandbox --target x86_64-unknown-linux-musl
    --release` -> pass
    - Triggered `rust-ci` on this branch and confirmed the new job appears:
    - `Lint/Build — ubuntu-24.04-arm - aarch64-unknown-linux-musl (release)`
  • ci: capture cargo timings in Rust CI and release workflows (#11543)
    ## Why
    We want actionable build-hotspot data from CI so we can tune Rust
    workflow performance (for example, target coverage, cache behavior, and
    job shape) based on actual compile-time bottlenecks.
    
    `cargo` timing reports are lightweight and provide a direct way to
    inspect where compilation time is spent.
    
    ## What Changed
    - Updated `.github/workflows/rust-release.yml` to run `cargo build` with
    `--timings` and upload `target/**/cargo-timings/cargo-timing.html`.
    - Updated `.github/workflows/rust-release-windows.yml` to run `cargo
    build` with `--timings` and upload
    `target/**/cargo-timings/cargo-timing.html`.
    - Updated `.github/workflows/rust-ci.yml` to:
      - run `cargo clippy` with `--timings`
      - run `cargo nextest run` with `--timings` (stable-compatible)
    - upload `target/**/cargo-timings/cargo-timing.html` artifacts for both
    the clippy and nextest jobs
    
    Artifacts are matrix-scoped via artifact names so timings can be
    compared per target/profile.
    
    ## Verification
    - Confirmed the net diff is limited to:
      - `.github/workflows/rust-ci.yml`
      - `.github/workflows/rust-release.yml`
      - `.github/workflows/rust-release-windows.yml`
    - Verified timing uploads are added immediately after the corresponding
    timed commands in each workflow.
    - Confirmed stable Cargo accepts plain `--timings` for the compile phase
    (`cargo test --no-run --timings`) and generates
    `target/cargo-timings/cargo-timing.html`.
    - Ran VS Code diagnostics on modified workflow files; no new diagnostics
    were introduced by these changes.
  • build(linux-sandbox): always compile vendored bubblewrap on Linux; remove CODEX_BWRAP_ENABLE_FFI (#11498)
    ## Summary
    This PR removes the temporary `CODEX_BWRAP_ENABLE_FFI` flag and makes
    Linux builds always compile vendored bubblewrap support for
    `codex-linux-sandbox`.
    
    ## Changes
    - Removed `CODEX_BWRAP_ENABLE_FFI` gating from
    `codex-rs/linux-sandbox/build.rs`.
    - Linux builds now fail fast if vendored bubblewrap compilation fails
    (instead of warning and continuing).
    - Updated fallback/help text in
    `codex-rs/linux-sandbox/src/vendored_bwrap.rs` to remove references to
    `CODEX_BWRAP_ENABLE_FFI`.
    - Removed `CODEX_BWRAP_ENABLE_FFI` env wiring from:
      - `.github/workflows/rust-ci.yml`
      - `.github/workflows/bazel.yml`
      - `.github/workflows/rust-release.yml`
    
    ---------
    
    Co-authored-by: David Zbarsky <zbarsky@openai.com>
  • ci(windows): use DotSlash for zstd in rust-release-windows (#11542)
    ## Why
    Installing `zstd` via Chocolatey in
    `.github/workflows/rust-release-windows.yml` has been taking about a
    minute on Windows release runs. This adds avoidable latency to each
    release job.
    
    Using DotSlash removes that package-manager install step and pins the
    exact binary we use for compression.
    
    ## What Changed
    - Added `.github/workflows/zstd`, a DotSlash wrapper that fetches
    `zstd-v1.5.7-win64.zip` with pinned size and digest.
    - Updated `.github/workflows/rust-release-windows.yml` to:
      - install DotSlash via `facebook/install-dotslash@v2`
    - replace `zstd -T0 -19 ...` with
    `${GITHUB_WORKSPACE}/.github/workflows/zstd -T0 -19 ...`
    - `windows-aarch64` uses the same win64 upstream zstd artifact because
    upstream releases currently publish `win32` and `win64` binaries.
    
    ## Verification
    - Verified the workflow now resolves the DotSlash file from
    `${GITHUB_WORKSPACE}` while the job runs with `working-directory:
    codex-rs`.
    - Ran VS Code diagnostics on changed files:
      - `.github/workflows/rust-release-windows.yml`
      - `.github/workflows/zstd`
  • ci: remove actions/cache from rust release workflows (#11540)
    ## Why
    
    `rust-release` cache restore has had very low practical value, while
    cache save consistently costs significant time (usually adding ~3
    minutes to the critical path of a release workflow).
    
    From successful release-tag runs with cache steps (`289` runs total):
    - Alpha tags: cache download averaged ~5s/run, cache upload averaged
    ~230s/run.
    - Stable tags: cache download averaged ~5s/run, cache upload averaged
    ~227s/run.
    - Windows release builds specifically: download ~2s/run vs upload
    ~169-170s/run.
    
    Hard step-level signal from the same successful release-tag runs:
    - Cache restore (`Run actions/cache`): `2,314` steps, total `1,515s`
    (~0.65s/step).
    - `95.3%` of restore steps finished in `<=1s`; `99.7%` finished in
    `<=2s`; `0` steps took `>=10s`.
    - Cache save (`Post Run actions/cache`): `2,314` steps, total `66,295s`
    (~28.65s/step).
    
    Run-level framing:
    - Download total was `<=10s` in `288/289` runs (`99.7%`).
    - Upload total was `>=120s` in `285/289` runs (`98.6%`).
    
    The net effect is that release jobs are spending time uploading caches
    that are rarely useful for subsequent runs.
    
    ## What Changed
    
    - Removed the `actions/cache@v5` step from
    `.github/workflows/rust-release.yml`.
    - Removed the `actions/cache@v5` step from
    `.github/workflows/rust-release-windows.yml`.
    - Left build, signing, packaging, and publishing flow unchanged.
    
    ## Validation
    
    - Queried historical `rust-release` run/job step timing and compared
    cache download vs upload for alpha and stable release tags.
    - Spot-checked release logs and observed repeated `Cache not found ...`
    followed by `Cache saved ...` patterns.
  • fix: add --test_verbose_timeout_warnings to bazel.yml (#11522)
    This is in response to seeing this on BuildBuddy:
    
    > There were tests whose specified size is too big. Use the
    --test_verbose_timeout_warnings command line option to see which ones
    these are.
  • feat: try to fix bugs I saw in the wild in the resource parsing logic (#11513)
    I gave Codex the following bug report about the logic to report the
    host's resources introduced in
    https://github.com/openai/codex/pull/11488 and this PR is its proposed
    fix.
    
    The fix seems like an escaping issue, mostly.
    
    ---
    
    The logic to print out the runner specs has an awk error on Mac:
    
    ```
    Runner: GitHub Actions 1014936475
    OS: macOS 15.7.3
    Hardware model: VirtualMac2,1
    CPU architecture: arm64
    Logical CPUs: 5
    Physical CPUs: 5
    awk: syntax error at source line 1
     context is
    	{printf >>>  \ <<< "%.1f GiB\\n\", $1 / 1024 / 1024 / 1024}
    awk: illegal statement at source line 1
    Total RAM: 
    Disk usage:
    Filesystem      Size    Used   Avail Capacity iused ifree %iused  Mounted on
    /dev/disk3s5   320Gi   237Gi    64Gi    79%    2.0M  671M    0%   /System/Volumes/Data
    ```
    
    as well as Linux:
    
    ```
    Runner: GitHub Actions 1014936469
    OS: Linux runnervmwffz4 6.11.0-1018-azure #18~24.04.1-Ubuntu SMP Sat Jun 28 04:46:03 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
    awk: cmd. line:1: /Model name/ {gsub(/^[ \t]+/,\"\",$2); print $2; exit}
    awk: cmd. line:1:                              ^ backslash not last character on line
    CPU model: 
    Logical CPUs: 4
    awk: cmd. line:1: /MemTotal/ {printf \"%.1f GiB\\n\", $2 / 1024 / 1024}
    awk: cmd. line:1:                    ^ backslash not last character on line
    Total RAM: 
    Disk usage:
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/root        72G   50G   22G  70% /
    ```
  • feat: build windows support binaries in parallel (#11500)
    Windows release builds were compiling and linking four release binaries
    on a single runner, which slowed the release pipeline. The
    Windows-specific logic also made `rust-release.yml` harder to read and
    maintain.
    
    ## What Changed
    
    - Extracted Windows release logic into a reusable workflow at
    `.github/workflows/rust-release-windows.yml`.
    - Updated `.github/workflows/rust-release.yml` to call the reusable
    Windows workflow via `workflow_call`.
    - Parallelized Windows binary builds with one 4-entry matrix over two
    targets (`x86_64-pc-windows-msvc`, `aarch64-pc-windows-msvc`) and two
    bundles (`primary`, `helpers`).
    - Kept signing centralized per target by downloading both prebuilt
    bundles and signing all four executables together.
    - Preserved final release artifact behavior and filtered intermediate
    `windows-binaries*` artifacts out of the published release asset set.
  • feat: use more powerful machines for building Windows releases (#11488)
    Windows release builds in `.github/workflows/rust-release.yml` were
    still using GitHub-hosted `windows-latest` and `windows-11-arm` runners.
    This change aligns release builds with the faster dedicated Codex runner
    pool already used in CI, and adds machine-spec logging at startup so
    runner capacity (CPU/RAM/disk) is visible in build logs.
    
    ## What Changed
    
    - Updated the `build` job to support matrix entries that provide a full
    `runs_on` object:
      - `runs-on: ${{ matrix.runs_on || matrix.runner }}`
    - Switched Windows release matrix entries to Codex runners:
      - `windows-latest` -> `windows-x64` with:
        - `group: codex-runners`
        - `labels: codex-windows-x64`
      - `windows-11-arm` -> `windows-arm64` with:
        - `group: codex-runners`
        - `labels: codex-windows-arm64`
    - Updated the ARM-specific zstd install condition to match the new
    runner id:
      - `matrix.runner == 'windows-arm64'`
    - Added early platform-specific runner diagnostics steps
    (Linux/macOS/Windows) that print OS, CPU, logical CPU count, total RAM,
    and disk usage.
  • feat: remove "cargo check individual crates" from CI (#11475)
    I think this check has outlived its usefulness. It is often one of the
    last CI jobs to finish when we put up a PR, so this should save us some
    time.
  • ci: fall back to local Bazel on forks without BuildBuddy key (#11359)
    ## Summary
    - detect whether BUILDBUDDY_API_KEY is present in Bazel CI
    - keep existing remote BuildBuddy path when key is available
    - add a local fallback path for fork PRs without secrets by clearing
    remote cache/executor/BES endpoints
    - document each fallback flag inline with links to Bazel docs
    
    ## Testing
    - ruby -e 'require "yaml";
    YAML.load_file(".github/workflows/bazel.yml"); puts "ok"'
    - verified Bazel docs/flag references used in workflow comments
  • Use thin LTO for alpha Rust release builds (#11348)
    We are looking to speed up build times for alpha releases, but we do not
    want to completely compromise on runtime performance by shipping debug
    builds. This PR changes our CI so that alpha releases build with
    `lto="thin"` instead of `lto="fat"`.
    
    Specifically, this change keeps `[profile.release] lto = "fat"` as the
    default in `Cargo.toml`, but overrides LTO in CI using
    `CARGO_PROFILE_RELEASE_LTO`:
    - `rust-release.yml`: use `thin` for `-alpha` tags, otherwise `fat`
    - `shell-tool-mcp.yml`: use `thin` for `-alpha` versions, otherwise
    `fat`
    
    Tradeoffs:
    - Alpha binaries may be somewhat larger and/or slightly slower than
    fat-LTO builds
    - LTO policy now lives in workflow logic for two pipelines, so
    consistency must be maintained across both files
    
    Note `CARGO_PROFILE_<name>_LTO` is documented on
    https://doc.rust-lang.org/cargo/reference/environment-variables.html#configuration-environment-variables.
  • # Use @openai/codex dist-tags for platform binaries instead of separate package names (#11339)
    https://github.com/openai/codex/pull/11318 introduced logic to publish
    platform artifacts as separate npm packages (for example,
    `@openai/codex-darwin-arm64`, `@openai/codex-linux-x64`, etc.). That
    requires provisioning and maintaining multiple package entries in npm,
    which we want to avoid.
    
    We still need to keep the package-size mitigation (platform-specific
    payloads), but we want that layout to live under a single npm package
    namespace (`@openai/codex`) using dist-tags.
    
    We also need to preserve pre-release workflows where users install
    `@openai/codex@alpha` and get platform-appropriate binaries.
    
    Additionally, we want GitHub Release assets to group Codex npm tarballs
    together, so platform tarballs should follow the same `codex-npm-*`
    filename prefix as the main Codex tarball.
    
    ## Release Strategy (New Scheme)
    
    We publish **one npm package name for Codex binaries** (`@openai/codex`)
    and use **dist-tags** to select platform-specific payloads. This avoids
    creating separate platform package names while keeping the package size
    split by platform.
    
    ### What gets published
    
    #### Mainline release (`x.y.z`)
    
    - `@openai/codex@latest` (meta package)
    - `@openai/codex@darwin-arm64`
    - `@openai/codex@darwin-x64`
    - `@openai/codex@linux-arm64`
    - `@openai/codex@linux-x64`
    - `@openai/codex@win32-arm64`
    - `@openai/codex@win32-x64`
    - `@openai/codex-responses-api-proxy@latest`
    - `@openai/codex-sdk@latest`
    
    #### Alpha release (`x.y.z-alpha.N`)
    
    - `@openai/codex@alpha` (meta package)
    - `@openai/codex@alpha-darwin-arm64`
    - `@openai/codex@alpha-darwin-x64`
    - `@openai/codex@alpha-linux-arm64`
    - `@openai/codex@alpha-linux-x64`
    - `@openai/codex@alpha-win32-arm64`
    - `@openai/codex@alpha-win32-x64`
    - `@openai/codex-responses-api-proxy@alpha`
    - `@openai/codex-sdk@alpha`
    
    As an example, the `package.json` for `@openai/codex@alpha` (using
    `0.99.0-alpha.17` as the `version`) would be:
    
    ```
    {
      "name": "@openai/codex",
      "version": "0.99.0-alpha.17",
      "license": "Apache-2.0",
      "bin": {
        "codex": "bin/codex.js"
      },
      "type": "module",
      "engines": {
        "node": ">=16"
      },
      "files": [
        "bin"
      ],
      "repository": {
        "type": "git",
        "url": "git+https://github.com/openai/codex.git",
        "directory": "codex-cli"
      },
      "packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
      "optionalDependencies": {
        "@openai/codex-linux-x64": "npm:@openai/codex@0.99.0-alpha.17-linux-x64",
        "@openai/codex-linux-arm64": "npm:@openai/codex@0.99.0-alpha.17-linux-arm64",
        "@openai/codex-darwin-x64": "npm:@openai/codex@0.99.0-alpha.17-darwin-x64",
        "@openai/codex-darwin-arm64": "npm:@openai/codex@0.99.0-alpha.17-darwin-arm64",
        "@openai/codex-win32-x64": "npm:@openai/codex@0.99.0-alpha.17-win32-x64",
        "@openai/codex-win32-arm64": "npm:@openai/codex@0.99.0-alpha.17-win32-arm64"
      }
    }
    ```
    
    Note that the keys in `optionalDependencies` have "clean" names, but the
    values have the tag embedded.
    
    ### Important note
    
    **Note:** Because we never created the new platform package names on npm
    (for example,
    `@openai/codex-darwin-arm64`) since #11318 landed, there are no extra
    npm packages to clean up.
    
    ## What changed
    
    ### 1. Stage platform tarballs as `@openai/codex` with platform-specific
    versions
    
    File: `codex-cli/scripts/build_npm_package.py`
    
    - Added `CODEX_NPM_NAME = "@openai/codex"` and platform metadata
    `npm_tag` values:
    - `darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`,
    `win32-arm64`, `win32-x64`
    - For platform package staging (`codex-<platform>` inputs), switched
    generated `package.json` from:
      - `name = @openai/codex-<platform>`
      to:
      - `name = @openai/codex`
    - Added `compute_platform_package_version(version, platform_tag)` so
    platform tarballs have unique
    versions (`<release-version>-<platform-tag>`), which is required because
    npm forbids re-publishing
      the same `name@version`.
    
    ### 2. Point meta package optional dependencies at dist-tags on
    `@openai/codex`
    
    File: `codex-cli/scripts/build_npm_package.py`
    
    - Updated `optionalDependencies` generation for the main `codex` package
    to use npm alias syntax:
    - key remains alias package name (for example,
    `@openai/codex-darwin-arm64`) so runtime lookup behavior is unchanged
      - value now resolves to `@openai/codex` by dist-tag
    - Stable releases emit tags like `npm:@openai/codex@darwin-arm64`.
    - Alpha releases (`x.y.z-alpha.N`) emit tags like
    `npm:@openai/codex@alpha-darwin-arm64`.
    
    ### 3. Publish with per-tarball dist-tags in release CI
    
    File: `.github/workflows/rust-release.yml`
    
    - Reworked npm publish logic to derive the publish tag per tarball
    filename:
      - platform tarballs publish with `<platform>` tags for stable releases
    - platform tarballs publish with `alpha-<platform>` tags for alpha
    releases
    - top-level tarballs (`codex`, `codex-responses-api-proxy`, `codex-sdk`)
    continue using
    the existing channel tag policy (`latest` implicit for stable, `alpha`
    for alpha)
    - Added fail-fast behavior for unexpected tarball names to avoid silent
    mispublishes.
    
    ### 4. Normalize Codex platform tarball filenames for GitHub Release
    grouping
    
    Files: `scripts/stage_npm_packages.py`,
    `.github/workflows/rust-release.yml`
    
    - Renamed staged platform tarball filenames from:
      - `codex-linux-<arch>-npm-<version>.tgz`
      - `codex-darwin-<arch>-npm-<version>.tgz`
      - `codex-win32-<arch>-npm-<version>.tgz`
    - To:
      - `codex-npm-linux-<arch>-<version>.tgz`
      - `codex-npm-darwin-<arch>-<version>.tgz`
      - `codex-npm-win32-<arch>-<version>.tgz`
    
    This keeps all Codex npm artifacts grouped under a common `codex-npm-`
    prefix in GitHub Releases.
    
    ### 5. Documentation update
    
    File: `codex-cli/scripts/README.md`
    
    - Updated staging docs to clarify that platform-native variants are
    published as dist-tagged
      `@openai/codex` artifacts rather than separate npm package names.
    
    ## Resulting behavior
    
    - Mainline release:
      - `@openai/codex@latest` resolves the meta package
    - meta package optional dependencies resolve
    `@openai/codex@<platform-tag>`
    - Alpha release:
      - users can continue installing `@openai/codex@alpha`
    - alpha meta package optional dependencies resolve
    `@openai/codex@alpha-<platform-tag>`
    - Release assets:
    - Codex npm tarballs share `codex-npm-` prefix for cleaner grouping in
    GitHub Releases
    
    This preserves platform-specific payload distribution while avoiding
    separate npm package names and
    improves release-asset discoverability.
    
    ## Validation notes
    
    - Verified staged `package.json` output for stable and alpha meta
    packages includes expected alias targets.
    - Verified staged platform package manifests are `name=@openai/codex`
    with unique platform-suffixed versions.
    - Verified publish tag derivation maps renamed platform tarballs to
    expected stable and alpha dist-tags.
  • fix: remove config.schema.json from tag check (#10980)
    Given that we have https://github.com/openai/codex/pull/10977, the
    existing "Verify config schema fixture" step seems unnecessary. Further,
    because it happens as part of the `tag-check` job (which is meant to be
    fast), it slows down the entire build process because it delays the more
    expensive steps from starting.
  • feat(linux-sandbox): add bwrap support (#9938)
    ## Summary
    This PR introduces a gated Bubblewrap (bwrap) Linux sandbox path. The
    curent Linux sandbox path relies on in-process restrictions (including
    Landlock). Bubblewrap gives us a more uniform filesystem isolation
    model, especially explicit writable roots with the option to make some
    directories read-only and granular network controls.
    
    This is behind a feature flag so we can validate behavior safely before
    making it the default.
    
    - Added temporary rollout flag:
      - `features.use_linux_sandbox_bwrap`
    - Preserved existing default path when the flag is off.
    - In Bubblewrap mode:
    - Added internal retry without /proc when /proc mount is not permitted
    by the host/container.
  • chore: remove deprecated mcp-types crate (#10357)
    https://github.com/openai/codex/pull/10349 migrated us off of
    `mcp-types`, so this PR deletes the code.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/10357).
    * __->__ #10357
    * #10349
    * #10356
  • fix: unify npm publish call across shell-tool-mcp.yml and rust-release.yml (#10182)
    We are seeing flakiness in the `npm publish` step for
    https://www.npmjs.com/package/@openai/codex-shell-tool-mcp, so this is a
    shot in the dark for a fix:
    
    https://github.com/openai/codex/actions/runs/21490679301/job/61913765060
    
    Note this removes `actions/checkout@v6` and `pnpm/action-setup@v4`
    steps, which I believe are superflous for the `npm publish` call.
  • chore: unify log queries (#10152)
    Unify log queries to only have SQLX code in the runtime and use it for
    both the log client and for tests
  • fix: remove references to corepack (#10138)
    Currently, our `npm publish` logic is failing.
    
    There were a number of things that were merged recently that seemed to
    contribute to this situation, though I think we have fixed most of them,
    but this one stands out:
    
    https://github.com/openai/codex/pull/10115
    
    As best I can tell, we tried to fix the pnpm version to a specific hash,
    but we did not do it consistently (though `shell-tool-mcp/package.json`
    had it specified twice...), so for this PR, I ran:
    
    ```
    $ git ls-files | grep package.json
    codex-cli/package.json
    codex-rs/responses-api-proxy/npm/package.json
    package.json
    sdk/typescript/package.json
    shell-tool-mcp/package.json
    ```
    
    and ensured that all of them now have this line:
    
    ```json
      "packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264"
    ```
    
    I also went and deleted all of the `corepack` stuff that was added by
    https://github.com/openai/codex/pull/10115.
    
    If someone can explain why we need it and verify it does not break `npm
    publish`, then we can bring it back.
  • fix(ci) missing package.json for shell-mcp-tool (#10135)
    ## Summary
    This _should_ be the final place to fix.
  • update the ci pnpm workflow for shell-tool-mcp to use corepack for pnpm versioning (#10115)
    This updates the CI workflows for shell-tool-mcp to use the pnpm version
    from package.json and print it in the build for verification.
    
    I have read the CLA Document and I hereby sign the CLA
  • fix(ci) fix shell-tool-mcp version v2 (#10101)
    ## summary
    we had a merge conflict from the linux musl fix, let's get this squared
    away.
  • Update shell-tool-mcp.yml (#10095)
    ## Summary
    #10004 broke the builds for shell-tool-mcp.yml - we need to copy over
    the build configuration from there.
    
    ## Testing
    - [x] builds
  • Upgrade to rust 1.93 (#10080)
    I needed to upgrade bazel one to get gnullvm artifacts and then noticed
    monorepo had drifted forward. They should move in lockstep. Also 1.93
    already shipped so we can try that instead.
  • Update shell-tool-mcp.yml (#10092)
    ## Summary
    Remove pnpm version so we rely on package.json instead, and fix the
    mismatch due to https://github.com/openai/codex/pull/9992
  • feat: sqlite 1 (#10004)
    Add a `.sqlite` database to be used to store rollout metatdata (and
    later logs)
    This PR is phase 1:
    * Add the database and the required infrastructure
    * Add a backfill of the database
    * Persist the newly created rollout both in files and in the DB
    * When we need to get metadata or a rollout, consider the `JSONL` as the
    source of truth but compare the results with the DB and show any errors
  • ensure codex bundle zip is created in dist/ (#9934)
    cd-ing into the tmp bundle directory was putting the .zip in the wrong
    place