Commit Graph

403 Commits

  • [codex] Fix Windows BuildBuddy Bazel wrapper execution (#25915)
    ## Why
    
    #25156 moved Bazel CI launches into a shared Python wrapper. On Windows,
    launching Bazel with `os.execvp` can split the spaced
    `--test_env=PATH=...` argument and fail to propagate the eventual Bazel
    exit status, allowing jobs to pass without running tests. This reapplies
    the wrapper after #25909 with a Windows-safe launch path.
    
    ## What changed
    
    Use a waited `subprocess.run` launch on Windows while preserving
    `os.execvp` on Unix. Add a process-level regression test for spaced
    arguments and child exit status, and run it on Windows Bazel shard 1.
    
    ## Experiment
    
    To confirm Bazel was actually invoking tests, patch `87b61d0be6`
    temporarily added an intentionally failing `codex-core` unit test. Bazel
    failed on that sentinel on all three major platforms:
    
    - [Linux Bazel
    test](https://github.com/openai/codex/actions/runs/26841132773/job/79151062486)
    - [macOS Bazel
    test](https://github.com/openai/codex/actions/runs/26841132773/job/79151062362)
    - [Windows Bazel test shard
    1/4](https://github.com/openai/codex/actions/runs/26841132773/job/79151062155)
    
    The sentinel was removed after collecting this evidence. Windows Bazel
    [clippy](https://github.com/openai/codex/actions/runs/26841132773/job/79151062914)
    and [release
    verification](https://github.com/openai/codex/actions/runs/26841132773/job/79151062739)
    also passed.
    
    ## Validation
    
    After removing the sentinel, `just test -p codex-core` no longer
    reported it. The local run retained two unrelated environment-specific
    failures.
  • [codex] Publish Python runtime wheels with Python SDK releases (#25906)
    ## Summary
    - stop publishing Python runtime wheels as a side effect of Rust
    releases
    - publish runtime wheels from the Python SDK release workflow, either
    explicitly before updating the SDK pin or immediately before a
    `python-v*` SDK release
    - resolve the runtime release from the requested version or the SDK
    package's exact `openai-codex-cli-bin` pin
    - build two musllinux-tagged wheels from the Rust-release Linux package
    archives alongside the six existing runtime wheels
    - validate SDK beta tags before any PyPI write
    
    ## Release configuration
    - update the `openai-codex-cli-bin` PyPI trusted publisher to trust
    `.github/workflows/python-sdk-release.yml` and the
    `publish-python-runtime` job
    
    ## Pin update flow
    - run the `python-sdk-release` workflow manually with the new runtime
    version before opening or updating the SDK pin PR
    - after the pin lands, a `python-v*` SDK tag republishes with
    `skip-existing: true` before publishing the SDK package
    
    ## Validation
    - ran `just fmt`
    - validated the edited workflow YAML
    - validated the embedded `publish-python-runtime` Bash with `bash -n`
    - validated manual `0.136.0 -> rust-v0.136.0` mapping
    - validated tag-driven `python-v0.1.0b3 -> 0.132.0 -> rust-v0.132.0`
    mapping
    - validated rejection of an invalid SDK tag before publication
    - confirmed `rust-v0.136.0` contains the two required Linux package
    archives
    - CI will provide the full test signal
  • Use environment secrets for Azure signing (#24859)
    ## Summary
    - Move Azure Trusted Signing values out of reusable workflow-call
    secrets and into the `azure-artifact-signing` environment scope
    - Attach the Windows signing job to the `azure-artifact-signing`
    environment so it can resolve the signing secrets directly
    - Stop inheriting caller secrets for the Windows release reusable
    workflow
    
    ## Validation
    - `git diff --check -- .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
    - `ruby -e 'require "yaml"; ARGV.each { |path| YAML.load_file(path);
    puts "ok #{path}" }' .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
  • [codex] Pin Python SDK to glibc-compatible runtime (#25907)
    ## Summary
    - pin the Python SDK runtime package to `openai-codex-cli-bin==0.136.0`
    so Ubuntu/glibc installs resolve a compatible wheel
    - refresh generated SDK artifacts and lock data for the runtime update
    - keep newly generated client-message-id wire models internal to the
    generated protocol layer
    
    ## Dependency
    - merge #25906 first so the Python SDK release publishes both manylinux
    and musllinux runtime wheels before publishing the package with this pin
    
    ## Validation
    - ran `just fmt`
    - regenerated the Python public API helpers
    - validated the edited workflow YAML
    - CI passed 29/29 checks
  • Fix Windows release PDB staging (#25916)
    ## Summary
    - Teach the Windows release prebuild staging step to locate Rust/MSVC
    PDBs emitted with crate-style underscore names.
    - Stage PDBs under the shipped hyphenated binary names so the downstream
    symbol archive step keeps the same artifact contract.
    - Keep a fallback for already-hyphenated PDB names and fail with a clear
    diagnostic if neither form exists.
    
    ## Root cause
    The recent symbol publishing change in #25649 started copying
    `${binary}.pdb` from `target/<triple>/release` during Windows prebuild
    staging. Cargo still emits the `.exe` with the hyphenated binary name,
    but MSVC PDBs for hyphenated Rust crates are emitted with underscores,
    for example `codex_app_server.pdb` for `codex-app-server.exe`. The
    release workflow was still building into the expected directory; the new
    PDB copy step was looking for the wrong filename.
    
    ## Impact
    This unblocks the `rust-release` Windows prebuilt-binary jobs for
    hyphenated binaries while preserving the hyphenated PDB names consumed
    by the final Windows release packaging and symbol archive steps.
    
    ## Validation
    - `just fmt` from `codex-rs`
    - `git diff --check -- .github/workflows/rust-release-windows.yml`
    - Parsed `.github/workflows/rust-release-windows.yml` as YAML locally
    - Local bash staging sanity test for both underscore-emitted and
    hyphenated PDB filenames
  • [codex] Revert shared BuildBuddy Bazel wrapper (#25909)
    ## Why
    
    PR #25905 intentionally adds a failing `codex-core` unit test, but its
    [Bazel test on Windows
    check](https://github.com/openai/codex/actions/runs/26837526950/job/79135369259)
    passed. That shows the Bazel configuration introduced by #25156 is not
    behaving as expected, so revert it while the configuration can be
    investigated separately.
    
    ## What changed
    
    Revert #25156 in full, restoring the previous Bazel remote
    configuration, CI scripts, workflows, `rusty_v8` handling, and
    documentation. This removes the shared BuildBuddy wrapper and its tests.
    
    ## Validation
    
    Not run locally; this exact revert was prioritized for a fast rollback.
  • Route Bazel CI through shared BuildBuddy remote config wrapper (#25156)
    ## Why
    
    Bazel remote configuration was selected in several CI scripts and
    workflow steps. That made the BuildBuddy tenant policy easy to duplicate
    and harder to audit, especially for fork pull requests that must not use
    the OpenAI tenant.
    
    This builds on
    [sluongng/buildbuddy-ci-host-routing](https://github.com/openai/codex/compare/main...sluongng:codex:sluongng/buildbuddy-ci-host-routing)
    and consolidates the policy in one place.
    
    ## What to do if this breaks you
    
    See `codex-rs/docs/bazel.md` for details. TLDR:
    
    1. make a BuildBuddy API key and put it in `~/.bazelrc`
    2. if you're an OpenAI employee, add `common
    --config=buildbuddy-openai-rbe` to `user.bazelrc` in the repo root
    
    Run `just bazel-test` to ensure it works.
    
    Note that `just bazel-remote-test` no longer exists, you need to select
    a remote configuration as documented to use RBE.
    
    ## What changed
    
    - Add `.github/scripts/run_bazel_with_buildbuddy.py` as the shared Bazel
    wrapper and Python library. It selects the OpenAI host only for trusted
    upstream GitHub Actions runs, routes keyed fork runs to the generic
    host, and falls back to local Bazel execution when no key is available.
    - Move endpoint selection into explicit `.bazelrc` configurations and
    update Bazel CI, query helpers, and `rusty_v8` staging to use the shared
    policy. Loading-phase target-discovery queries remain local.
    - Add wrapper and `rusty_v8` unit coverage, plus `just test-scripts` for
    the `.github/scripts` Python tests.
    - Document local Bazel usage, `user.bazelrc` setup, BuildBuddy
    configurations, and CI behavior in `codex-rs/docs/bazel.md`.
    
    ## Validation
    
    - `just test-scripts`
    - `bash -n .github/scripts/run-bazel-ci.sh
    .github/scripts/run-bazel-query-ci.sh
    .github/scripts/run-argument-comment-lint-bazel.sh
    scripts/list-bazel-clippy-targets.sh`
    - `python3 -m py_compile .github/scripts/run_bazel_with_buildbuddy.py
    .github/scripts/test_run_bazel_with_buildbuddy.py
    .github/scripts/test_rusty_v8_bazel.py
    .github/scripts/rusty_v8_bazel.py`
    - `ruff check .github/scripts/run_bazel_with_buildbuddy.py
    .github/scripts/test_run_bazel_with_buildbuddy.py
    .github/scripts/test_rusty_v8_bazel.py
    .github/scripts/rusty_v8_bazel.py`
  • [codex] Use git CLI for Cargo fetches across Rust workflows (#25775)
    ## Why
    Cargo's libgit2 transport has intermittently failed while fetching git
    dependencies with nested submodules.
    [#25644](https://github.com/openai/codex/pull/25644) applied
    `CARGO_NET_GIT_FETCH_WITH_CLI=true` to the main Rust release build after
    macOS SecureTransport/libgit2 failures while cloning `libwebrtc`'s
    nested `libyuv` submodule. Similar flakes can affect other Cargo-bearing
    Rust jobs.
    
    ## What changed
    Configure `CARGO_NET_GIT_FETCH_WITH_CLI=true` at workflow scope for the
    remaining Cargo-bearing Rust workflows:
    
    - fast Rust CI and `cargo-deny`
    - reusable Windows and argument-comment-lint release workflows
    - `rusty-v8-release` and `v8-canary` Cargo builds and smoke tests
    
    The full Rust CI, reusable nextest workflow, and primary Rust release
    build already had the override. Bazel-only workflows are unchanged
    because they use a different dependency fetch path.
    
    ## Validation
    - Parsed all `.github/workflows/*.yml` files as YAML.
    - Scanned Cargo-bearing workflows to confirm they configure
    `CARGO_NET_GIT_FETCH_WITH_CLI`.
  • [codex] Add comprehensive root formatting check (#25683)
    ## Why
    
    The root formatting entrypoints could drift: `just fmt` did not format
    the Justfile itself, and the CI-facing check recipe only checked Python
    scripts instead of matching everything formatted by `just fmt`.
    
    ## What changed
    
    - Add a shared cross-platform Python formatter driver used by both `just
    fmt` and `just fmt-check`.
    - Run Justfile, Rust, Python SDK, and internal-script formatter groups
    concurrently while buffering each formatter group's output until it
    finishes.
    - Log formatter starts immediately, then print each formatter group's
    labeled output when it completes.
    - Keep the SDK lint-fix and Ruff formatting passes ordered, with source
    comments explaining their distinct roles and the check-mode equivalents.
    - Run Ruff through shared `uv run --no-sync --with ruff` overlays so
    formatting works on clean glibc Linux checkouts without installing the
    platform-specific SDK runtime wheel.
    - Show `fmt-check` help text in `just -l` and simplify CI to call the
    shared driver through `just fmt-check`.
    - Pin the general CI workflow to `just@1.51.0` so its formatter agrees
    with the checked-in Justfile.
    - Add regression coverage for the thin Just recipes and the driver's
    formatter graph.
    
    ## Validation
    
    - `just fmt`
    - `just fmt-check`
    - `python3 -m pytest
    sdk/python/tests/test_artifact_workflow_and_binaries.py -k 'root_fmt or
    root_format' -q`
    - `pnpm run format`
    - `git diff --check`
    - `just -l | rg -n '^    fmt|fmt-check'`
    - `uvx --from uv==0.7.22 uv run --frozen --project sdk/python --no-sync
    --with ruff ruff check --diff sdk/python`
  • [codex] Publish release symbol artifacts (#25649)
    ## Why
    
    Production Codex binaries are stripped for distribution, which leaves
    crashes and samples from released builds without the symbols needed for
    useful stack traces. Publish symbols as separate release assets so
    production artifacts stay small while released builds remain
    symbolicateable.
    
    ## What changed
    
    - Add `.github/scripts/archive-release-symbols-and-strip-binaries.sh` to
    package platform-native symbols into `codex-symbols-<artifact>.tar.gz`
    assets while stripping the corresponding Unix binaries before signing.
    - Build release binaries with full debug information before producing
    distribution artifacts.
    - Publish macOS `.dSYM` bundles, Linux `.debug` files with
    `.gnu_debuglink`, and Windows `.pdb` files.
    - Strip Linux `bwrap` before computing its packaged-resource digest, but
    intentionally omit `bwrap` from symbol archives.
    - Preserve symbols artifacts in the unsigned macOS promotion flow.
    
    ## Verification
    
    - Ran `shellcheck` and `bash -n` on
    `.github/scripts/archive-release-symbols-and-strip-binaries.sh`.
    - Parsed the modified workflow YAML files and ran `git diff --check`.
    - Built a macOS release smoke binary and verified that the archived
    `.dSYM` contains DWARF application source information and has the same
    UUID as the stripped production binary.
    - Built Linux smoke binaries and verified that the symbol archive
    contains `codex.debug`, excludes `bwrap.debug`, leaves the expected
    `.gnu_debuglink` in `codex`, and does not mutate the separately stripped
    `bwrap` digest.
    - Staged a Windows smoke archive and verified that it contains the
    expected `.pdb` file.
  • Check root Python script formatting in CI (#25165)
    ## Why
    
    Python files under `scripts/` were not covered by the repository
    formatting recipe or the CI formatting job, so formatting drift could
    merge unnoticed.
    
    ## What
    
    - Add a dedicated `scripts/pyproject.toml` and `scripts/uv.lock` so
    root-script formatting uses a locked Ruff version.
    - Extend `just fmt` to format root Python scripts and add
    `fmt-scripts-check` for CI.
    - Run `just fmt-scripts-check` from `.github/workflows/ci.yml`,
    installing `uv` through SHA-pinned `astral-sh/setup-uv` while retaining
    the `uv` `0.11.3` pin.
    - Apply Ruff formatting to the root Python scripts, including
    `scripts/just-shell.py`, and extend
    `sdk/python/tests/test_artifact_workflow_and_binaries.py` to cover the
    root formatting recipe.
    - Update `AGENTS.md` so agents run `just fmt` after code changes
    anywhere in the repository.
    
    ## Validation
    
    - Extended the existing Python SDK workflow test to assert that `just
    fmt` includes root Python scripts.
  • [codex] Use git CLI for release Cargo fetches (#25644)
    ## Summary
    - Configure the rust-release build job with
    `CARGO_NET_GIT_FETCH_WITH_CLI=true`
    - Document the macOS SecureTransport/libgit2 failure mode that hit the
    `libwebrtc`/`libyuv` git submodule fetch
    
    ## Root cause
    The release run at
    https://github.com/openai/codex/actions/runs/26717498860/job/78745156683
    repeatedly failed before compilation because Cargo's libgit2 fetch path
    could not clone the nested `yuv-sys/libyuv` submodule from
    `chromium.googlesource.com`, ending with `SecureTransport error:
    connection closed via error`.
    
    ## Validation
    - `git diff --check`
    
    This is a workflow-only change, so I did not run Rust package tests.
  • Disable SQLite intrinsics for Windows x64 releases (#25490)
    ## Why
    
    Codex 0.135.0 started shipping bundled SQLite 3.51.x via SQLx 0.9.0 to
    avoid the older WAL corruption bug fixed by #24728. On Windows x64,
    #25367 reports an immediate `STATUS_ILLEGAL_INSTRUCTION` crash on a
    Haswell CPU when starting normal Codex paths.
    
    Rather than downgrading SQLite, this keeps the newer bundled SQLite
    source and removes SQLite compiler-intrinsic code paths from the Windows
    x64 release build.
    
    ## What changed
    
    For `x86_64-pc-windows-msvc` release builds, export
    `LIBSQLITE3_FLAGS=SQLITE_DISABLE_INTRINSIC` before `cargo build` in:
    
    - `.github/workflows/rust-release.yml`
    - `.github/workflows/rust-release-windows.yml`
    
    Other targets keep their current SQLite build flags.
    
    ## Verification
    
    - `git diff --check`
  • Add build_unsigned_archive release mode (#25435)
    ## Why
    We want a manual mode that produces the full packaged unsigned macOS
    Codex archive, including bundled resources like `rg`, without mixing
    those archives into the signing and publishing flow.
    
    The existing `build_unsigned` mode is the handoff used by external
    signing and `promote_signed`, so archive-only inspection and local
    packaging should live in a separate mode and artifact namespace.
    
    ## What Changed
    - added `build_unsigned_archive` as a new manual `release_mode`
    - kept the existing `build` matrix running for that mode instead of
    introducing a separate archive-only job
    - wrote unsigned macOS package archives to
    `codex-rs/unsigned-archive-dist/...` instead of the normal `dist/...`
    tree
    - uploaded those packaged macOS outputs as dedicated
    `*-unsigned-archive` workflow artifacts
    - kept `build_unsigned` and `promote_signed` on their existing raw
    unsigned binary path
    
    ## Validation
    - parsed `.github/workflows/rust-release.yml` with `ruby -e 'require
    "yaml"; YAML.load_file(".github/workflows/rust-release.yml")'`
    - ran `git diff --check -- .github/workflows/rust-release.yml`
    - reviewed the workflow diff to confirm `build_unsigned_archive` now
    reuses the existing `build` job while isolating the unsigned macOS
    package archives under dedicated artifact names
    - locally verified the package builder layout against unsigned macOS
    binaries to confirm the packaged archive contains `bin/codex`,
    `codex-path/rg`, and `codex-resources/zsh/bin/zsh`
  • ci: use issue triage environment for issue workflows (#25134)
    ## Summary
    
    This adds `environment: issue-triage` to the Codex-calling issue
    workflow jobs so they can read the GitHub Environment Secret while
    staying on GitHub-hosted runners for public issue-triggered workflows.
  • Move Bazel Windows jobs onto codex-runners (#24952)
    The codex-windows runner group should be much faster than the default
    GHA runners. Since bazel jobs on windows are frequently the long pole
    for PRs checks, this will hopefully get people landing a bit faster.
  • Remove libubsan CI workaround (#24782)
    It seems that this was added to allow rustc to load proc macros that had
    been compiled with UBSan enabled, which zig does for debug and
    `ReleaseSafe` builds. When zig drives the link of the final binary it
    knows to include the ubsan runtime, but our zig-built artifacts are
    being linked into a binary whose linking rustc drives. This removes the
    libubsan workaround we have and replaces it with
    `-fno-sanitize=undefined` passed to zig.
    
    The new argument is passed at the end of zig's args so should take
    precedence over any earlier arguments from the script's caller.
  • Add app-server startup benchmark crate (#24651)
    ## Summary
    - Add a new `app-server-start-bench` crate to measure app-server startup
    performance
    - Wire the benchmark into the workspace and Bazel build so it can be run
    consistently
    - Update lockfiles and repo automation to account for the new package
  • [codex] Stage Python SDK beta versions from release tags (#24872)
    ## Summary
    - Treat `sdk/python` as a development template with source version
    `0.0.0-dev`, matching the existing Python runtime packaging pattern.
    - Have `python-v*` tags supply the published SDK beta version through
    the existing `stage-sdk --sdk-version` path.
    - Remove the workflow check requiring a source version bump for each
    beta release and remove its now-unused host Python setup step.
    - Keep the reviewed runtime dependency pin at
    `openai-codex-cli-bin==0.132.0`.
    - Remove beta-number-specific documentation so it does not need editing
    for each publish.
    
    ## Why
    The package staging script already writes the release version into the
    artifact. Requiring the checked-in SDK template version to match every
    tag adds release-only source churn without changing the package users
    receive.
    
    ## Validation
    - Not run locally; relying on online CI for this workflow and metadata
    change.
    
    ## Release
    After this PR lands, publish the next beta by pushing tag
    `python-v0.1.0b2` from merged `main`.
  • [codex] Prepare Python SDK beta documentation and package metadata (#24836)
    ## Why
    
    The initial public `openai-codex` beta should read and install like a
    normal published Python package before a release tag is created. This
    follows merged PR #24828, which establishes the independent SDK beta
    release plumbing and exact runtime dependency.
    
    ## What changed
    
    - Rewrote `sdk/python/README.md` as a compact PyPI-facing beta package
    page: published installation, one quickstart, short login examples,
    built-in help, and links to deeper guides.
    - Updated the getting-started guide, API reference, FAQ, and examples
    index to present the published beta consistently without repeating
    onboarding in the package landing page or reference page.
    - Made `pip install openai-codex` the primary install path while beta
    releases are the only published SDK releases, with `--pre` documented
    for opting into prereleases after a stable release exists.
    - Added curated `help()` / `pydoc` docstrings across the public API and
    generated public convenience methods through
    `scripts/update_sdk_artifacts.py`.
    - Declared the repository `Apache-2.0` license expression and
    Documentation URL in package metadata, without introducing a duplicated
    SDK-local license file.
    - Kept the source distribution focused on installable package material
    (`src/openai_codex`, `README.md`, and `pyproject.toml`); the repository
    docs and runnable examples remain linked from the PyPI README.
    - Built release artifacts in an Alpine container on the Ubuntu runner,
    matching Python SDK CI and allowing type generation to install the
    published `musllinux` runtime wheel.
    - Added `twine check --strict` to the release workflow so malformed PyPI
    metadata or rendered README content fails before publishing.
    - Added focused SDK assertions for beta metadata, the exact runtime pin,
    source distribution contents, and the built-in Python documentation
    surface.
    
    ## Validation
    
    - Ran `uv run --frozen --extra dev ruff check
    scripts/update_sdk_artifacts.py src/openai_codex
    tests/test_public_api_signatures.py
    tests/test_artifact_workflow_and_binaries.py` before the final
    README-only reductions and review-fix follow-ups.
    - Built `openai_codex-0.1.0b1-py3-none-any.whl` and
    `openai_codex-0.1.0b1.tar.gz` before the final README-only reductions
    and review-fix follow-ups.
    - Ran `python -m twine check --strict` on both built artifacts before
    the final README-only reductions and review-fix follow-ups.
    - Verified artifact metadata reports `Apache-2.0` without a duplicated
    SDK-local license file.
    - Verified `inspect.getdoc(...)` resolves documentation for the package,
    `Codex`, `CodexConfig`, and key generated thread methods.
    - Rebased the documentation/readiness change onto merged PR #24828
    without changing the intended SDK or workflow file contents.
    - Final verification is delegated to online CI for this PR.
  • [codex] Add independent beta release for the Python SDK (#24828)
    ## Why
    
    `openai-codex` needs a beta release lifecycle without requiring beta
    releases of its pinned runtime package. Previously, SDK staging rewrote
    its runtime dependency to the SDK version, which made an SDK-only beta
    impossible.
    
    ## What changed
    
    - Set the initial SDK beta version to `0.1.0b1` and pin it to published
    stable `openai-codex-cli-bin==0.132.0`.
    - Decoupled SDK release staging from runtime versioning so it preserves
    the reviewed exact runtime pin.
    - Added a `python-v*` tag workflow that builds and publishes only
    `openai-codex` through PyPI trusted publishing.
    - Removed the Beta classifier from runtime package metadata for future
    runtime publications.
    - Regenerated protocol-derived SDK models from the selected stable
    runtime package.
    
    `0.132.0` is the newest stable runtime admitted by the checked-in
    dependency date fence and retains the Linux wheel family currently used
    by SDK CI.
    
    ## Release setup
    
    Before pushing `python-v0.1.0b1`, configure PyPI trusted publishing for
    the `openai-codex` project with workflow `python-sdk-release.yml`,
    environment `pypi`, and job `publish-python-sdk`.
    
    ## Validation
    
    - `uv run --frozen --extra dev ruff check src/openai_codex scripts
    examples tests`
    - Parsed `.github/workflows/python-sdk-release.yml` with PyYAML.
    - Built staged release artifacts locally:
    `openai_codex-0.1.0b1-py3-none-any.whl` and
    `openai_codex-0.1.0b1.tar.gz`.
    - Verified wheel metadata pins `openai-codex-cli-bin==0.132.0`.
    - Tests are deferred to online CI for this PR.
  • make vercel webhook url an env secret (#24778)
    move `DEV_WEBSITE_VERCEL_DEPLOY_HOOK_URL` to a repo environment secret.
    
    to keep scope of use of that env secret small, move the vercel website
    redeploy to its own post-release job.
  • Uprev Rust toolchain pins to 1.95.0 (#24684)
    ## Summary
    - Bump the workspace Rust toolchain from `1.93.0` to `1.95.0` across
    Cargo, Bazel, CI, release workflows, devcontainers, and the Codex
    environment config.
    - Refresh `MODULE.bazel.lock` so the Bazel Rust toolchain artifacts
    match the new version.
    - Leave purpose-specific toolchains unchanged, including the
    `argument-comment-lint` nightly and the upstream `rusty_v8` `1.91.0`
    build pin.
    - Includes fixes for new lints from `just fix` and a few codex-authored
    fixes for lints without a suggestion.
  • release: build macOS x64 zsh artifact (#24165)
    ## Why
    
    The zsh release workflow currently publishes macOS arm64 and Linux zsh
    fork artifacts, but no macOS x64 artifact. The Codex package builder
    therefore cannot include codex-resources/zsh/bin/zsh for
    x86_64-apple-darwin packages.
    
    ## What Changed
    
    - Added an x86_64-apple-darwin row to the macOS zsh release matrix.
    - Runs that row on macos-15-large, the Intel macOS runner appropriate
    for the native zsh build.
    - Added the matching macos-x86_64 platform to the zsh DotSlash publish
    config so the generated release manifest can reference the new tarball.
  • [codex] Add image re-encoding benchmarks (#23935)
    ## Summary
    - add Divan benchmarks for prompt image re-encoding paths
    - wire the image benchmark smoke test into Rust CI workflows
    
    ## Why
    Image prompt handling includes re-encoding work that benefits from
    repeatable benchmark coverage so changes can be measured in CI and
    locally.
    
    This already helped identify a potential regression from changing compiler flags.
    
    ## Impact
    Developers can run and compare the new image re-encoding benchmarks, and
    CI exercises the benchmark target via the Rust benchmark smoke test.
  • ci: Use codex produced v8 artifacts for release builds (#23934)
    Updates our build script to pull down the artifacts like we do in CI for
    building v8 into our targets.
    
    This changes the flow so that we now pre-install rusty v8 assets for all
    of our release targets from pre-built in workflow.
    Secondarily if running it locally we now optionally pull the assets down
    on python run assuming the user hasn't set the proper values, it then
    provides them.
    
    Sorry for the miss here.
  • npm: remove legacy package artifact synthesis (#23836)
    ## Why
    
    `rust-release` now publishes `codex-package-<target>.tar.gz` as the
    canonical native package payload. npm staging should consume those
    archives directly instead of keeping legacy synthesis code that fetched
    `rg`, copied standalone binaries, and rebuilt an approximate package
    layout.
    
    That also means the package builder should not know the internal shape
    of `codex-package`. It should extract and copy the target payload
    wholesale so future layout changes stay localized to the archive
    producer.
    
    The release job stages `codex`, `codex-responses-api-proxy`, and
    `codex-sdk` together, so native artifact download should be filtered,
    observable, and shared across component installs. Since that native
    hydration is now only used by release staging, keeping a separate
    `install_native_deps.py` CLI adds an extra wrapper without a real
    caller.
    
    ## What Changed
    
    - Removed legacy `codex-package` synthesis and related compatibility
    flags from npm staging.
    - Folded the remaining native artifact hydration code into
    `scripts/stage_npm_packages.py` and deleted
    `codex-cli/scripts/install_native_deps.py`.
    - Made platform package staging copy the full extracted target directory
    instead of enumerating package entries.
    - Kept non-`codex-package` native components under their component
    directory name instead of using a legacy destination map.
    - Split native staging by component set while sharing one
    workflow-artifact cache across the invocation.
    - Changed workflow artifact download to select target artifacts by name,
    print sizes/progress, and reuse cached artifacts.
    - Removed the implicit `CI=true` default from `build_npm_package.py`;
    local CI-shaped runs should set that environment explicitly.
    - Kept `npm pack` cache/log output in its temporary directory so packing
    does not write to the user npm cache.
    
    ## Verification
    
    - `python3 -m py_compile scripts/stage_npm_packages.py
    codex-cli/scripts/build_npm_package.py`
    - `python3 -m unittest discover -s scripts/codex_package -p "test_*.py"`
    - `scripts/stage_npm_packages.py --help`
    - `codex-cli/scripts/build_npm_package.py --help`
    - Ran the release-shaped staging command from `rust-release.yml` against
    workflow run https://github.com/openai/codex/actions/runs/26240748758
    with `CI=true` set locally to match GitHub Actions:
    
    ```sh
    CI=true python3 ./scripts/stage_npm_packages.py \
      --release-version 0.133.0 \
      --workflow-url https://github.com/openai/codex/actions/runs/26240748758 \
      --package codex \
      --package codex-responses-api-proxy \
      --package codex-sdk
    ```
    
    That completed successfully, downloaded only the six target artifacts
    once, reused the cache for `codex-responses-api-proxy`, and produced all
    nine npm tarballs. Generated tarballs and staging/artifact temp dirs
    were cleaned afterward.
  • sdk: launch packaged Codex runtimes (#23786)
    ## Why
    
    The Python and TypeScript SDKs launch the native Codex runtime directly,
    so they need to consume the same package artifact shape that release
    jobs now produce. The runtime wheel should be built from the canonical
    Codex package archive rather than reconstructing a parallel layout from
    loose binaries.
    
    ## What Changed
    
    - Stage `openai-codex-cli-bin` by extracting
    `codex-package-<target>.tar.gz` into `src/codex_cli_bin` and validating
    the expected package layout.
    - Update release workflows to pass the generated package archive into
    `stage-runtime` instead of the temporary package directory.
    - Update Python runtime setup to download `codex-package-*.tar.gz`
    release assets directly.
    - Expose Python runtime helpers for the bundled package directory and
    `codex-path`, and prepend that path when `openai_codex` launches the
    installed runtime without duplicating Windows `Path`/`PATH` keys.
    - Teach the TypeScript SDK to resolve package-layout optional
    dependencies while keeping the existing npm fallback layout, and
    preserve the existing Windows path variable casing when prepending
    `codex-path`.
    
    ## Test Plan
    
    - `python3 -m py_compile sdk/python/scripts/update_sdk_artifacts.py
    sdk/python/_runtime_setup.py sdk/python/src/openai_codex/client.py
    sdk/python-runtime/src/codex_cli_bin/__init__.py`
    - `uv run --frozen --project sdk/python --extra dev ruff check
    sdk/python/scripts/update_sdk_artifacts.py sdk/python/_runtime_setup.py
    sdk/python/src/openai_codex/client.py
    sdk/python/tests/test_artifact_workflow_and_binaries.py
    sdk/python-runtime/src/codex_cli_bin/__init__.py`
    - `uv run --frozen --project sdk/python --extra dev pytest
    sdk/python/tests/test_artifact_workflow_and_binaries.py`
    - `pnpm eslint src/exec.ts tests/exec.test.ts`
    - `pnpm test --runInBand tests/exec.test.ts`
  • ci: run Codex package builder tests (#23760)
    ## Why
    
    #23752 and #23759 add Python unit tests for the Codex package builder,
    but the root CI workflow did not run tests under
    `scripts/codex_package`. That left the `zstd` resolution and
    prebuilt-resource packaging behavior covered locally without a CI check.
    
    ## What changed
    
    - Add a root CI step in `.github/workflows/ci.yml` that runs `python3 -m
    unittest discover -s scripts/codex_package -p "test_*.py"`.
    - Keep the step with the existing Python verification checks before
    Node/pnpm setup.
    
    ## Verification
    
    - `python3 -m unittest discover -s scripts/codex_package -p "test_*.py"`
    - `python3 -m py_compile scripts/codex_package/*.py`
  • release: package prebuilt resource binaries (#23759)
    ## Why
    
    Release packaging should be a staging step once release binaries have
    already been built and signed. The Windows release job was downloading
    and signing `codex-command-runner.exe` and
    `codex-windows-sandbox-setup.exe`, but `scripts/build_codex_package.py`
    still rebuilt those helpers while creating the package archives.
    
    That makes the package step slower and, more importantly, risks putting
    helper binaries in the archive that were produced after the signing
    step. Linux had the same shape for package resources: `bwrap` could be
    rebuilt by the package builder instead of being passed in as a prebuilt
    release artifact.
    
    This builds on #23752, which fixes `.tar.zst` creation when Windows
    runners rely on the repository DotSlash `zstd` wrapper.
    
    ## What changed
    
    - Add explicit prebuilt resource inputs to the Codex package builder:
      - `--bwrap-bin`
      - `--codex-command-runner-bin`
      - `--codex-windows-sandbox-setup-bin`
    - Make `.github/scripts/build-codex-package-archive.sh` pass resource
    binaries from the release output directory when they are already
    present.
    - Build Linux `bwrap` for app-server release jobs too, so app-server
    package creation does not invoke Cargo just to supply the package
    resource.
    - Keep macOS package creation as a no-Cargo path when `--entrypoint-bin`
    is provided, since macOS packages have no resource binaries.
    - Add unit coverage showing prebuilt macOS, Linux, and Windows package
    inputs result in no source-built binaries.
    
    ## Verification
    
    - `python3 -m unittest discover -s scripts/codex_package -p 'test_*.py'`
    - `python3 -m py_compile scripts/codex_package/*.py`
    - `bash -n .github/scripts/build-codex-package-archive.sh`
    - Dry-ran Linux and Windows package builds with fake prebuilt resources
    and a nonexistent Cargo path to verify the package builder did not
    invoke Cargo.
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23759).
    * #23760
    * __->__ #23759
  • chore: use Codex Linux runners for Rust releases (#23761)
    ## Why
    
    Linux release jobs build the MUSL artifacts that ship in Codex releases,
    including both the primary CLI bundle and the app-server bundle. Those
    builds should run on the Codex Linux runner pools instead of generic
    Ubuntu-hosted runners so release builds use the x64 and arm64 capacity
    intended for Codex artifacts.
    
    ## What Changed
    
    - Moves the `x86_64-unknown-linux-musl` release matrix entries in
    `.github/workflows/rust-release.yml` from `ubuntu-24.04` to
    `codex-linux-x64-xl`.
    - Moves the `aarch64-unknown-linux-musl` release matrix entries from
    `ubuntu-24.04-arm` to `codex-linux-arm64`.
    - Leaves macOS release jobs, target triples, bundle names, and artifact
    names unchanged.
    
    ## Verification
    
    - Reviewed the workflow matrix diff for
    `.github/workflows/rust-release.yml`.
    - Not run locally; this is a GitHub Actions runner configuration change.
  • dotslash: publish Codex entrypoints from package archives (#23638)
    ## Summary
    
    DotSlash should resolve the same canonical package archives used by
    standalone installers and npm platform packages, rather than continuing
    to point at single-binary zstd artifacts or the older Linux bundle
    archive.
    
    This updates the Codex CLI and `codex-app-server` DotSlash release
    config entries to match `codex-package-<target>.tar.gz` and
    `codex-app-server-package-<target>.tar.gz`, with paths that select
    `bin/codex` or `bin/codex-app-server` inside the extracted package. The
    other helper outputs stay on their existing per-binary artifacts for
    now.
    
    ## Test plan
    
    - `python3 -m json.tool .github/dotslash-config.json > /dev/null`
    - Ran a Python regex smoke test that checked every updated `codex` and
    `codex-app-server` platform entry against the archive names emitted by
    `.github/scripts/build-codex-package-archive.sh`.
  • npm: ship platform packages in Codex package layout (#23637)
    ## Summary
    
    The npm platform packages should stop carrying a bespoke native layout
    now that the release workflow builds canonical Codex package archives.
    Keeping npm on the same `bin/`, `codex-resources/`, and `codex-path/`
    structure lets the Rust package-layout detection behave consistently
    across standalone, npm, and future DotSlash installs.
    
    This changes platform npm packages to stage the `codex-package` artifact
    for each target under `vendor/<target>`. The Node launcher now resolves
    `bin/codex` and prepends `codex-path`, while retaining legacy
    `vendor/<target>/codex` and `vendor/<target>/path` fallback support for
    local development and migration. The npm staging helper downloads
    `codex-package` archives instead of rebuilding the CLI payload from
    individual `codex`, `rg`, `bwrap`, and sandbox helper artifacts.
    
    CI still needs to stage npm packages from historical rust-release
    workflow artifacts that predate package archives, so the staging scripts
    expose an explicit `--allow-legacy-codex-package` fallback. That
    fallback synthesizes the canonical package layout from legacy per-binary
    artifacts and is wired only into the CI smoke path; release staging
    remains strict and continues to require real package archives.
    
    For direct local use, `install_native_deps.py` now points its built-in
    default workflow at the same recent artifact run used by CI and
    automatically enables legacy package synthesis only when
    `--workflow-url` is omitted. Explicit workflow URLs remain strict unless
    callers opt in with `--allow-legacy-codex-package`.
    
    ## Test plan
    
    - `python3 -m py_compile codex-cli/scripts/build_npm_package.py
    codex-cli/scripts/install_native_deps.py scripts/stage_npm_packages.py
    scripts/codex_package/cli.py`
    - `node --check codex-cli/bin/codex.js`
    - `ruby -e 'require "yaml";
    YAML.load_file(".github/workflows/rust-release.yml");
    YAML.load_file(".github/workflows/ci.yml"); puts "ok"'`
    - Staged a synthetic `codex-linux-x64` platform package from a canonical
    vendor tree and verified it copied only `bin/`, `codex-path/`,
    `codex-resources/`, and `codex-package.json`.
    - Imported `install_native_deps.py` and extracted a synthetic
    `codex-package-x86_64-unknown-linux-musl.tar.gz` into `vendor/<target>`.
    - Ran legacy-layout conversion smokes for Linux, Windows, and unsigned
    macOS artifact naming.
    - Ran a synthetic `install_native_deps.py` default-workflow smoke that
    verifies legacy package synthesis is automatic only when
    `--workflow-url` is omitted.
    - `NPM_CONFIG_CACHE="$tmp_dir/npm-cache" python3
    ./scripts/stage_npm_packages.py --release-version 0.125.0 --workflow-url
    https://github.com/openai/codex/actions/runs/26131514935 --package codex
    --allow-legacy-codex-package --output-dir "$tmp_dir"`
    - `node codex-cli/bin/codex.js --version`
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23637).
    * #23638
    * __->__ #23637
  • release: publish Codex package archive checksums (#23635)
    ## Summary
    
    Standalone installers and other downstream package consumers need a
    stable checksum source for the canonical package archives. Relying on
    per-asset metadata makes that harder to consume uniformly, especially
    when several package archives are produced in the same release.
    
    This keeps the `codex-package-*.tar.gz` and
    `codex-app-server-package-*.tar.gz` assets in the GitHub Release upload
    set and adds `codex-package_SHA256SUMS` to `dist/` before the release is
    created. The manifest contains one SHA-256 line per package archive and
    fails the release job if no package archives are present.
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23635).
    * #23638
    * #23637
    * #23636
    * __->__ #23635
  • ci: build Codex package archives in release workflow (#23582)
    ## Why
    
    Release CI already builds the Codex entrypoints before staging
    artifacts, and the package builder can now package those prebuilt
    binaries directly. The workflow should produce package-shaped sidecar
    archives from the same staged entrypoints that downstream distribution
    channels will eventually consume, without rebuilding `codex` or
    `codex-app-server` inside the packaging step.
    
    This intentionally does **not** publish the new package archives as
    GitHub Release assets yet. The archives are kept with workflow artifacts
    until npm, Homebrew, `install.sh`, winget, and related consumers are
    ready to switch over.
    
    ## What changed
    
    - Adds a `Build Codex package archive` step to
    `.github/workflows/rust-release.yml` after target artifacts are staged.
    - Runs `scripts/build_codex_package.py` for both release bundles:
    - `primary` builds `codex-package-${TARGET}.tar.gz` with `--variant
    codex`.
    - `app-server` builds `codex-app-server-package-${TARGET}.tar.gz` with
    `--variant codex-app-server`.
    - Passes `--entrypoint-bin target/${TARGET}/release/<entrypoint>` so
    packages contain the entrypoint already built by the workflow.
    - Deletes both package archive names before the final GitHub Release
    upload so they remain workflow artifacts only for now.
    
    ## Verification
    
    - Parsed `.github/workflows/rust-release.yml` with Ruby's YAML loader.
    
    
    
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23582).
    * #23596
    * __->__ #23582
  • Fan out rust-ci-full nextest by platform (#23358)
    ## Why
    
    `rust-ci-full` was paying the full Cargo nextest build-and-run cost once
    per platform, with Windows ARM64 as the long pole. This change moves the
    heavy work into one reusable per-platform flow: build a nextest archive
    once, then replay it across four shards so the platform lane spends less
    time running tests serially. For Windows ARM64, the archive is
    cross-compiled on Windows x64 and replayed on native Windows ARM64
    shards so the slow ARM64 machine is used for execution rather than
    compilation.
    
    ## What changed
    
    - split the `rust-ci-full` nextest matrix into five explicit
    per-platform reusable-workflow calls
    - add `.github/workflows/rust-ci-full-nextest-platform.yml` to build one
    archive, upload timings/helpers, replay four nextest shards, upload
    per-shard JUnit, and roll the shard status back up per platform
    - add Windows CI helpers for Dev Drive setup and MSVC ARM64 linker
    environment export so the Windows ARM64 archive can be produced on
    Windows x64
    - keep the existing Cargo git CLI fetch hardening inside the reusable
    workflow, since caller workflow-level `env` does not flow through
    `workflow_call`
    - document the archive-backed shard shape in
    `.github/workflows/README.md`
    - raise the default nextest slow timeout to 30s so the sharded full-CI
    path does not treat every >15s test as stuck
    
    ## Verification
    
    - validated the archive/shard flow with live GitHub Actions runs on this
    PR branch
    - Windows ARM64 cross-compile latency on completed runs:
    - https://github.com/openai/codex/actions/runs/26118759651: `34m30s`
    lane e2e, `17m16s` archive build, `9m55s` shard phase
    - https://github.com/openai/codex/actions/runs/26120777976: `30m36s`
    lane e2e, `17m21s` archive build, `6m50s` shard phase
    - comparable pre-cross-compile sharded Windows ARM64 runs were `55m01s`,
    `50m21s`, and `46m42s`, so the completed cross-compile runs improved the
    lane by roughly `12m` to `24m` versus the prior range
    - latest corrected cross-compile run:
    https://github.com/openai/codex/actions/runs/26120777976
      - Windows ARM64 archive built successfully on Windows x64
    - native Windows ARM64 shards started immediately after the archive
    upload
    - 3/4 Windows ARM64 shards passed; the failing shard hit the same
    existing `code_mode` test failure seen outside this lane
    - downloaded failed-shard JUnit XML from the validation runs and
    confirmed the remaining red is from known test failures, not
    archive/shard wiring
    - no local Codex tests run per repo guidance
    
    ## Notes
    
    - this PR does not change developers.openai.com documentation
  • CI: Customize v8 building (#22086)
    ## Summary
    
    Move the rusty_v8 artifact production into hermetic Bazel path and bump
    the `v8` crate to `147.4.0`
    
    The new flow builds V8 release artifacts from source for Darwin and
    Linux targets, publishes both the current release-compatible artifacts
    and sandbox-enabled variants, and keeps Cargo consumers on prebuilt
    binaries by continuing to feed the `v8` crate the archive and generated
    binding files it already expects.
    
    ## Why
    
    We need control over V8 build-time features without giving up prebuilt
    artifacts for downstream Cargo builds.
    
    Upstream `rusty_v8` already supports source-only features such as
    `v8_enable_sandbox`, but its normal prebuilt release assets do not cover
    every feature combination we need. Building the artifacts ourselves lets
    us enable settings such as the V8 sandbox and pointer compression at
    artifact build time, then publish those outputs so ordinary Cargo builds
    can still consume prebuilts instead of compiling V8 locally.
    
    This keeps the fast consumer experience of prebuilt `rusty_v8` archives
    while giving us a reproducible path to ship featureful variants that
    upstream does not currently publish for us.
    
    ## Implementation Notes
    
    The Bazel graph in this PR is not copied wholesale from `rusty_v8`;
    `rusty_v8`'s normal source build is still GN/Ninja-based.
    
    Instead, this change starts from upstream V8's Bazel rules and adapts
    them to Codex's hermetic toolchains and dependency layout. Where we
    intentionally follow `rusty_v8`, we mirror its existing artifact
    contract:
    
    - the same `v8` crate version and generated binding expectations
    - the same sandbox feature relationship, where sandboxing requires
    pointer compression
    - the same custom libc++ model expected by Cargo's default
    `use_custom_libcxx` feature
    - the same release-style archive plus `src_binding` outputs consumed by
    the `v8` crate
    
    To preserve that contract, the Bazel release path pins the libc++,
    libc++abi, and llvm-libc revisions used by `rusty_v8 v147.4.0`, builds
    release artifacts with `--config=rusty-v8-upstream-libcxx`, and folds
    the matching runtime objects into the final static archive.
    
    ## Windows
    
    Windows is annoyingly handled differently.
    
    Codex's current hermetic Bazel Windows C++ platform is `windows-gnullvm`
    / `x86_64-w64-windows-gnu`, while upstream `rusty_v8` publishes Windows
    prebuilts for `*-pc-windows-msvc`. Those are different ABIs, so the
    Bazel graph cannot truthfully reproduce the upstream MSVC artifacts
    until we add a real MSVC-targeting C++ toolchain.
    
    For now:
    
    - Windows MSVC consumers continue to use upstream `rusty_v8` release
    archives.
    - Windows GNU targets are built in-tree so they link against a matching
    GNU ABI.
    - The canary workflow separately exercises upstream `rusty_v8` source
    builds for MSVC sandbox artifacts, but MSVC is not yet part of the
    Bazel-produced release matrix.
    
    ## Validation
    This PR is technically self validating through CI. I have already
    published it as a release tag so the artifacts from this branch are
    published to
    https://github.com/openai/codex/releases/tag/rusty-v8-v147.4.0 CI for
    this PR should therefore consume our own release targets. I have also
    locally tested for linux and darwin.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Publish Linux runtime wheels with glibc-compatible tags (#21812)
    ## Why
    
    The Python SDK depends on `openai-codex-cli-bin` runtime wheels being
    installable on the Linux hosts our users actually run. The release
    workflow currently tags the Linux runtime artifacts as `musllinux_*`,
    which makes pip ignore them on normal glibc distributions even though
    the bundled Rust executables are intended to run there.
    
    ## What changed
    
    - Tag the Linux runtime wheels as `manylinux_2_17_aarch64` and
    `manylinux_2_17_x86_64` instead of `musllinux_1_1_*`.
    - Keep the existing runtime wheel build and publish flow unchanged
    otherwise.
    
    ## Verification
    
    - Confirmed the wheel-tag issue against the PyPA platform-tag rules for
    `manylinux` vs `musllinux`.
    - This PR is now intentionally scoped to the tag correction only; the
    broader Python runtime release workflow has already landed on `main`
    through the merged stack.
    
    ## Follow-up
    
    After publishing the next alpha from this branch, install the
    SDK/runtime in a fresh glibc Linux environment and confirm pip resolves
    the tagged Linux wheel as expected.
    
    Co-authored-by: Codex <noreply@openai.com>
  • Reduce rust-ci-full Windows nextest timeout flakes (#23253)
    ## Why
    Recent `rust-ci-full` failures were dominated by transient Windows
    timeout clusters in process-heavy tests such as `suite::resume`,
    `suite::cli_stream`, `suite::auth_env`,
    `start_thread_uses_all_default_environments_from_codex_home`, and
    `connect_stdio_command_initializes_json_rpc_client_on_windows`.
    
    The goal here is to make those known flaky paths less likely to fail
    full CI without relaxing the global nextest timeout policy.
    
    ## What changed
    - Enable one global nextest retry with `retries = 1` so a single
    transient failure can recover.
    - Add a `windows_process_heavy` test group with `max-threads = 2` for
    the recurring Windows subprocess/session-heavy timeout families.
    - Add Windows-only slow-timeout overrides for that process-heavy group.
    - Add a narrower Windows-only timeout override for
    `start_thread_uses_all_default_environments_from_codex_home`, which
    still exceeded the broader Windows bucket in both Windows full-CI lanes.
    - Increase the `rust-ci-full` nextest job timeout from `45m` to `60m` so
    Windows ARM64 still has job-level headroom after retries and targeted
    per-test timeout increases.
    - Keep the global `slow-timeout` unchanged at `15s`.
    
    ## Validation
    Validated through `rust-ci-full` GitHub Actions reruns on this PR.
    
    Observed improvement on the tuned Windows lanes:
    - Windows x64 went from `5 timed out` to `0 timed out`.
    - Windows ARM64 went from `2 timed out` to `0 timed out`.
    - `start_thread_uses_all_default_environments_from_codex_home` recovered
    as a flaky pass on Windows ARM64 instead of timing out.
    
    The remaining failing tests in those runs were unrelated hard failures
    outside this nextest timeout tuning.
  • Upload rust full CI JUnit reports (#23273)
    ## Why
    
    `rust-ci-full` failures currently leave downstream investigation
    reconstructing basic test facts from raw logs. `cargo nextest` can emit
    standard JUnit XML for each lane, which gives us a small structured
    artifact for post-run failure analysis without changing the test
    execution model.
    
    ## What changed
    
    - enable nextest JUnit output in `codex-rs/.config/nextest.toml`
    - upload the lane-scoped JUnit XML artifact from each `rust-ci-full`
    test lane
    
    ## Verification
    
    - `rust-ci-full` run `26018931531` on head
    `52d77c60e79b36859d944ef28a36b014055c5c48` produced JUnit artifacts for
    macOS, Linux x64 remote, Windows x64, and Windows ARM64 test lanes
    - `rust-ci-full` run `26021241006` on the same head produced the missing
    Linux ARM JUnit artifact after the first run lost that runner before
    export
    - downloaded all five lane JUnit artifacts and verified each contains
    non-empty test counters and failure data
  • Disable DMG staging for signed macOS promotion (#22900)
    ## Why
    `promote_signed` is now used to finish a release from an externally
    signed macOS handoff, but this release path (temporarily) no longer
    distributes DMGs. Keeping DMG staging enabled made the handoff
    unnecessarily require DMG assets and notarization/stapling validation
    even though the promoted release only needs the signed macOS binaries.
    
    ## What changed
    - Set every `stage-signed-macos` matrix entry to `build_dmg: "false"`,
    including the primary macOS bundles.
    - Kept the existing DMG staging branch in place behind
    `matrix.build_dmg` so it can be re-enabled deliberately later.
    - Updated the workflow header comment so the signed handoff contract
    asks for signed binaries, not signed DMGs.
    
    The regular signed build path that creates, signs, notarizes, and stages
    DMGs is unchanged; this only affects the `promote_signed` handoff path.
  • Fix signed macOS release promotion follow-up jobs (#22788)
    ## Why
    
    The `release_mode=promote_signed` path intentionally skips the build
    jobs after signed macOS artifacts are staged, then runs the `release`
    job from the signed handoff. In the `rust-v0.131.0-alpha.19` promotion
    run, `release` succeeded but the npm, PyPI, and `latest-alpha-cli`
    follow-up jobs were skipped because their custom job `if:` expressions
    let GitHub Actions apply the implicit `success()` status check before
    reading `needs.release.outputs.*`.
    
    The unsigned build handoff does not need DotSlash manifests. Publishing
    unsigned DotSlash manifests creates release assets that can conflict
    with the later signed promotion, especially shared outputs such as
    `bwrap`, `codex-command-runner`, and `codex-windows-sandbox-setup`.
    
    ## What Changed
    
    - Stop publishing DotSlash manifests when `SIGN_MACOS == 'false'`.
    - Delete `.github/dotslash-unsigned-config.json`.
    - Gate post-release jobs with the `!cancelled()` status function plus an
    explicit `needs.release.result == 'success'` check before consulting
    release outputs.
    - Keep the existing publish eligibility rules for npm, PyPI, WinGet, and
    `latest-alpha-cli`.
    
    ## Verification
    
    - `rg -n "dotslash-unsigned-config|SIGN_MACOS ==
    'false'.*dotslash|unsigned-config" .github/workflows/rust-release.yml
    .github || true`
    - `git diff --check -- .github/workflows/rust-release.yml
    .github/dotslash-unsigned-config.json`
  • ci: support signed macOS release promotion (#22737)
    ## Why
    
    `rust-release.yml` can create unsigned macOS artifacts for external
    signing, but there was no signed resume path after those artifacts
    returned from a secure enclave. Release operators need a way to reuse
    the first run artifacts, ingest signed macOS binaries and DMGs, and
    continue the normal signed release path without rebuilding every
    platform or treating handoff assets as final release assets.
    
    ## How this is meant to be used
    
    First, start the release as an unsigned macOS build against the release
    tag:
    
    ```shell
    gh workflow run rust-release.yml \
      --repo openai/codex \
      --ref rust-vX.Y.Z \
      -f release_mode=build_unsigned
    ```
    
    That run builds the normal Linux/Windows artifacts and publishes
    unsigned macOS handoff artifacts. The unsigned macOS binaries are then
    copied to the secure enclave, signed and notarized there, packaged as a
    signed handoff archive, and uploaded back to the GitHub Release for the
    same tag.
    
    The signed handoff asset should contain either target directories such
    as `aarch64-apple-darwin/` and `x86_64-apple-darwin/`, or artifact
    directories such as `aarch64-apple-darwin-app-server/`. The promote
    workflow accepts either layout. The directories should contain the
    signed binaries and, for primary macOS bundles, the signed and stapled
    DMGs.
    
    For example, after signing, upload the handoff asset to the release:
    
    ```shell
    gh release upload rust-vX.Y.Z \
      signed-macos-rust-vX.Y.Z.tar.zst \
      --repo openai/codex \
      --clobber
    ```
    
    Then start the promotion run. `unsigned_run_id` is the workflow run id
    from the first `build_unsigned` run, and `signed_macos_asset` is the
    exact Release asset name uploaded by the secure enclave:
    
    ```shell
    gh workflow run rust-release.yml \
      --repo openai/codex \
      --ref rust-vX.Y.Z \
      -f release_mode=promote_signed \
      -f unsigned_run_id=1234567890 \
      -f signed_macos_asset=signed-macos-rust-vX.Y.Z.tar.zst \
      -f signed_macos_sha256=<sha256>
    ```
    
    The `signed_macos_sha256` input is optional, but when provided the
    promotion run verifies the handoff archive before unpacking it. The
    promotion run also validates that `unsigned_run_id` points to a
    successful manual `rust-release` run for the same tag and commit before
    importing artifacts.
    
    ## What Changed
    
    - Add explicit manual `release_mode` values for `build_unsigned` and
    `promote_signed` while keeping `sign_macos` as a deprecated
    compatibility input.
    - Add promote inputs for `unsigned_run_id`, `signed_macos_asset`, and
    optional `signed_macos_sha256`.
    - Add a `stage-signed-macos` job that downloads the signed handoff asset
    from the GitHub Release, verifies signed binaries and stapled DMGs,
    repacks normal macOS release artifacts, and builds macOS Python runtime
    wheels.
    - Teach the release job to download Part 1 artifacts from the unsigned
    run, discard unsigned macOS staging artifacts, re-upload promoted Linux
    and Windows artifacts for npm staging, and then run the signed release
    tail.
    - Validate that `unsigned_run_id` points to a successful manual
    `rust-release` run for the same tag and commit before importing
    artifacts.
    - Limit unsigned macOS artifact upload to the unsigned build path so
    normal signed releases do not publish unsigned handoff binaries.
    - Clean up unsigned and signed handoff release assets after successful
    promotion.
    
    ## Verification
    
    - Parsed `.github/workflows/rust-release.yml` with Ruby YAML loading.
    
    No developers.openai.com documentation update is needed.
  • make rust-release-prepare use env secret (#22702)
    made a `rust-release-prepare` environment with the necessary API key as
    an environment secret. use this in the workflow rather than the action
    secret.
    
    once this merges and i confirm it works as intended, ill rm the action
    secret.
  • Chore: better published unsigned artifacts (#22649)
    This is the exact same change as @bolinfest made but he could not push
    because of github action change permission.
    
    ## Why
    
    The `rust-release` workflow can now be run manually with
    `sign_macos=false` to skip macOS signing, but that path previously
    stopped before creating a GitHub Release. That left the unsigned macOS
    binaries available only as workflow-run artifacts, which are awkward to
    fetch from automation and cannot be retrieved with a simple
    unauthenticated `curl`.
    
    For the unsigned path we still should not perform the normal release
    side effects: no npm or Python publishing, no WinGet publishing, no
    `latest-alpha-cli` branch update, and no promotion to GitHub's latest
    release. The goal is only to make the build outputs easy to fetch from
    the release page.
    
    ## What changed
    
    - Allow the `release` job in `.github/workflows/rust-release.yml` to run
    for `workflow_dispatch` runs with `sign_macos=false`.
    - For unsigned runs, keep the unsigned macOS artifacts plus the normal
    Linux and Windows release artifacts needed for DotSlash, then
    create/update the GitHub Release with `make_latest: false`.
    - Keep the normal publish/promote paths gated to signed releases:
      - npm staging and publish
      - Python runtime publish
      - WinGet publish
      - `latest-alpha-cli` update
      - developer-site deploy
      - normal DotSlash release files
    - Add `.github/dotslash-unsigned-config.json`, which publishes
    `*-unsigned` DotSlash files that use unsigned macOS artifacts and the
    normal Linux/Windows artifacts.
    
    
    ## What I added
    PLEASE READ THIS!!!
    I added `codex-command-runner` and `codex-windows-sandbox-setup` entries
    to `.github/dotslash-unsigned-config.json` so that with
    `sign_macos=false` we would still get the dotslash files for those
    artifacts which are necessary for windows builds.