Commit Graph

384 Commits

  • chore: increase release build timeout from 60 min to 90 (#20271)
    Build times are creeping up, so increase the timeout as a precaution.
  • Clarify PR template invitation requirement (#19912)
    Addresses #19856
    
    ## Summary
    - Clarifies that external code contributions are invitation only.
    - Points contributors to `docs/contributing.md` for the full policy
    instead of using the previous warning phrasing.
  • ci: migrate Bazel setup away from archived setup-bazelisk (#19851)
    ## Why
    
    All Bazel CI jobs are currently blocked in the `setup-bazelisk` step
    while trying to download Bazelisk.
    [`bazelbuild/setup-bazelisk`](https://github.com/bazelbuild/setup-bazelisk)
    is archived, and its README now recommends migrating to
    [`bazel-contrib/setup-bazel`](https://github.com/bazel-contrib/setup-bazel),
    so leaving our workflows on the archived action leaves CI exposed to
    exactly this sort of outage.
    
    Because `v8-canary` now consumes the shared local `setup-bazel-ci`
    action, that workflow also needs to trigger when the action changes.
    Without that follow-up, Bazel bootstrap regressions specific to the V8
    canary path could be skipped by the workflow path filters.
    
    ## What Changed
    
    - Switched `.github/actions/setup-bazel-ci/action.yml` from
    `bazelbuild/setup-bazelisk` to `bazel-contrib/setup-bazel`, pinned to
    `0.19.0`.
    - Left `bazelisk-version` unset so GitHub-hosted runners can use their
    preinstalled Bazelisk instead of downloading `1.x` at job start.
    - Updated `.github/workflows/rusty-v8-release.yml` and
    `.github/workflows/v8-canary.yml` to use the shared `setup-bazel-ci`
    action instead of referencing `setup-bazelisk` directly.
    - Added `.github/actions/setup-bazel-ci/**` to the `pull_request` and
    `push` path filters in `.github/workflows/v8-canary.yml` so changes to
    the shared Bazel setup action still run the canary workflow.
    - Kept the existing repository-cache and Windows-specific Bazel setup
    logic intact.
    
    This keeps Bazel version selection anchored by `.bazelversion` while
    removing the failing dependency on the archived setup action.
    
    ## Verification
    
    - Searched `.github/` to confirm there are no remaining `setup-bazelisk`
    references.
    - Parsed the updated workflow and action YAML locally with Ruby's
    `YAML.load_file`.
  • ci: pin npm staging smoke test to a recent rust-release run (#19854)
    ## Why
    
    The `build-test` workflow stages a representative `codex` npm tarball by
    asking `scripts/stage_npm_packages.py` to look up a past `rust-release`
    run for a hardcoded release version. That started failing in CI because
    the representative version in `.github/workflows/ci.yml` was stale:
    
    - the workflow was still using `0.115.0`
    - `stage_npm_packages.py` resolves native artifacts by looking for a
    `rust-release` run on the `rust-v<version>` branch
    - that lookup no longer found a matching run for `rust-v0.115.0`, so the
    smoke test failed before it could stage the package
    
    This PR makes that smoke test depend on a known-good recent release run
    instead of an older branch lookup that is no longer reliable.
    
    ## What Changed
    
    - Updated the representative release version in
    `.github/workflows/ci.yml` from `0.115.0` to `0.125.0`.
    - Added an explicit `WORKFLOW_URL` pointing at a recent successful
    `rust-release` run:
    `https://github.com/openai/codex/actions/runs/24901475298`.
    - Passed that URL to `scripts/stage_npm_packages.py` via
    `--workflow-url` so the job can reuse the expected native artifacts
    directly instead of relying on `gh run list --branch rust-v<version>` to
    discover them.
    
    That keeps the npm staging smoke test representative while making it
    less sensitive to older release branch history disappearing from the
    GitHub Actions lookup path.
    
    ## Verification
    
    - Inspected the failing CI log from `build-test` and confirmed the
    failure came from `scripts/stage_npm_packages.py` being unable to
    resolve `rust-v0.115.0`.
    - Confirmed that
    `https://github.com/openai/codex/actions/runs/24901475298` is a
    successful `rust-release` run for `rust-v0.125.0`.
  • Guard npm update readiness (#19389)
    ## Why
    For npm/Bun-managed installs, the update prompt was treating the latest
    GitHub release as ready to install. During the `0.124.0` release, GitHub
    and npm visibility were not atomic: the root npm wrapper could become
    visible before the npm registry marked that version as the package
    `latest`. That left a window where users could be prompted to upgrade
    before npm was ready for the release.
    
    ## What changed
    - Keep GitHub Releases as the candidate latest-version source for
    npm/Bun installs, but only write the existing `version.json` cache after
    npm registry metadata proves that same root version is ready.
    - Add `codex-rs/tui/src/npm_registry.rs` to validate npm readiness by
    checking `dist-tags.latest` and root package `dist` metadata for the
    GitHub candidate version.
    - Move version parsing helpers into
    `codex-rs/tui/src/update_versions.rs` so that logic can be tested
    without compiling the release-only `updates.rs` module under tests.
    - Update `.github/workflows/rust-release.yml` so the six known platform
    tarballs publish before the root `@openai/codex` wrapper. Other npm
    tarballs publish before the root wrapper, and the SDK publishes after
    the root package it depends on.
  • fix: restore 30-minute timeout for Bazel builds (#19609)
    I think raising it to 45 minutes in
    https://github.com/openai/codex/pull/19578 was a mistake for the reasons
    explained in the comments in the code. Instead, we attempt to defend
    against timeouts by increasing the number of shards in
    `app-server-all-test` so that a "true failure" that gets run 3x should
    not take as much wall clock time.
  • fix: increase Bazel timeout to 45 minutes (#19578)
    Unfortunately, if most of the build graph is invalidated such that there
    are few cache hits, the Windows Bazel build for all the tests often
    takes more than `30` minutes, so this PR increases the timeout to `45`
    minutes until we set up distributed builds.
  • ci: pin codex-action v1.7 (#19472)
    ## Summary
    - update Codex issue automation to pin `openai/codex-action` to
    `5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02`, the commit for `v1.7`
    - keep the release intent visible with `# v1.7` comments beside the hash
    pins
    
    ## Test plan
    - `git diff --check`
    - `yq e '.' .github/workflows/issue-labeler.yml`
    - `yq e '.' .github/workflows/issue-deduplicator.yml`
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • ci: publish codex-app-server release artifacts (#19447)
    ## Why
    The VS Code extension and desktop app do not need the full TUI binary,
    and `codex-app-server` is materially smaller than standalone `codex`. We
    still want to publish it as an official release artifact, but building
    it by tacking another `--bin` onto the existing release `cargo build`
    invocations would lengthen those jobs.
    
    This change keeps `codex-app-server` on its own release bundle so it can
    build in parallel with the existing `codex` and helper bundles.
    
    ## What changed
    - Made `.github/workflows/rust-release.yml` bundle-aware so each macOS
    and Linux MUSL target now builds either the existing `primary` bundle
    (`codex` and `codex-responses-api-proxy`) or a standalone `app-server`
    bundle (`codex-app-server`).
    - Preserved the historical artifact names for the primary macOS/Linux
    bundles so `scripts/stage_npm_packages.py` and
    `codex-cli/scripts/install_native_deps.py` continue to find release
    assets under the paths they already expect, while giving the new
    app-server artifacts distinct names.
    - Added a matching `app-server` bundle to
    `.github/workflows/rust-release-windows.yml`, and updated the final
    Windows packaging job to download, sign, stage, and archive
    `codex-app-server.exe` alongside the existing release binaries.
    - Generalized the shared signing actions in
    `.github/actions/linux-code-sign/action.yml`,
    `.github/actions/macos-code-sign/action.yml`, and
    `.github/actions/windows-code-sign/action.yml` so each workflow row
    declares its binaries once and reuses that list for build, signing, and
    staging.
    - Added `codex-app-server` to `.github/dotslash-config.json` so releases
    also publish a generated DotSlash manifest for the standalone app-server
    binary.
    - Kept the macOS DMG focused on the existing `primary` bundle;
    `codex-app-server` ships as the regular standalone archives and DotSlash
    manifest.
    
    ## Verification
    - Parsed the modified workflow and action YAML files locally with
    `python3` + `yaml.safe_load(...)`.
    - Parsed `.github/dotslash-config.json` locally with `python3` +
    `json.loads(...)`.
    - Reviewed the resulting release matrices, artifact names, and packaging
    paths to confirm that `codex-app-server` is built separately on macOS,
    Linux MUSL, and Windows, while the existing npm staging and Windows
    `codex` zip bundling contracts remain intact.
  • ci: stop publishing GNU Linux release artifacts (#19445)
    ## Why
    We already prefer shipping the MUSL Linux builds, and the in-repo
    release consumers resolve Linux release assets through the MUSL targets.
    Keeping the GNU release jobs around adds release time and extra assets
    without serving the paths we actually publish and consume.
    
    This is also easier to reason about as a standalone change: future work
    can point back to this PR as the intentional decision to stop publishing
    `x86_64-unknown-linux-gnu` and `aarch64-unknown-linux-gnu` release
    artifacts.
    
    ## What changed
    - Removed the `x86_64-unknown-linux-gnu` and `aarch64-unknown-linux-gnu`
    entries from the `build` matrix in `.github/workflows/rust-release.yml`.
    - Added a short comment in that matrix documenting that Linux release
    artifacts intentionally ship MUSL-linked binaries.
    
    ## Verification
    - Reviewed `.github/workflows/rust-release.yml` to confirm that the
    release workflow now only builds Linux release artifacts for
    `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl`.
  • ci: reuse Bazel CI startup for target-discovery queries (#19232)
    ## Why
    
    A rerun of the Windows Bazel clippy job after
    [#19161](https://github.com/openai/codex/pull/19161) had exactly the
    cache behavior we wanted in BuildBuddy: zero action-cache misses. Even
    so, the GitHub job still took a little over five minutes.
    
    The problem was that the job was paying for two separate Bazel startup
    paths:
    
    1. a `bazel query` to discover extra lint targets
    2. the real `bazel build --config=clippy ...` invocation
    
    On Windows, that query was bypassing the CI Bazel wrapper, so it did not
    reuse the same `--output_user_root`, CI config, or remote-cache setup as
    the real build. In practice that meant the rerun could still cold-start
    a separate Bazel server before the actual clippy build even began.
    
    ## What
    
    - add `.github/scripts/run-bazel-query-ci.sh` to run CI-side Bazel
    queries with the same startup and cache-related flags as the main Bazel
    command
    - switch `scripts/list-bazel-clippy-targets.sh` to use that helper for
    manual `rust_test` target discovery
    - switch `tools/argument-comment-lint/list-bazel-targets.sh` to use the
    same helper
    - simplify `.github/scripts/run-argument-comment-lint-bazel.sh` so its
    Windows-only query path also goes through the shared helper
    
    This keeps the target-discovery queries aligned with the later
    build/test invocation instead of treating them as a separate cold Bazel
    session.
    
    ## Verification
    
    - `bash -n .github/scripts/run-bazel-query-ci.sh`
    - `bash -n scripts/list-bazel-clippy-targets.sh`
    - `bash -n tools/argument-comment-lint/list-bazel-targets.sh`
    - `bash -n .github/scripts/run-argument-comment-lint-bazel.sh`
    - mocked a Windows invocation of `run-bazel-query-ci.sh` and verified it
    forwards `--output_user_root`, `--config=ci-windows`, the BuildBuddy
    auth header, and the repository cache flags
    
    ## Docs
    
    No documentation updates are needed.
  • ci: derive cache-stable Windows Bazel PATH (#19161)
    ## Why
    
    The BuildBuddy runs for PR #19086 and the later `main` build had the
    same source tree, but their Windows Bazel action and test cache keys did
    not line up. Comparing the downloaded execution logs showed the full
    GitHub-hosted Windows runner `PATH` had changed from
    `apache-maven-3.9.14` to `apache-maven-3.9.15`.
    
    This repo is not using Maven; the Maven entry was just ambient
    hosted-runner state. The problem was that Windows Bazel CI was still
    forwarding the whole runner `PATH` into Bazel via `--action_env=PATH`,
    `--host_action_env=PATH`, and `--test_env=PATH`, which made otherwise
    reusable cache entries sensitive to unrelated runner image churn.
    
    After discussion with the Bazel and BuildBuddy folks, the better shape
    for this change was to stop asking Bazel to inherit the ambient Windows
    `PATH` and instead compute one explicit cache-stable `PATH` in the
    Windows setup action that already prepares the CI toolchain environment.
    
    ## What
    
    - remove Windows `PATH` passthrough from `.bazelrc`
    - export `CODEX_BAZEL_WINDOWS_PATH` from
    `.github/actions/setup-bazel-ci/action.yml`
    - move the PATH derivation logic into
    `.github/scripts/compute-bazel-windows-path.ps1` so the allow-list is
    easier to review and document
    - keep only the Windows tool locations these Bazel jobs actually need:
    MSVC and SDK paths, Git, PowerShell, Node, DotSlash, and the standard
    Windows system directories
    - update `.github/scripts/run-bazel-ci.sh` to require that explicit
    value and forward it to Bazel action, host action, and test environments
    - log the derived `CODEX_BAZEL_WINDOWS_PATH` in the setup step to
    simplify cache-key debugging
    
    ## Verification
    
    - `bash -n .github/scripts/run-bazel-ci.sh`
    - `ruby -e 'require "yaml"; YAML.load_file(ARGV[0])'
    .github/actions/setup-bazel-ci/action.yml`
    - PowerShell parse check for
    `.github/scripts/compute-bazel-windows-path.ps1`
    - simulated a representative Windows `PATH` in PowerShell; the
    allow-list retained MSVC, Git, PowerShell, Node, Windows, and DotSlash
    entries while dropping Maven
  • ci: add macOS keychain entitlements (#19167)
    ## Summary
    
    - add macOS application and team identifiers to the release signing
    entitlements
    - add a Codex keychain access group for release-signed macOS binaries
    - keep the existing JIT entitlement unchanged
    
    ## Why
    
    Codex release binaries are signed with the OpenAI Developer ID team, but
    the current entitlements plist only grants JIT. macOS Keychain and
    Secure Enclave operations that create persistent keys can require the
    process to carry an application identifier and keychain access group.
    Adding these entitlements gives release-signed binaries a stable
    Keychain namespace for Codex-owned device keys.
    
    ## Validation
    
    - `plutil -lint
    .github/actions/macos-code-sign/codex.entitlements.plist`
  • test: set Rust test thread stack size (#19067)
    ## Summary
    
    Set `RUST_MIN_STACK=8388608` for Rust test entry points so
    libtest-spawned test threads get an 8 MiB stack.
    
    The Windows BuildBuddy failure on #18893 showed
    `//codex-rs/tui:tui-unit-tests` exiting with a stack overflow in a
    `#[tokio::test]` even though later test binaries in the shard printed
    successful summaries. Default `#[tokio::test]` uses a current-thread
    Tokio runtime, which means the async test body is driven on libtest's
    std-spawned test thread. Increasing the test thread stack addresses that
    failure mode directly.
    
    To date, we have been fixing these stack-pressure problems with
    localized future-size reductions, such as #13429, and by adding
    `Box::pin()` in specific async wrapper chains. This gives us a baseline
    test-runner stack size instead of continuing to patch individual tests
    only after CI finds another large async future.
    
    ## What changed
    
    - Added `common --test_env=RUST_MIN_STACK=8388608` in `.bazelrc` so
    Bazel test actions receive the env var through Bazel's cache-keyed test
    environment path.
    - Set the same `RUST_MIN_STACK` value for Cargo/nextest CI entry points
    and `just test`.
    - Annotated the existing Windows Bazel linker stack reserve as 8 MiB so
    it stays aligned with the libtest thread stack size.
    
    ## Testing
    
    - `just --list`
    - parsed `.github/workflows/rust-ci.yml` and
    `.github/workflows/rust-ci-full.yml` with Ruby's YAML loader
    - compared `bazel aquery` `TestRunner` action keys before/after explicit
    `--test_env=RUST_MIN_STACK=...` and after moving the Bazel env to
    `.bazelrc`
    - `bazel test //codex-rs/tui:tui-unit-tests --test_output=errors`
    - failed locally on the existing sandbox-specific status snapshot
    permission mismatch, but loaded the Starlark changes and ran the TUI
    test shards
  • ci: keep argument comment lint checks materialized (#18926)
    ## Why
    
    The fast `rust-ci` workflow decides whether to run the cross-platform
    `argument-comment-lint` job based on changed paths. PRs that touch
    Rust-adjacent Bazel wrapper files, such as `defs.bzl` or
    `workspace_root_test_launcher.*.tpl`, can change how Rust tests and lint
    targets behave without changing any `.rs` files.
    
    When that detector returned false, GitHub skipped the matrix job before
    expanding it. That produced a single skipped check named `Argument
    comment lint - ${{ matrix.name }}` instead of the Linux, macOS, and
    Windows check names that branch protection expects, leaving the PR
    unable to go green when those matrix checks are required.
    
    ## What Changed
    
    - Treat root Bazel wrapper files as `argument-comment-lint` relevant
    changes.
    - Keep the `argument_comment_lint_prebuilt` matrix job materialized for
    every PR so the per-platform check names always exist.
    - Add a single gate step that decides whether the real lint work should
    run.
    - Move the checkout-adjacent Bazel setup and OS-specific lint commands
    into `.github/actions/run-argument-comment-lint/action.yml` so the
    workflow does not repeat the same path-detection condition on each step.
    
    ## Verification
    
    - Parsed `.github/workflows/rust-ci.yml` and
    `.github/actions/run-argument-comment-lint/action.yml` with Python YAML
    loading.
    - Simulated the workflow path-matching shell conditions for the root
    Bazel wrapper files and confirmed they set `argument_comment_lint=true`.
  • fix(guardian) Dont hard error on feature disable (#18795)
    ## Summary 
    This shouldn't error for now
    
    ## Test plan
    - [x] Updated unit test
  • Remove unused models.json (#18585)
    - Remove the stale core models catalog.
    - Update the release workflow to refresh the active models-manager
    catalog.
  • ci: scope Bazel repository cache by job (#18366)
    ## Why
    
    The Bazel workflow has multiple jobs that run concurrently for the same
    target triple. In particular, the Windows `test`, `clippy`, and
    `verify-release-build` jobs could all miss and then attempt to save the
    same Bazel repository cache key:
    
    ```text
    bazel-cache-${target}-${lockhash}
    ```
    
    Because `actions/cache` entries are immutable, only one job can reserve
    that key. The others can report failures such as:
    
    ```text
    Failed to save: Unable to reserve cache with key bazel-cache-x86_64-pc-windows-gnullvm-..., another job may be creating this cache.
    ```
    
    Adding only the workflow name would not separate these jobs because they
    all run inside the same `Bazel` workflow. The key needs a job-level
    namespace as well.
    
    ## What Changed
    
    - Added a required `cache-scope` input to
    `.github/actions/prepare-bazel-ci/action.yml`.
    - Moved Bazel repository cache key construction into the shared action
    and exposed the computed key as `repository-cache-key`.
    - Exposed the exact restore result as `repository-cache-hit` so save
    steps can skip exact cache hits.
    - Updated `.github/workflows/bazel.yml` to pass `cache-scope: bazel-${{
    github.job }}` for the `test`, `clippy`, and `verify-release-build`
    jobs.
    - The scoped restore key is now the only fallback. This avoids carrying
    a temporary restore path for the old unscoped cache namespace.
    
    ## Verification
    
    - Parsed `.github/actions/prepare-bazel-ci/action.yml` and
    `.github/workflows/bazel.yml` with Ruby's YAML parser.
    - `actionlint` is not installed in this workspace, so I could not run a
    GitHub Actions semantic lint locally.
  • Add core CODEOWNERS (#18362)
    Adds @openai/codex-core-agent-team as the owner for codex-rs/core/ and
    protects .github/CODEOWNERS with the same owner.
  • ci: make Windows Bazel clippy catch core test imports (#18350)
    ## Why
    
    Unused imports in `core/tests/suite/unified_exec.rs` in the Windows
    build were not caught by Bazel CI on
    https://github.com/openai/codex/pull/18096. I spot-checked
    https://github.com/openai/codex/actions/workflows/rust-ci-full.yml?query=branch%3Amain
    and noticed that builds were consistently red. This revealed that our
    Cargo builds _were_ properly catching these issues, identifying a
    Windows-specific coverage hole in the Bazel clippy job.
    
    The Windows Bazel clippy job uses `--skip_incompatible_explicit_targets`
    so it can lint a broad target set without failing immediately on targets
    that are genuinely incompatible with Windows. However, with the default
    Windows host platform, `rust_test` targets such as
    `//codex-rs/core:core-all-test` could be skipped before the clippy
    aspect reached their integration-test modules. As a result, the imports
    in `core/tests/suite/unified_exec.rs` were not being linted by the
    Windows Bazel clippy job at all.
    
    The clippy diagnostic that Windows Bazel should have surfaced was:
    
    ```text
    error: unused import: `codex_config::Constrained`
     --> core\tests\suite\unified_exec.rs:8:5
      |
    8 | use codex_config::Constrained;
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^
      |
      = note: `-D unused-imports` implied by `-D warnings`
      = help: to override `-D warnings` add `#[allow(unused_imports)]`
    
    error: unused import: `codex_protocol::permissions::FileSystemAccessMode`
      --> core\tests\suite\unified_exec.rs:11:5
       |
    11 | use codex_protocol::permissions::FileSystemAccessMode;
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: unused import: `codex_protocol::permissions::FileSystemPath`
      --> core\tests\suite\unified_exec.rs:12:5
       |
    12 | use codex_protocol::permissions::FileSystemPath;
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: unused import: `codex_protocol::permissions::FileSystemSandboxEntry`
      --> core\tests\suite\unified_exec.rs:13:5
       |
    13 | use codex_protocol::permissions::FileSystemSandboxEntry;
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: unused import: `codex_protocol::permissions::FileSystemSandboxPolicy`
      --> core\tests\suite\unified_exec.rs:14:5
       |
    14 | use codex_protocol::permissions::FileSystemSandboxPolicy;
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ```
    
    ## What changed
    
    - Run the Windows Bazel clippy job with the MSVC host platform via
    `--windows-msvc-host-platform`, matching the Windows Bazel test job.
    This keeps `--skip_incompatible_explicit_targets` while ensuring Windows
    `rust_test` targets such as `//codex-rs/core:core-all-test` are still
    linted.
    - Remove the unused imports from `core/tests/suite/unified_exec.rs`.
    - Add `--print-failed-action-summary` to
    `.github/scripts/run-bazel-ci.sh` so Bazel action failures can be
    summarized after the build exits.
    
    ## Failure reporting
    
    Once the coverage issue was fixed, an intentionally reintroduced unused
    import made the Windows Bazel clippy job fail as expected. That exposed
    a separate usability problem: because the job keeps `--keep_going`, the
    top-level Bazel output could still end with:
    
    ```text
    ERROR: Build did NOT complete successfully
    FAILED:
    ```
    
    without the underlying rustc/clippy diagnostic being visible in the
    obvious part of the GitHub Actions log.
    
    To keep `--keep_going` while making failures actionable, the wrapper now
    scans the captured Bazel console output for failed actions and prints
    the matching rustc/clippy diagnostic block. When a diagnostic block is
    found, it is emitted both as a GitHub `::error` annotation and as plain
    expanded log output, rather than being hidden in a collapsed group.
    
    ## Verification
    
    To validate the CI path, I intentionally introduced an unused import in
    `core/tests/suite/unified_exec.rs`. The Windows Bazel clippy job failed
    as expected, confirming that the integration-test module is now covered
    by Bazel clippy. The same failure also verified that the wrapper
    surfaces the matching clippy diagnostics directly in the Actions output.
  • Throttle Windows Bazel test concurrency (#18192)
    ## Summary
    - cap the Windows Bazel test lane at `--jobs=8` to reduce local runner
    pressure
    - keep Linux and macOS Bazel test concurrency unchanged
    - make failed-test log tailing resolve `bazel-testlogs` with the same CI
    config and Windows host-platform context as the failed invocation
    - prefer Bazel-reported `test.log` paths and normalize Windows path
    separators before tailing
    
    ## Context
    The Windows Bazel workflow currently uses `ci-windows`, which does not
    inherit the remote executor config. This means the lane runs the `//...`
    test suite locally and otherwise falls back to the repo-wide `common
    --jobs=30`. The new Windows-only override is intended to reduce local
    executor pressure without changing coverage.
    
    ## Validation
    Not run locally; this is a CI workflow change and the draft PR is
    intended to exercise the GitHub Actions lane directly.
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • debug: windows flake (#18135)
    Make sure Bazel logs shows every errors so that we can debug flakes +
    fix a small flake on Windows by updating the sleep command to a
    `Start-Sleep` instead of a PowerShell nested command (otherwise we had
    double nesting which is absurdely slow)
  • [docs] Revert extra changes from PR 17848 (#18003)
    ## Summary
    
    1. Revert https://github.com/openai/codex/pull/17848 so the Bazel and
    `BUILD` file changes leave `main`.
    2. Prepare for a narrower follow up that restores only `SECURITY.md`.
    
    ## Validation
    
    1. Reviewed the revert diff against `main`.
    2. Ran a clean diff check before push.
  • [docs] Add security boundaries reference in SECURITY.md (#17848)
    ## Summary
    1. Add a Security Boundaries section to `SECURITY.md`.
    2. Point readers to the Codex Agent approvals and security documentation
    for sandboxing, approvals, and network controls.
    
    ## Validation
    1. Reviewed the `SECURITY.md` diff in a clean worktree.
    2. No tests run. Docs only change.
  • Reuse remote exec-server in core tests (#17837)
    ## Summary
    - reuse a shared remote exec-server for remote-aware codex-core
    integration tests within a test binary process
    - keep per-test remote cwd creation and cleanup so tests retain
    workspace isolation
    - leave codex_self_exe, codex_linux_sandbox_exe, cwd_path(), and
    workspace_path() behavior unchanged
    
    ## Validation
    - rustfmt codex-rs/core/tests/common/test_codex.rs
    - git diff --check
    - CI is running on the updated branch
  • Add Bazel verify-release-build job (#17705)
    ## Why
    
    `main` recently needed
    [#17691](https://github.com/openai/codex/pull/17691) because code behind
    `cfg(not(debug_assertions))` was not being compiled by the Bazel PR
    workflow. Our existing CI only built the fast/debug configuration, so
    PRs could stay green while release-only Rust code still failed to
    compile. This PR adds a release-style compile check that is cheap enough
    to run on every PR.
    
    ## What Changed
    
    - Added a `verify-release-build` job to `.github/workflows/bazel.yml`.
    - Represented each supported OS once in that job's matrix: x64 Linux,
    arm64 macOS, and x64 Windows.
    - Kept the build close to fastbuild cost by using
    `--compilation_mode=fastbuild` while forcing Rust to compile with
    `-Cdebug-assertions=no`, which makes `cfg(not(debug_assertions))` true
    without also turning on release optimizations or debug-info generation.
    - Added comments in `.github/workflows/bazel.yml` and
    `scripts/list-bazel-release-targets.sh` to make the job's intent and
    target scope explicit.
    - Restored the Bazel repository cache save behavior to run after every
    non-cancelled job, matching
    [#16926](https://github.com/openai/codex/pull/16926), and removed the
    now-unused `repository-cache-hit` output from `prepare-bazel-ci`.
    - Reused the shared `prepare-bazel-ci` action from the parent PR so the
    new job does not duplicate Bazel setup boilerplate.
    
    ## Verification
    
    - Used `bazel aquery` on `//codex-rs/tui:codex-tui` to confirm the Rust
    compile still uses `opt-level=0` and `debuginfo=0` while passing
    `-Cdebug-assertions=no`.
    - Parsed `.github/workflows/bazel.yml` as YAML locally.
    - Ran `bash -n scripts/list-bazel-release-targets.sh`.
  • Refactor Bazel CI job setup (#17704)
    ## Why
    
    This stack adds a new Bazel CI lane that verifies Rust code behind
    `cfg(not(debug_assertions))`, but adding that job directly to
    `.github/workflows/bazel.yml` would duplicate the same setup in multiple
    places. Extracting the shared setup first keeps the follow-up change
    easier to review and reduces the chance that future Bazel workflow edits
    drift apart.
    
    ## What Changed
    
    - Added `.github/actions/prepare-bazel-ci/action.yml` as a composite
    action for the Bazel job bootstrap shared by multiple workflow jobs.
    - Moved the existing Bazel setup, repository-cache restore, and
    execution-log setup behind that action.
    - Updated the `test` and `clippy` jobs in `.github/workflows/bazel.yml`
    to call `prepare-bazel-ci`.
    - Exposed `repository-cache-hit` and `repository-cache-path` outputs so
    callers can keep the existing cache-save behavior without duplicating
    the restore step.
    
    ## Verification
    
    - Parsed `.github/workflows/bazel.yml` as YAML locally after rebasing
    the stack.
    - CI will exercise the refactored jobs end to end.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/17704).
    * #17705
    * __->__ #17704
  • fix: Revert danger-full-access denylist-only mode (#17732)
    ## Summary
    
    - Reverts openai/codex#16946 and removes the danger-full-access
    denylist-only network mode.
    - Removes the corresponding config requirements, app-server
    protocol/schema, config API, TUI debug output, and network proxy
    behavior.
    - Drops stale tests that depended on the reverted mode while preserving
    newer managed allowlist-only coverage.
    
    ## Verification
    
    - `just write-app-server-schema`
    - `just fmt`
    - `cargo test -p codex-config network_requirements`
    - `cargo test -p codex-core network_proxy_spec`
    - `cargo test -p codex-core
    managed_network_proxy_decider_survives_full_access_start`
    - `cargo test -p codex-app-server map_requirements_toml_to_api`
    - `cargo test -p codex-tui debug_config_output`
    - `cargo test -p codex-app-server-protocol`
    - `just fix -p codex-config -p codex-core -p codex-app-server-protocol
    -p codex-app-server -p codex-tui`
    - `git diff --cached --check`
    
    Not run: full workspace `cargo test` (repo instructions ask for
    confirmation before that broader run).
  • fix: pin inputs (#17471)
    ## Summary
    - Pin Rust git patch dependencies to immutable revisions and make
    cargo-deny reject unknown git and registry sources unless explicitly
    allowlisted.
    - Add checked-in SHA-256 coverage for the current rusty_v8 release
    assets, wire those hashes into Bazel, and verify CI override downloads
    before use.
    - Add rusty_v8 MODULE.bazel update/check tooling plus a Bazel CI guard
    so future V8 bumps cannot drift from the checked-in checksum manifest.
    - Pin release/lint cargo installs and all external GitHub Actions refs
    to immutable inputs.
    
    ## Future V8 bump flow
    Run these after updating the resolved `v8` crate version and checksum
    manifest:
    
    ```bash
    python3 .github/scripts/rusty_v8_bazel.py update-module-bazel
    python3 .github/scripts/rusty_v8_bazel.py check-module-bazel
    ```
    
    The update command rewrites the matching `rusty_v8_<crate_version>`
    `http_file` SHA-256 values in `MODULE.bazel` from
    `third_party/v8/rusty_v8_<crate_version>.sha256`. The check command is
    also wired into Bazel CI to block drift.
    
    ## Notes
    - This intentionally excludes RustSec dependency upgrades and
    bubblewrap-related changes per request.
    - The branch was rebased onto the latest origin/main before opening the
    PR.
    
    ## Validation
    - cargo fetch --locked
    - cargo deny check advisories
    - cargo deny check
    - cargo deny check sources
    - python3 .github/scripts/rusty_v8_bazel.py check-module-bazel
    - python3 .github/scripts/rusty_v8_bazel.py update-module-bazel
    - python3 -m unittest discover -s .github/scripts -p
    'test_rusty_v8_bazel.py'
    - python3 -m py_compile .github/scripts/rusty_v8_bazel.py
    .github/scripts/rusty_v8_module_bazel.py
    .github/scripts/test_rusty_v8_bazel.py
    - repo-wide GitHub Actions `uses:` audit: all external action refs are
    pinned to 40-character SHAs
    - yq eval on touched workflows and local actions
    - git diff --check
    - just bazel-lock-check
    
    ## Hash verification
    - Confirmed `MODULE.bazel` hashes match
    `third_party/v8/rusty_v8_146_4_0.sha256`.
    - Confirmed GitHub release asset digests for denoland/rusty_v8
    `v146.4.0` and openai/codex `rusty-v8-v146.4.0` match the checked-in
    hashes.
    - Streamed and SHA-256 hashed all 10 `MODULE.bazel` rusty_v8 asset URLs
    locally; every downloaded byte stream matched both `MODULE.bazel` and
    the checked-in manifest.
    
    ## Pin verification
    - Confirmed signing-action pins match the peeled commits for their tag
    comments: `sigstore/cosign-installer@v3.7.0`, `azure/login@v2`, and
    `azure/trusted-signing-action@v0`.
    - Pinned the remaining tag-based action refs in Bazel CI/setup:
    `actions/setup-node@v6`, `facebook/install-dotslash@v2`,
    `bazelbuild/setup-bazelisk@v3`, and `actions/cache/restore@v5`.
    - Normalized all `bazelbuild/setup-bazelisk@v3` refs to the peeled
    commit behind the annotated tag.
    - Audited Cargo git dependencies: every manifest git dependency uses
    `rev` only, every `Cargo.lock` git source has `?rev=<sha>#<same-sha>`,
    and `cargo deny check sources` passes with `required-git-spec = "rev"`.
    - Shallow-fetched each distinct git dependency repo at its pinned SHA
    and verified Git reports each object as a commit.
  • Update issue labeler agent labels (#17483)
    Problem: The automatic issue labeler still treated agent-related issues
    as one broad category, even though more specific agent-area labels now
    exist.
    
    Solution: Update the issue labeler prompt to prefer the new agent-area
    labels and keep "agent" as the fallback for uncategorized core agent
    issues.
  • TUI: enforce core boundary (#17399)
    Problem: The TUI still depended on `codex-core` directly in a number of
    places, and we had no enforcement from keeping this problem from getting
    worse.
    
    Solution: Route TUI core access through
    `codex-app-server-client::legacy_core`, add CI enforcement for that
    boundary, and re-export this legacy bridge inside the TUI as
    `crate::legacy_core` so the remaining call sites stay readable. There is
    no functional change in this PR — just changes to import targets.
    
    Over time, we can whittle away at the remaining symbols in this legacy
    namespace with the eventual goal of removing them all. In the meantime,
    this linter rule will prevent us from inadvertently importing new
    symbols from core.
  • Remove obsolete codex-cli README (#17096)
    Problem: codex-cli/README.md is obsolete and confusing to keep around.
    
    Solution: Delete codex-cli/README.md so the stale README is no longer
    present in the repository.
  • Add full-ci branch trigger (#16980)
    Allow branches to trigger full ci (helpful to run remote tests)
  • bazel: Always save bazel repository cache (#16926)
    This should improve the cache hit ratio for external deps and such
  • ci: align Bazel repo cache and Windows clippy target handling (#16740)
    ## Why
    
    Bazel CI had two independent Windows issues:
    
    - The workflow saved/restored `~/.cache/bazel-repo-cache`, but
    `.bazelrc` configured `common:ci-windows
    --repository_cache=D:/a/.cache/bazel-repo-cache`, so `actions/cache` and
    Bazel could point at different directories.
    - The Windows `Bazel clippy` job passed the full explicit target list
    from `//codex-rs/...`, but some of those explicit targets are
    intentionally incompatible with `//:local_windows`.
    `run-argument-comment-lint-bazel.sh` already handles that with
    `--skip_incompatible_explicit_targets`; the clippy workflow path did
    not.
    
    I also tried switching the workflow cache path to
    `D:\a\.cache\bazel-repo-cache`, but the Windows clippy job repeatedly
    failed with `Failed to restore: Cache service responded with 400`, so
    the final change standardizes on `$HOME/.cache/bazel-repo-cache` and
    makes cache restore non-fatal.
    
    ## What Changed
    
    - Expose one repository-cache path from
    `.github/actions/setup-bazel-ci/action.yml` and export that path as
    `BAZEL_REPOSITORY_CACHE` so `run-bazel-ci.sh` passes it to Bazel after
    `--config=ci-*`.
    - Move `actions/cache/restore` out of the composite action into
    `.github/workflows/bazel.yml`, and make restore failures non-fatal
    there.
    - Save exactly the exported cache path in `.github/workflows/bazel.yml`.
    - Remove `common:ci-windows
    --repository_cache=D:/a/.cache/bazel-repo-cache` from `.bazelrc` so the
    Windows CI config no longer disagrees with the workflow cache path.
    - Pass `--skip_incompatible_explicit_targets` in the Windows `Bazel
    clippy` job so incompatible explicit targets do not fail analysis while
    the lint aspect still traverses compatible Rust dependencies.
    
    ## Verification
    
    - Parsed `.github/actions/setup-bazel-ci/action.yml` and
    `.github/workflows/bazel.yml` with Ruby's YAML loader.
    - Resubmitted PR `#16740`; CI is rerunning on the amended commit.
  • Use Node 24 for npm publish (#16755)
    Avoid self-upgrading the runner's bundled npm in release publishing;
    Node 24 already provides an npm CLI that supports trusted publishing.
    
    Co-authored-by: Codex <noreply@openai.com>
  • bazel: lint rust_test targets in clippy workflow (#16450)
    ## Why
    
    `cargo clippy --tests` was catching warnings in inline `#[cfg(test)]`
    code that the Bazel PR Clippy lane missed. The existing Bazel invocation
    linted `//codex-rs/...`, but that did not apply Clippy to the generated
    manual `rust_test` binaries, so warnings in targets such as
    `//codex-rs/state:state-unit-tests-bin` only surfaced as plain compile
    warnings instead of failing the lint job.
    
    ## What Changed
    
    - added `scripts/list-bazel-clippy-targets.sh` to expand the Bazel
    Clippy target set with the generated manual `rust_test` rules while
    still excluding `//codex-rs/v8-poc:all`
    - updated `.github/workflows/bazel.yml` to use that expanded target list
    in the Bazel Clippy PR job
    - updated `just bazel-clippy` to use the same target expansion locally
    - updated `.github/workflows/README.md` to document that the Bazel PR
    lint lane now covers inline `#[cfg(test)]` code
    
    ## Verification
    
    - `./scripts/list-bazel-clippy-targets.sh` includes
    `//codex-rs/state:state-unit-tests-bin`
    - `bazel build --config=clippy -- //codex-rs/state:state-unit-tests-bin`
    now fails with the same unused import in `state/src/runtime/logs.rs`
    that `cargo clippy --tests` reports
  • Codex/windows bazel rust test coverage no rs (#16528)
    # Why this PR exists
    
    This PR is trying to fix a coverage gap in the Windows Bazel Rust test
    lane.
    
    Before this change, the Windows `bazel test //...` job was nominally
    part of PR CI, but a non-trivial set of `//codex-rs/...` Rust test
    targets did not actually contribute test signal on Windows. In
    particular, targets such as `//codex-rs/core:core-unit-tests`,
    `//codex-rs/core:core-all-test`, and `//codex-rs/login:login-unit-tests`
    were incompatible during Bazel analysis on the Windows gnullvm platform,
    so they never reached test execution there. That is why the
    Cargo-powered Windows CI job could surface Windows-only failures that
    the Bazel-powered job did not report: Cargo was executing those tests,
    while Bazel was silently dropping them from the runnable target set.
    
    The main goal of this PR is to make the Windows Bazel test lane execute
    those Rust test targets instead of skipping them during analysis, while
    still preserving `windows-gnullvm` as the target configuration for the
    code under test. In other words: use an MSVC host/exec toolchain where
    Bazel helper binaries and build scripts need it, but continue compiling
    the actual crate targets with the Windows gnullvm cfgs that our current
    Bazel matrix is supposed to exercise.
    
    # Important scope note
    
    This branch intentionally removes the non-resource-loading `.rs` test
    and production-code changes from the earlier
    `codex/windows-bazel-rust-test-coverage` branch. The only Rust source
    changes kept here are runfiles/resource-loading fixes in TUI tests:
    
    - `codex-rs/tui/src/chatwidget/tests.rs`
    - `codex-rs/tui/tests/manager_dependency_regression.rs`
    
    That is deliberate. Since the corresponding tests already pass under
    Cargo, this PR is meant to test whether Bazel infrastructure/toolchain
    fixes alone are enough to get a healthy Windows Bazel test signal,
    without changing test behavior for Windows timing, shell output, or
    SQLite file-locking.
    
    # How this PR changes the Windows Bazel setup
    
    ## 1. Split Windows host/exec and target concerns in the Bazel test lane
    
    The core change is that the Windows Bazel test job now opts into an MSVC
    host platform for Bazel execution-time tools, but only for `bazel test`,
    not for the Bazel clippy build.
    
    Files:
    
    - `.github/workflows/bazel.yml`
    - `.github/scripts/run-bazel-ci.sh`
    - `MODULE.bazel`
    
    What changed:
    
    - `run-bazel-ci.sh` now accepts `--windows-msvc-host-platform`.
    - When that flag is present on Windows, the wrapper appends
    `--host_platform=//:local_windows_msvc` unless the caller already
    provided an explicit `--host_platform`.
    - `bazel.yml` passes that wrapper flag only for the Windows `bazel test
    //...` job.
    - The Bazel clippy job intentionally does **not** pass that flag, so
    clippy stays on the default Windows gnullvm host/exec path and continues
    linting against the target cfgs we care about.
    - `run-bazel-ci.sh` also now forwards `CODEX_JS_REPL_NODE_PATH` on
    Windows and normalizes the `node` executable path with `cygpath -w`, so
    tests that need Node resolve the runner's Node installation correctly
    under the Windows Bazel test environment.
    
    Why this helps:
    
    - The original incompatibility chain was mostly on the **exec/tool**
    side of the graph, not in the Rust test code itself. Moving host tools
    to MSVC lets Bazel resolve helper binaries and generators that were not
    viable on the gnullvm exec platform.
    - Keeping the target platform on gnullvm preserves cfg coverage for the
    crates under test, which is important because some Windows behavior
    differs between `msvc` and `gnullvm`.
    
    ## 2. Teach the repo's Bazel Rust macro about Windows link flags and
    integration-test knobs
    
    Files:
    
    - `defs.bzl`
    - `codex-rs/core/BUILD.bazel`
    - `codex-rs/otel/BUILD.bazel`
    - `codex-rs/tui/BUILD.bazel`
    
    What changed:
    
    - Replaced the old gnullvm-only linker flag block with
    `WINDOWS_RUSTC_LINK_FLAGS`, which now handles both Windows ABIs:
      - gnullvm gets `-C link-arg=-Wl,--stack,8388608`
    - MSVC gets `-C link-arg=/STACK:8388608`, `-C
    link-arg=/NODEFAULTLIB:libucrt.lib`, and `-C link-arg=ucrt.lib`
    - Threaded those Windows link flags into generated `rust_binary`,
    unit-test binaries, and integration-test binaries.
    - Extended `codex_rust_crate(...)` with:
      - `integration_test_args`
      - `integration_test_timeout`
    - Used those new knobs to:
    - mark `//codex-rs/core:core-all-test` as a long-running integration
    test
      - serialize `//codex-rs/otel:otel-all-test` with `--test-threads=1`
    - Added `src/**/*.rs` to `codex-rs/tui` test runfiles, because one
    regression test scans source files at runtime and Bazel does not expose
    source-tree directories unless they are declared as data.
    
    Why this helps:
    
    - Once host-side MSVC tools are available, we still need the generated
    Rust test binaries to link correctly on Windows. The MSVC-side
    stack/UCRT flags make those binaries behave more like their Cargo-built
    equivalents.
    - The integration-test macro knobs avoid hardcoding one-off test
    behavior in ad hoc BUILD rules and make the generated test targets more
    expressive where Bazel and Cargo have different runtime defaults.
    
    ## 3. Patch `rules_rs` / `rules_rust` so Windows MSVC exec-side Rust and
    build scripts are actually usable
    
    Files:
    
    - `MODULE.bazel`
    - `patches/rules_rs_windows_exec_linker.patch`
    - `patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch`
    - `patches/rules_rust_windows_build_script_runner_paths.patch`
    - `patches/rules_rust_windows_exec_msvc_build_script_env.patch`
    - `patches/rules_rust_windows_msvc_direct_link_args.patch`
    - `patches/rules_rust_windows_process_wrapper_skip_temp_outputs.patch`
    - `patches/BUILD.bazel`
    
    What these patches do:
    
    - `rules_rs_windows_exec_linker.patch`
    - Adds a `rust-lld` filegroup for Windows Rust toolchain repos,
    symlinked to `lld-link.exe` from `PATH`.
      - Marks Windows toolchains as using a direct linker driver.
      - Supplies Windows stdlib link flags for both gnullvm and MSVC.
    - `rules_rust_windows_bootstrap_process_wrapper_linker.patch`
    - For Windows MSVC Rust targets, prefers the Rust toolchain linker over
    an inherited C++ linker path like `clang++`.
    - This specifically avoids the broken mixed-mode command line where
    rustc emits MSVC-style `/NOLOGO` / `/LIBPATH:` / `/OUT:` arguments but
    Bazel still invokes `clang++.exe`.
    - `rules_rust_windows_build_script_runner_paths.patch`
    - Normalizes forward-slash execroot-relative paths into Windows path
    separators before joining them on Windows.
    - Uses short Windows paths for `RUSTC`, `OUT_DIR`, and the build-script
    working directory to avoid path-length and quoting issues in third-party
    build scripts.
    - Exposes `RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER=1` to build scripts so
    crate-local patches can detect "this is running under Bazel's
    build-script runner".
    - Fixes the Windows runfiles cleanup filter so generated files with
    retained suffixes are actually retained.
    - `rules_rust_windows_exec_msvc_build_script_env.patch`
    - For exec-side Windows MSVC build scripts, stops force-injecting
    Bazel's `CC`, `CXX`, `LD`, `CFLAGS`, and `CXXFLAGS` when that would send
    GNU-flavored tool paths/flags into MSVC-oriented Cargo build scripts.
    - Rewrites or strips GNU-only `--sysroot`, MinGW include/library paths,
    stack-protector, and `_FORTIFY_SOURCE` flags on the MSVC exec path.
    - The practical effect is that build scripts can fall back to the Visual
    Studio toolchain environment already exported by CI instead of crashing
    inside Bazel's hermetic `clang.exe` setup.
    - `rules_rust_windows_msvc_direct_link_args.patch`
    - When using a direct linker on Windows, stops forwarding GNU driver
    flags such as `-L...` and `--sysroot=...` that `lld-link.exe` does not
    understand.
    - Passes non-`.lib` native artifacts as explicit `-Clink-arg=<path>`
    entries when needed.
    - Filters C++ runtime libraries to `.lib` artifacts on the Windows
    direct-driver path.
    - `rules_rust_windows_process_wrapper_skip_temp_outputs.patch`
    - Excludes transient `*.tmp*` and `*.rcgu.o` files from process-wrapper
    dependency search-path consolidation, so unstable compiler outputs do
    not get treated as real link search-path inputs.
    
    Why this helps:
    
    - The host-platform split alone was not enough. Once Bazel started
    analyzing/running previously incompatible Rust tests on Windows, the
    next failures were in toolchain plumbing:
    - MSVC-targeted Rust tests were being linked through `clang++` with
    MSVC-style arguments.
    - Cargo build scripts running under Bazel's Windows MSVC exec platform
    were handed Unix/GNU-flavored path and flag shapes.
    - Some generated paths were too long or had path-separator forms that
    third-party Windows build scripts did not tolerate.
    - These patches make that mixed Bazel/Cargo/Rust/MSVC path workable
    enough for the test lane to actually build and run the affected crates.
    
    ## 4. Patch third-party crate build scripts that were not robust under
    Bazel's Windows MSVC build-script path
    
    Files:
    
    - `MODULE.bazel`
    - `patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch`
    - `patches/ring_windows_msvc_include_dirs.patch`
    - `patches/zstd-sys_windows_msvc_include_dirs.patch`
    
    What changed:
    
    - `aws-lc-sys`
    - Detects Bazel's Windows MSVC build-script runner via
    `RULES_RUST_BAZEL_BUILD_SCRIPT_RUNNER` or a `bazel-out` manifest-dir
    path.
    - Uses `clang-cl` for Bazel Windows MSVC builds when no explicit
    `CC`/`CXX` is set.
    - Allows prebuilt NASM on the Bazel Windows MSVC path even when `nasm`
    is not available directly in the runner environment.
    - Avoids canonicalizing `CARGO_MANIFEST_DIR` in the Bazel Windows MSVC
    case, because that path may point into Bazel output/runfiles state where
    preserving the given path is more reliable than forcing a local
    filesystem canonicalization.
    - `ring`
    - Under the Bazel Windows MSVC build-script runner, copies the
    pregenerated source tree into `OUT_DIR` and uses that as the
    generated-source root.
    - Adds include paths needed by MSVC compilation for
    Fiat/curve25519/P-256 generated headers.
    - Rewrites a few relative includes in C sources so the added include
    directories are sufficient.
    - `zstd-sys`
    - Adds MSVC-only include directories for `compress`, `decompress`, and
    feature-gated dictionary/legacy/seekable sources.
    - Skips `-fvisibility=hidden` on MSVC targets, where that
    GCC/Clang-style flag is not the right mechanism.
    
    Why this helps:
    
    - After the `rules_rust` plumbing started running build scripts on the
    Windows MSVC exec path, some third-party crates still failed for
    crate-local reasons: wrong compiler choice, missing include directories,
    build-script assumptions about manifest paths, or Unix-only C compiler
    flags.
    - These crate patches address those crate-local assumptions so the
    larger toolchain change can actually reach first-party Rust test
    execution.
    
    ## 5. Keep the only `.rs` test changes to Bazel/Cargo runfiles parity
    
    Files:
    
    - `codex-rs/tui/src/chatwidget/tests.rs`
    - `codex-rs/tui/tests/manager_dependency_regression.rs`
    
    What changed:
    
    - Instead of asking `find_resource!` for a directory runfile like
    `src/chatwidget/snapshots` or `src`, these tests now resolve one known
    file runfile first and then walk to its parent directory.
    
    Why this helps:
    
    - Bazel runfiles are more reliable for explicitly declared files than
    for source-tree directories that happen to exist in a Cargo checkout.
    - This keeps the tests working under both Cargo and Bazel without
    changing their actual assertions.
    
    # What we tried before landing on this shape, and why those attempts did
    not work
    
    ## Attempt 1: Force `--host_platform=//:local_windows_msvc` for all
    Windows Bazel jobs
    
    This did make the previously incompatible test targets show up during
    analysis, but it also pushed the Bazel clippy job and some unrelated
    build actions onto the MSVC exec path.
    
    Why that was bad:
    
    - Windows clippy started running third-party Cargo build scripts with
    Bazel's MSVC exec settings and crashed in crates such as `tree-sitter`
    and `libsqlite3-sys`.
    - That was a regression in a job that was previously giving useful
    gnullvm-targeted lint signal.
    
    What this PR does instead:
    
    - The wrapper flag is opt-in, and `bazel.yml` uses it only for the
    Windows `bazel test` lane.
    - The clippy lane stays on the default Windows gnullvm host/exec
    configuration.
    
    ## Attempt 2: Broaden the `rules_rust` linker override to all Windows
    Rust actions
    
    This fixed the MSVC test-lane failure where normal `rust_test` targets
    were linked through `clang++` with MSVC-style arguments, but it broke
    the default gnullvm path.
    
    Why that was bad:
    
    -
    `@@rules_rs++rules_rust+rules_rust//util/process_wrapper:process_wrapper`
    on the gnullvm exec platform started linking with `lld-link.exe` and
    then failed to resolve MinGW-style libraries such as `-lkernel32`,
    `-luser32`, and `-lmingw32`.
    
    What this PR does instead:
    
    - The linker override is restricted to Windows MSVC targets only.
    - The gnullvm path keeps its original linker behavior, while MSVC uses
    the direct Windows linker.
    
    ## Attempt 3: Keep everything on pure Windows gnullvm and patch the V8 /
    Python incompatibility chain instead
    
    This would have preserved a single Windows ABI everywhere, but it is a
    much larger project than this PR.
    
    Why that was not the practical first step:
    
    - The original incompatibility chain ran through exec-side generators
    and helper tools, not only through crate code.
    - `third_party/v8` is already special-cased on Windows gnullvm because
    `rusty_v8` only publishes Windows prebuilts under MSVC names.
    - Fixing that path likely means deeper changes in
    V8/rules_python/rules_rust toolchain resolution and generator execution,
    not just one local CI flag.
    
    What this PR does instead:
    
    - Keep gnullvm for the target cfgs we want to exercise.
    - Move only the Windows test lane's host/exec platform to MSVC, then
    patch the build-script/linker boundary enough for that split
    configuration to work.
    
    ## Attempt 4: Validate compatibility with `bazel test --nobuild ...`
    
    This turned out to be a misleading local validation command.
    
    Why:
    
    - `bazel test --nobuild ...` can successfully analyze targets and then
    still exit 1 with "Couldn't start the build. Unable to run tests"
    because there are no runnable test actions after `--nobuild`.
    
    Better local check:
    
    ```powershell
    bazel build --nobuild --keep_going --host_platform=//:local_windows_msvc //codex-rs/login:login-unit-tests //codex-rs/core:core-unit-tests //codex-rs/core:core-all-test
    ```
    
    # Which patches probably deserve upstream follow-up
    
    My rough take is that the `rules_rs` / `rules_rust` patches are the
    highest-value upstream candidates, because they are fixing generic
    Windows host/exec + MSVC direct-linker behavior rather than
    Codex-specific test logic.
    
    Strong upstream candidates:
    
    - `patches/rules_rs_windows_exec_linker.patch`
    - `patches/rules_rust_windows_bootstrap_process_wrapper_linker.patch`
    - `patches/rules_rust_windows_build_script_runner_paths.patch`
    - `patches/rules_rust_windows_exec_msvc_build_script_env.patch`
    - `patches/rules_rust_windows_msvc_direct_link_args.patch`
    - `patches/rules_rust_windows_process_wrapper_skip_temp_outputs.patch`
    
    Why these seem upstreamable:
    
    - They address general-purpose problems in the Windows MSVC exec path:
      - missing direct-linker exposure for Rust toolchains
      - wrong linker selection when rustc emits MSVC-style args
    - Windows path normalization/short-path issues in the build-script
    runner
      - forwarding GNU-flavored CC/link flags into MSVC Cargo build scripts
      - unstable temp outputs polluting process-wrapper search-path state
    
    Potentially upstreamable crate patches, but likely with more care:
    
    - `patches/zstd-sys_windows_msvc_include_dirs.patch`
    - `patches/ring_windows_msvc_include_dirs.patch`
    - `patches/aws-lc-sys_windows_msvc_prebuilt_nasm.patch`
    
    Notes on those:
    
    - The `zstd-sys` and `ring` include-path fixes look fairly generic for
    MSVC/Bazel build-script environments and may be straightforward to
    propose upstream after we confirm CI stability.
    - The `aws-lc-sys` patch is useful, but it includes a Bazel-specific
    environment probe and CI-specific compiler fallback behavior. That
    probably needs a cleaner upstream-facing shape before sending it out, so
    upstream maintainers are not forced to adopt Codex's exact CI
    assumptions.
    
    Probably not worth upstreaming as-is:
    
    - The repo-local Starlark/test target changes in `defs.bzl`,
    `codex-rs/*/BUILD.bazel`, and `.github/scripts/run-bazel-ci.sh` are
    mostly Codex-specific policy and CI wiring, not generic rules changes.
    
    # Validation notes for reviewers
    
    On this branch, I ran the following local checks after dropping the
    non-resource-loading Rust edits:
    
    ```powershell
    cargo test -p codex-tui
    just --shell 'C:\Program Files\Git\bin\bash.exe' --shell-arg -lc -- fix -p codex-tui
    python .\tools\argument-comment-lint\run-prebuilt-linter.py -p codex-tui
    just --shell 'C:\Program Files\Git\bin\bash.exe' --shell-arg -lc fmt
    ```
    
    One local caveat:
    
    - `just argument-comment-lint` still fails on this Windows machine for
    an unrelated Bazel toolchain-resolution issue in
    `//codex-rs/exec:exec-all-test`, so I used the direct prebuilt linter
    for `codex-tui` as the local fallback.
    
    # Expected reviewer takeaway
    
    If this PR goes green, the important conclusion is that the Windows
    Bazel test coverage gap was primarily a Bazel host/exec toolchain
    problem, not a need to make the Rust tests themselves Windows-specific.
    That would be a strong signal that the deleted non-resource-loading Rust
    test edits from the earlier branch should stay out, and that future work
    should focus on upstreaming the generic `rules_rs` / `rules_rust`
    Windows fixes and reducing the crate-local patch surface.
  • ci: upload compact Bazel execution logs for bazel.yml (#16577)
    ## Why
    
    The main Bazel CI lanes need compact execution logs to investigate cache
    misses and unexpected rebuilds, but local users of the shared wrapper
    should not pay that log-generation cost by default.
    
    ## What Changed
    
    -
    [`.github/scripts/run-bazel-ci.sh`](https://github.com/openai/codex/blob/a6ec239a24fd21507bb75a28f17277653f52e3a2/.github/scripts/run-bazel-ci.sh#L149-L153)
    now appends `--execution_log_compact_file=...` only when
    `CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR` is set; the caller owns creating
    that directory.
    -
    [`.github/workflows/bazel.yml`](https://github.com/openai/codex/blob/a6ec239a24fd21507bb75a28f17277653f52e3a2/.github/workflows/bazel.yml#L66-L174)
    enables that env var only for the main `test` and `clippy` jobs, creates
    the temp log directory in each job, and uploads the resulting `*.zst`
    files from `runner.temp`.
    
    ## Verification
    
    - `bash -n .github/scripts/run-bazel-ci.sh`
    - Parsed `.github/workflows/bazel.yml` as YAML.
    - Ran a local opt-in wrapper smoke test and confirmed it writes
    `execution-log-cquery-local-*.zst` when the caller pre-creates
    `CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR`.
  • ci: stop running rust CI with --all-features (#16473)
    ## Why
    
    Now that workspace crate features have been removed and
    `.github/scripts/verify_cargo_workspace_manifests.py` hard-bans new
    ones, Rust CI should stop building and testing with `--all-features`.
    
    Keeping `--all-features` in CI no longer buys us meaningful coverage for
    `codex-rs`, but it still makes the workflow look like we rely on Cargo
    feature permutations that we are explicitly trying to eliminate. It also
    leaves stale examples in the repo that suggest `--all-features` is a
    normal or recommended way to run the workspace.
    
    ## What changed
    
    - removed `--all-features` from the Rust CI `cargo chef cook`, `cargo
    clippy`, and `cargo nextest` invocations in
    `.github/workflows/rust-ci-full.yml`
    - updated the `just test` guidance in `justfile` to reflect that
    workspace crate features are banned and there should be no need to add
    `--all-features`
    - updated the multiline command example and snapshot in
    `codex-rs/tui/src/history_cell.rs` to stop rendering `cargo test
    --all-features --quiet`
    - tightened the verifier docstring in
    `.github/scripts/verify_cargo_workspace_manifests.py` so it no longer
    talks about temporary remaining exceptions
    
    ## How tested
    
    - `python3 .github/scripts/verify_cargo_workspace_manifests.py`
    - `cargo test -p codex-tui`
  • otel: remove the last workspace crate feature (#16469)
    ## Why
    
    `codex-otel` still carried `disable-default-metrics-exporter`, which was
    the last remaining workspace crate feature.
    
    We are removing workspace crate features because they do not fit our
    current build model well:
    
    - our Bazel setup does not honor crate features today, which can let
    feature-gated issues go unnoticed
    - they create extra crate build permutations that we want to avoid
    
    For this case, the feature was only being used to keep the built-in
    Statsig metrics exporter off in test and debug-oriented contexts. This
    repo already treats `debug_assertions` as the practical proxy for that
    class of behavior, so OTEL should follow the same convention instead of
    keeping a dedicated crate feature alive.
    
    ## What changed
    
    - removed `disable-default-metrics-exporter` from
    `codex-rs/otel/Cargo.toml`
    - removed the `codex-otel` dev-dependency feature activation from
    `codex-rs/core/Cargo.toml`
    - changed `codex-rs/otel/src/config.rs` so the built-in
    `OtelExporter::Statsig` default resolves to `None` when
    `debug_assertions` is enabled, with a focused unit test covering that
    behavior
    - removed the final feature exceptions from
    `.github/scripts/verify_cargo_workspace_manifests.py`, so workspace
    crate features are now hard-banned instead of temporarily allowlisted
    - expanded the verifier error message to explain the Bazel mismatch and
    build-permutation cost behind that policy
    
    ## How tested
    
    - `python3 .github/scripts/verify_cargo_workspace_manifests.py`
    - `cargo test -p codex-otel`
    - `cargo test -p codex-core
    metrics_exporter_defaults_to_statsig_when_missing`
    - `cargo test -p codex-app-server app_server_default_analytics_`
    - `just bazel-lock-check`
  • tui: remove the voice-input crate feature (#16467)
    ## Why
    
    `voice-input` is the only remaining TUI crate feature, but it is also a
    default feature and nothing in the workspace selects it explicitly. In
    practice it is just acting as a proxy for platform support, which is
    better expressed with target-specific dependencies and cfgs.
    
    ## What changed
    
    - remove the `voice-input` feature from `codex-tui`
    - make `cpal` a normal non-Linux target dependency
    - replace the feature-based voice and audio cfgs with pure
    Linux-vs-non-Linux cfgs
    - shrink the workspace-manifest verifier allowlist to remove the
    remaining `codex-tui` exception
    
    ## How tested
    
    - `python3 .github/scripts/verify_cargo_workspace_manifests.py`
    - `cargo test -p codex-tui`
    - `just bazel-lock-check`
    - `just argument-comment-lint -p codex-tui`
  • tui: remove debug/test-only crate features (#16457)
    ## Why
    
    The remaining `vt100-tests` and `debug-logs` features in `codex-tui`
    were only gating test-only and debug-only behavior. Those feature
    toggles add Cargo and Bazel permutations without buying anything, and
    they make it easier for more crate features to linger in the workspace.
    
    ## What changed
    
    - delete `vt100-tests` and `debug-logs` from `codex-tui`
    - always compile the VT100 integration tests in the TUI test target
    instead of hiding them behind a Cargo feature
    - remove the unused textarea debug logging branch instead of replacing
    it with another gate
    - add the required argument-comment annotations in the VT100 tests now
    that Bazel sees those callsites during linting
    - shrink the manifest verifier allowlist again so only the remaining
    real feature exceptions stay permitted
    
    ## How tested
    
    - `cargo test -p codex-tui`
    - `just argument-comment-lint -p codex-tui`
  • cloud-tasks: split the mock client out of cloud-tasks-client (#16456)
    ## Why
    
    `codex-cloud-tasks-client` was mixing two different roles: the real HTTP
    client and the mock implementation used by tests and local mock mode.
    Keeping both in the same crate forced Cargo feature toggles and Bazel
    `crate_features` just to pick an implementation.
    
    This change keeps `codex-cloud-tasks-client` focused on the shared API
    surface and real backend client, and moves the mock implementation into
    its own crate so we can remove those feature permutations cleanly.
    
    ## What changed
    
    - add a new `codex-cloud-tasks-mock-client` crate that owns `MockClient`
    - remove the `mock` and `online` features from
    `codex-cloud-tasks-client`
    - make `codex-cloud-tasks-client` unconditionally depend on
    `codex-backend-client` and export `HttpClient` directly
    - gate the mock-mode path in `codex-cloud-tasks` behind
    `#[cfg(debug_assertions)]`, so release builds always initialize the real
    HTTP client
    - update `codex-cloud-tasks` and its tests to use
    `codex-cloud-tasks-mock-client::MockClient` wherever mock behavior is
    needed
    - remove the matching Bazel `crate_features` override and shrink the
    manifest verifier allowlist accordingly
    
    ## How tested
    
    - `cargo test -p codex-cloud-tasks-client`
    - `cargo test -p codex-cloud-tasks-mock-client`
    - `cargo test -p codex-cloud-tasks`
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16456).
    * #16457
    * __->__ #16456
  • ci: block new workspace crate features (#16455)
    ## Why
    
    We already enforce workspace metadata and lint inheritance for
    `codex-rs` manifests, but we still allow new crate features to slip into
    the workspace. That makes it too easy to add more Cargo-only feature
    permutations while we are trying to eliminate them.
    
    ## What changed
    
    - extend `verify_cargo_workspace_manifests.py` to reject new
    `[features]` tables in workspace crates
    - reject new optional dependencies that create implicit crate features
    - reject new workspace-to-workspace `features = [...]` activations and
    `default-features = false`
    - add a narrow temporary allowlist for the existing feature-bearing
    manifests and internal feature activations
    - make the allowlist self-shrinking so a follow-up removal has to delete
    its corresponding exception
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16455).
    * #16457
    * #16456
    * __->__ #16455
  • ci: sync Bazel clippy lints and fix uncovered violations (#16351)
    ## Why
    
    Follow-up to #16345, the Bazel clippy rollout in #15955, and the cleanup
    pass in #16353.
    
    `cargo clippy` was enforcing the workspace deny-list from
    `codex-rs/Cargo.toml` because the member crates opt into `[lints]
    workspace = true`, but Bazel clippy was only using `rules_rust` plus
    `clippy.toml`. That left the Bazel lane vulnerable to drift:
    `clippy.toml` can tune lint behavior, but it cannot set
    allow/warn/deny/forbid levels.
    
    This PR now closes both sides of the follow-up. It keeps `.bazelrc` in
    sync with `[workspace.lints.clippy]`, and it fixes the real clippy
    violations that the newly-synced Windows Bazel lane surfaced once that
    deny-list started matching Cargo.
    
    ## What Changed
    
    - added `.github/scripts/verify_bazel_clippy_lints.py`, a Python check
    that parses `codex-rs/Cargo.toml` with `tomllib`, reads the Bazel
    `build:clippy` `clippy_flag` entries from `.bazelrc`, and reports
    missing, extra, or mismatched lint levels
    - ran that verifier from the lightweight `ci.yml` workflow so the sync
    check does not depend on a Rust toolchain being installed first
    - expanded the `.bazelrc` comment to explain the Cargo `workspace =
    true` linkage and why Bazel needs the deny-list duplicated explicitly
    - fixed the Windows-only `codex-windows-sandbox` violations that Bazel
    clippy reported after the sync, using the same style as #16353: inline
    `format!` args, method references instead of trivial closures, removed
    redundant clones, and replaced SID conversion `unwrap` and `expect`
    calls with proper errors
    - cleaned up the remaining cross-platform violations the Bazel lane
    exposed in `codex-backend-client` and `core_test_support`
    
    ## Testing
    
    Key new test introduced by this PR:
    
    `python3 .github/scripts/verify_bazel_clippy_lints.py`