Commit Graph

496 Commits

  • [codex] package Windows symbols in parallel (#27856)
    In the x64 packaging job from
    
    https://github.com/openai/codex/actions/runs/27391514823
    
    archiving and uploading PDBs took 65 seconds after signing. Release
    packaging could not start until that work completed.
    
    Windows code signing changes executables but not their PDBs. Package
    the PDBs in a sibling Ubuntu job as soon as all binary artifacts are
    available. Signing and release packaging can then proceed without
    waiting for the symbols archive, reducing the critical path by about
    one minute.
  • [codex] parallelize Windows compression (#27855)
    Each Windows packaging job creates three compressed forms of five
    binaries in sequence. This takes roughly two minutes and is on the
    release critical path.
    
    Use two xargs workers to compress independent binaries concurrently.
    The workers only read the raw executables and write per-binary archive
    names. The Codex zip can safely read the helper executables while their
    own archives are generated.
    
    On a 16-vCPU AMD EPYC 9V74 Windows x64 release runner, alternating
    trials against artifacts from release run 27391514823 measured:
    
      serial:   121 s, 123 s, 121 s
      parallel:  73 s,  73 s,  74 s
    
    This saves 47 to 50 seconds in the x64 packaging lane, reducing the
    observed release critical path by about 48 seconds when x64 remains the
    limiting lane.
    
    https://github.com/openai/codex/actions/runs/27401905938
  • Use dependency groups for Python SDK tooling (#27538)
    ## Summary
    
    `just fmt` previously used `uv run --with ruff` to make Ruff available.
    Because `--with` creates an ephemeral overlay outside the project
    lockfile, uv periodically re-resolved Ruff (by default every 10 minutes)
    instead of using the version recorded in `uv.lock`.
    
    Move the Python SDK tooling dependencies from the published `dev` extra
    into `format`, `test`, and composed `dev` dependency groups. The
    formatter now selects only the locked `format` group, contributor and CI
    setup explicitly sync the `dev` group, and CI and release commands reuse
    that environment with `--frozen --no-sync`. The scripts formatter also
    uses its project's locked Ruff dependency instead of an ephemeral
    overlay.
    
    Validated the Python 3.12 SDK suite (119 passed, 38 skipped) and the
    repository formatter.
  • Translate non-English issues (#27778)
    Issues written in languages other than English, such as #26979, require
    manual translation before the development team can triage them.
    
    This adds an `Issue Translator` workflow that uses Codex when an issue
    is opened. For non-English reports, it replaces the title with an
    English translation, preserves the original body, and posts the
    translated body as an idempotent issue comment.
    
    The translation scripts were run manually against non-English issue
    content and produced the expected English title and comment output.
  • ci(v8): gate Windows source builds on relevant changes (#27715)
    Avoid rebuilding sandboxed Windows MSVC V8 artifacts for unrelated
    changes to `codex-rs/Cargo.toml`.
    
    The V8 canary now compares the resolved V8 version between the base and
    head commits and only runs the Windows source-build matrix when:
    
    - the resolved V8 crate version changes;
    - Windows artifact-production scripts or workflows change; or
    - the workflow is manually dispatched.
    
    The existing Bazel V8 matrix is unchanged.
    
    ## Why
    
    The Windows MSVC source builds take roughly two to three hours and
    currently run whenever any entry in the broad `v8-canary` path filter
    changes.
  • [codex] revert concurrent npm publishing (#27639)
    In https://github.com/openai/codex/actions/runs/27354608310, the
    concurrency introduced by
    
    https://github.com/openai/codex/commit/5e50e7e639c9284ceac24a5498b73a5602fb6615
    caused the npm publish job to fail.
    
    The six platform tarballs contain different versions of the same
    `@openai/codex` package. Every publish updates the same packument, so
    only two concurrent updates succeeded while four failed with HTTP 409.
    
    Serializing that group would leave only the responses API proxy running
    in parallel. Saving one publish does not justify the nested `xargs`
    machinery needed to express those groups.
    
    Restore the serial publish loop and document why the platform variants
    must not publish concurrently. Platform packages remain ahead of the
    root CLI wrapper, and the SDK remains after its exact root dependency.
  • [codex] download only release artifacts (#27529)
    In https://github.com/openai/codex/actions/runs/27308011621, the
    release job downloaded 10.0 GiB of workflow artifacts in 87 seconds,
    then discarded 42 artifacts accounting for 3.3 GiB.
    
    Select target and supplemental release artifact patterns at download
    time. This also excludes duplicate Cargo timing files without a cleanup
    pass and should reduce total release time by about 30 seconds.
  • [codex] publish DotSlash alongside npm (#27528)
    In https://github.com/openai/codex/actions/runs/27308011621,
    preparing and publishing the three DotSlash configurations took 72
    seconds after creating the GitHub release. npm publication could not
    start until those independent steps finished.
    
    Move DotSlash publication to a sibling job that starts after the GitHub
    release. npm and DotSlash can then proceed concurrently, reducing total
    release time by about one minute.
  • [codex] publish npm packages concurrently (#27527)
    In https://github.com/openai/codex/actions/runs/27308011621,
    publishing the npm tarballs serially took 147 seconds. Six platform
    packages and the responses API proxy are independent.
    
    Publish those packages concurrently, then publish the root CLI wrapper
    and SDK in dependency order. Individual platform publishes took 19 to
    23 seconds, so this should reduce total release time by nearly two
    minutes.
  • [codex] reuse release artifacts for npm staging (#27312)
    The release job already downloads every workflow artifact into `dist`,
    but npm staging creates a new cache and downloads the six target
    artifacts again.
    
    Reuse `dist` as the staging script's artifact cache while preserving the
    existing download fallback for missing artifacts and standalone callers.
    The script retains ownership of temporary caches but does not delete a
    caller-provided directory.
    
    In https://github.com/openai/codex/actions/runs/27242495616, the
    duplicate
    download transferred 3.3 GiB and took 4 minutes 13 seconds. This should
    reduce total release time by about 4 minutes.
  • [codex] link Windows releases with LLD (#27315)
    Windows x64 release builds spend about 36.5 of 48 minutes in final
    LLVM code generation and MSVC linking. Use the existing target-aware
    MSVC
    setup action to select LLD for release builds; the Windows ARM64 archive
    path already exercises the action and its LLD wrapper.
    
    In https://github.com/openai/codex/actions/runs/27242495616, macOS
    becomes
    the critical path after roughly four minutes of Windows improvement, so
    this is expected to reduce total workflow time by about four minutes.
  • Add typed file URIs (#26840)
    ## Why
    
    Codex needs stable `file:` URI identifiers that can cross process and
    operating-system boundaries without eagerly interpreting them as native
    paths. Existing fields also need to keep accepting absolute path strings
    during migration.
    
    ## What changed
    
    - Add `codex-utils-path-uri` with a validated, immutable `PathUri`
    wrapper that currently accepts only `file:` URLs.
    - Expose URI-level `basename`, `parent`, and `join` operations that
    preserve authorities and percent encoding without guessing the source
    operating system.
    - Keep native conversion explicit through `AbsolutePathBuf` and the
    current host rules.
    - Serialize as canonical URI text while accepting both URI text and
    legacy absolute native paths during deserialization.
    - Add adversarial coverage for Windows-looking and POSIX paths, UNC
    authorities, encoded metadata characters, non-UTF-8 POSIX paths, URI
    hierarchy operations, and legacy serde round trips.
  • ci: template custom runner names by repo (#27024)
    ## Why
    
    These workflows currently hard-code the `codex` runner group and custom
    runner labels. That makes the same workflow definitions less portable
    across repository copies or renamed repos, even though the runner fleet
    follows the repository name scheme. Template the runner identities from
    the repository name so `openai/codex` still resolves to the existing
    `codex-*` runners while other repos can use their own `<repo>-*` runner
    names.
    
    ## What Changed
    
    - Replaced custom runner `group` values such as `codex-runners` with
    `${{ github.event.repository.name }}-runners`.
    - Replaced custom runner labels such as `codex-linux-x64` and
    `codex-windows-arm64` with `${{ github.event.repository.name }}-...`.
    - Covered direct `runs-on` objects, matrix `runs_on` entries, reusable
    workflow runner inputs, and release runner labels.
    
    ## Verification
    
    - Parsed all `.github/workflows/*.yml` files as YAML with Ruby.
    - Searched `.github/workflows` to confirm no hardcoded runner-field
    `codex-runners` or `codex-*` labels remain.
  • [codex] Restore release symbol artifacts with line tables (#26202)
    ## Summary
    
    - Restore separate release symbol archives for macOS, Linux, and Windows
    binaries.
    - Build release binaries with `line-tables-only` debuginfo instead of
    full debuginfo.
    - Strip Unix distribution binaries after extracting symbols, preserve
    Windows PDBs, and keep symbol archives available to the release job.
    - Strip the packaged Linux `bwrap` binary before hashing it so the
    embedded digest matches the distributed bytes.
    
    ## Root cause
    
    The first symbol-artifact implementation enabled
    `CARGO_PROFILE_RELEASE_DEBUG=full`. In the June 2 release runs, macOS
    ARM primary builds reached the 90-minute timeout while still inside
    `Cargo build`. After the symbol changes were reverted, the same primary
    build completed in about 22 minutes. The archive step itself completed
    in tens of seconds when reached.
    
    Rust's `line-tables-only` debuginfo level preserves function names and
    source locations for symbolication without emitting the heavier variable
    and type information from full debuginfo.
    
    ## Validation
    
    - Ran `just fmt` from `codex-rs`.
    - Ran `just test-github-scripts` from the repository root: 23 tests
    passed.
    - Ran `bash -n` and `shellcheck` on
    `.github/scripts/archive-release-symbols-and-strip-binaries.sh`.
    - Parsed both modified workflows as YAML and ran `git diff --check`.
    - Built a macOS release smoke binary with `line-tables-only`, archived
    its dSYM through the restored script, stripped the production binary,
    and verified that `atos` resolves `symbol_smoke_function` to
    `main.rs:2`.
    - Ran Linux archive-script control-flow coverage with stubbed `objcopy`
    and `strip` commands.
    - Ran Windows PDB archive staging coverage and verified
    underscore-emitted Rust PDB names are staged under shipped hyphenated
    binary names.
    
    ## Follow-up
    
    The release workflow only runs for tags or manual dispatches, so CI
    cannot dry-run the full release matrix on this PR. The next release run
    will verify runner time and memory behavior under `line-tables-only`.
  • ci: use bazel environment for BuildBuddy secret (#26895)
    ## Why
    
    `BUILDBUDDY_API_KEY` now lives in the `bazel` GitHub Actions environment
    as an environment secret. Jobs that need BuildBuddy credentials must opt
    into that environment so `${{ secrets.BUILDBUDDY_API_KEY }}` resolves
    from the protected environment secret instead of relying on an unscoped
    repository/organization secret.
    
    This follows the same environment-secret migration pattern as #26466.
    
    ## What Changed
    
    - Attach each workflow job that reads `BUILDBUDDY_API_KEY` to the
    `bazel` environment.
    - Set `deployment: false` on those job-level environment blocks.
    
    `deployment: false` lets the job enter the `bazel` environment to access
    its environment secrets without creating GitHub deployment records for
    these CI jobs. That keeps the environment as a secret/access-control
    boundary without making ordinary Bazel CI runs look like deploys.
    
    ## Validation
    
    - Parsed the modified workflow YAML files with Ruby's YAML parser.
    - Checked the modified workflow files for trailing whitespace.
  • Clean up Rust release workflow (#26335)
    ## Why
    PR #26252 moved macOS release signing into the tag-triggered
    `rust-release` workflow through the protected `codesigning` environment
    and Azure Key Vault. That leaves the old manual unsigned-build /
    signed-promotion handoff as dead compatibility scaffolding: it makes the
    release DAG harder to reason about and keeps paths around that the
    current release process no longer intends to operate.
    
    ## What changed
    - Remove the manual `workflow_dispatch` inputs and validation for
    `build_unsigned`, `promote_signed`, and the deprecated `sign_macos`
    flag.
    - Drop the `stage-signed-macos` job and the promotion-specific artifact
    download, re-upload, pruning, and cleanup logic.
    - Make tag-pushed releases always follow the signed release path: build,
    sign, package, finalize, publish, and then run downstream release jobs
    from `release` success.
    - Remove stale `SIGN_MACOS` / `sign_macos` conditions and outputs,
    including downstream gates for npm, DotSlash, WinGet, dev website
    deploy, and `latest-alpha-cli` branch updates.
    
    ## Verification
    - `ruby -e 'require "yaml"; YAML.load_file(ARGV.fetch(0)); puts "yaml
    ok"' .github/workflows/rust-release.yml`
    - `git diff --check`
    - `rg -n
    "workflow_dispatch|inputs\\.|release_mode|build_unsigned|SIGN_MACOS|outputs\\.sign_macos|sign_macos\\b"
    .github/workflows/rust-release.yml` returned no matches
  • [codex] Keep Bazel startup options stable across commands (#26256)
    ## Why
    
    `just bazel-clippy` ran target discovery with
    `--noexperimental_remote_repo_contents_cache`, then ran the build with
    the workspace default `--experimental_remote_repo_contents_cache`. Bazel
    therefore killed and restarted its server on each transition, slowing
    repeated commands and discarding the in-memory analysis cache. An audit
    found the same class of startup-option variation in several CI command
    sequences.
    
    ## What changed
    
    - Keep local lint target-discovery queries on the workspace-default
    Bazel server, while making CI target discovery explicitly use the CI
    startup options.
    - Normalize GitHub Actions launches through the BuildBuddy wrapper to
    share `BAZEL_OUTPUT_USER_ROOT` and
    `--noexperimental_remote_repo_contents_cache`.
    - Route the CI lockfile check and Windows test-shard query through the
    same startup configuration.
    - Document the startup-option invariant and add wrapper regression
    coverage.
    
    ## Validation
    
    - Confirmed consecutive local clippy target-discovery runs retained the
    same Bazel server PID.
  • ci: test windows cross build (#25000)
    We cross build when using bazel for windows. This causes a couple
    hiccups in that v8 does a mksnapshot step that is expecting to snapshot
    on the host arch which wasn't matching when we were doing the
    crossbuild. This was causing segfault failiures when starting up
    codemode from a cross built artifact.
    
    This changes things such that we cross build the library and then run
    and link a snapshot on the host machine/arch which is windows. This
    gives us a functional snapshot and library that can start code-mode on
    windows.
    
    This fixes the build and then fixes two test regressions we had.
  • Use Winget release environment secret (#26466)
    ## Why
    `WINGET_PUBLISH_PAT` now lives as a GitHub environment secret under
    `mainline-release-winget`. The WinGet release job needs to enter that
    environment so `secrets.WINGET_PUBLISH_PAT` resolves during
    stable/mainline Rust releases.
    
    ## What Changed
    - Attach the `winget` job in `.github/workflows/rust-release.yml` to the
    `mainline-release-winget` environment.
    - Set `deployment: false` so the job can read environment secrets
    without creating GitHub deployment records.
    
    ## Operational Note
    The `mainline-release-winget` environment must allow `rust-v*.*.*` tag
    refs before this can run on release tags. The live environment currently
    has a custom policy named `rust-v*.*.*` with type `branch`; add the
    corresponding `tag` policy before relying on this path for a release.
    
    ## Validation
    - `git diff --check origin/main...HEAD --
    .github/workflows/rust-release.yml`
    - `ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts
    "yaml ok: #{f}" }' .github/workflows/rust-release.yml`
  • build: use ThinLTO for release binaries (#23710)
    ## Why
    
    Fat LTO makes release builds substantially slower without providing
    enough measured runtime benefit to justify the release CI long pole. The
    build-profile investigation found that keeping Cargo's default release
    `opt-level=3` and switching from fat LTO to ThinLTO (`3/thin/1`) reduced
    a clean `codex-cli` release build from 2073.893 seconds to 1243.172
    seconds, a 40.06% improvement.
    
    The resulting binary increased from 196.7 MiB to 211.8 MiB (+7.63%).
    Measured runtime changes were small: the worst image workload median was
    +0.86% and app-server startup was +0.31% relative to fat LTO. ThinLTO
    retains cross-crate optimization while avoiding most of the fat-LTO
    build cost.
    
    This deliberately avoids global size optimization: final-executable
    testing showed a substantial regression on the image request path, which
    is expected to become more important as image usage grows.
    
    ## What changed
    
    - Set the workspace release profile to `lto = "thin"`, retaining Cargo's
    default release `opt-level=3`.
    - Remove release and CI workflow-specific LTO overrides so
    release-profile builds consistently use the workspace setting.
    - Remove the now-unused Windows release workflow input and related
    diagnostic output.
    
    ## Validation
    
    - Confirmed the release profile parses with `cargo metadata --no-deps
    --format-version 1`.
    - CI validates release builds across the supported target matrix.
  • Use Azure artifact signing environment secrets (#25945)
    ## Why
    Windows release signing should read Azure signing credentials from the
    `azure-artifact-signing` environment instead of the old repo-level
    `AZURE_TRUSTED_SIGNING_*` names. The smoke runs confirmed the
    environment secrets resolve with the new `AZURE_ARTIFACT_SIGNING_*`
    names once the Windows signing job is attached to that environment.
    
    ## What Changed
    - Put the real Windows signing job in the `azure-artifact-signing`
    environment.
    - Switch the Windows signing action inputs from
    `AZURE_TRUSTED_SIGNING_*` to `AZURE_ARTIFACT_SIGNING_*`.
    - Drop the obsolete `workflow_call.secrets` declarations for the old
    repo-level secret names; the caller continues to use `secrets: inherit`.
    - Remove the temporary branch-trigger and Windows-only smoke-test
    workflow changes before finalizing this PR.
    
    ## Validation
    - `git diff --check -- .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
    - `ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts
    "yaml ok: #{f}" }' .github/workflows/rust-release.yml
    .github/workflows/rust-release-windows.yml`
  • ci: sign macOS release artifacts with Azure Key Vault (#26252)
    ## Why
    
    The public Codex release workflow needs to sign and notarize macOS
    binaries and DMGs without placing the Developer ID private key in
    GitHub. This moves the private-key operation behind the protected
    `codesigning` environment and uses GitHub OIDC with Azure Key Vault
    PKCS#11, while preserving the existing external `build_unsigned` /
    `promote_signed` fallback.
    
    ## What changed
    
    - Add a reusable AKV PKCS11 setup action that authenticates to Azure
    with OIDC, downloads pinned signing tools, verifies their SHA-256
    digests, and loads the public signing certificate from Key Vault.
    - Replace the legacy macOS signing action with scripts that support
    AKV-backed `rcodesign`, notarize signed binaries and DMGs, and staple
    DMG notarization tickets.
    - Restructure `rust-release.yml` so macOS builds produce unsigned
    artifacts first, protected jobs perform signing and notarization, macOS
    runners package and verify the results, and release publishing waits for
    verified artifacts.
    - Preserve the manual external-signing handoff flow and make manual-mode
    conditions explicit.
    - Move the Codex entitlements file alongside the signing scripts and
    update CODEOWNERS for the new signing surfaces.
    
    ## Verification
    
    - [Live protected signing workflow
    run](https://github.com/openai/codex/actions/runs/26903610631) completed
    successfully for both macOS architectures, including binary
    signing/notarization, DMG signing/notarization, and final artifact
    verification.
    - Downloaded both signed DMGs and independently verified their checksums
    and strict signatures.
    - Confirmed `xcrun stapler validate` succeeds and Gatekeeper accepts
    both DMGs as `Notarized Developer ID`.
    - Mounted both DMGs and confirmed the contained `codex` and
    `codex-responses-api-proxy` binaries have valid Developer ID signatures
    for the expected architectures.
    
    ---------
    
    Co-authored-by: shijie-openai <shijie.rao@openai.com>
  • [codex] Split Python runtime release workflow (#26226)
    ## Why
    
    Python SDK releases pin an exact `openai-codex-cli-bin` version, so all
    eight platform runtime wheels must be available on PyPI before the SDK
    package is built and published. PyPI does not support reusable workflows
    as Trusted Publishers, which means OIDC-backed publishing must run from
    each top-level release workflow.
    
    ## What changed
    
    - add reusable `python-runtime-build.yml` to prepare and upload all
    eight runtime wheels without publishing
    - add top-level `python-runtime-release.yml` for manual runtime
    publication before updating an SDK pin
    - have `python-sdk-release.yml` publish and verify the prepared runtime
    wheels from its own top-level trusted job before building the SDK
    - verify PyPI exposes exactly the expected eight runtime wheels before
    either release workflow continues
    
    ## PyPI configuration
    
    - keep the trusted publisher for
    `.github/workflows/python-sdk-release.yml` with environment `pypi`
    - add a trusted publisher for
    `.github/workflows/python-runtime-release.yml` with environment `pypi`
    - no trusted publisher is needed for
    `.github/workflows/python-runtime-build.yml`
    
    ## Validation
    
    - parsed all three workflow YAML files
    - validated all embedded shell blocks with `bash -n`
    - no local tests run; relying on online CI
  • [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] Consolidate shared prompts in codex-prompts (#25151)
    ## Why
    
    `codex_core` is consistently a bottleneck for incremental builds during
    iteration. The simplest fix is to make the crate smaller.
    
    ## Summary
    
    `codex-core` owns several reusable prompt renderers and static prompt
    assets, which makes the crate harder to split apart.
    
    Rename `codex-review-prompts` to `codex-prompts` and move shared review,
    goal, permissions, compaction, realtime, hierarchical AGENTS.md, and
    `apply_patch` prompts into it. Move prompt-only tests and update
    consumers and `CODEOWNERS`.
    
    ## Validation
    
    - `just test -p codex-prompts -p codex-apply-patch`
    - `just test -p codex-core prompt_caching`
    - Bazel builds for the affected crates
  • [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.