Commit Graph
4967 Commits
Author SHA1 Message Date
Friel 8cf3da357b ci: extend bazel watchdog timer timeout 2026-03-30 13:49:33 +00:00
Friel c5475b2354 ci: bump linux arglint prebuilt timeout 2026-03-30 12:56:00 +00:00
Friel dfdee7d6cb ci: extend watchdog timer and subagent behavior timeouts 2026-03-30 11:03:33 +00:00
Friel 9f0916586d ci: extend watchdog timer workflow timeouts 2026-03-30 10:03:34 +00:00
Friel 79d73b4a5c ci: extend watchdog timer branch workflow timeouts 2026-03-30 09:12:31 +00:00
Friel 484eb1ebfd ci: bump workflow timeouts 2026-03-30 08:45:49 +00:00
Friel 45bf65d007 Render watchdog countdown in subagent panel 2026-03-29 21:11:31 +00:00
FrielandCodex a2f37d5548 fix(tui): preserve watchdog behavior on refreshed base
Resolve the remaining TUI-side merge drift after restacking the watchdog and subagent behavior branch onto the refreshed TUI foundation branch.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 23:09:20 -07:00
Friel 65db8195a5 test(nextest): extend schema fixture timeout on windows 2026-03-28 23:09:20 -07:00
Friel 86fe4f6be4 test(app-server): stabilize thread unsubscribe on slow runners 2026-03-28 23:09:20 -07:00
Friel 3bd69accc1 fix(tui): render live agent inbox notifications 2026-03-28 23:08:51 -07:00
Friel b8be51fe7c fix(tui): annotate subagent panel test literals 2026-03-28 19:24:31 -07:00
Friel 0b72153645 fix(tui): annotate subagent panel render literals 2026-03-28 18:54:46 -07:00
Friel 510d5679a9 fix(tui): annotate subagent panel truncation literal 2026-03-28 18:43:02 -07:00
Friel 48b7f72829 fix(tui): drop stale voice transcription init on current main 2026-03-28 18:34:11 -07:00
Friel fc7a5e3d0f fix(tui): restore subagent panel wiring on app-server TUI 2026-03-28 18:28:25 -07:00
Friel 90d339cf75 fix(tui): mount subagent panel independently of active cell 2026-03-28 18:24:50 -07:00
Friel 0af3f1f66e fix(tui): keep subagent panel out of transcript history 2026-03-28 18:24:50 -07:00
Friel 4ef8493fd2 test(tui): annotate subagent panel literals 2026-03-28 18:24:50 -07:00
Friel 5e41296824 fix(tui): format multi-agent status helper 2026-03-28 18:24:50 -07:00
Friel 3cfdc99ecc fix(tui): annotate watchdog panel truncation literals 2026-03-28 18:24:50 -07:00
FrielandCodex 77c69e35b7 fix(tui): adapt collab foundation to refreshed main
Preserve the collab transcript fixtures and current TUI style rules after rebasing onto the refreshed tui_app_server codebase.

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 18:24:49 -07:00
Friel ed0cff78a6 feat(tui): add subagent inbox foundation
Preserve the subagent inbox foundation behavior on the current origin/main base and collapse the branch back to a single commit for easier future restacks.
2026-03-28 18:24:49 -07:00
Eric Traut 3bbc1ce003 Remove TUI voice transcription feature (#16114)
Removes the partially-completed TUI composer voice transcription flow,
including its feature flag, app events, and hold-to-talk state machine.
2026-03-29 00:20:25 +00:00
Michael Bolin 4e119a3b38 codex-tools: extract local host tool specs (#16138)
## Why

`core/src/tools/spec.rs` still bundled a set of pure local-host tool
builders with the orchestration that actually decides when those tools
are exposed and which handlers back them. That made `codex-core`
responsible for JSON/tool-shape construction that does not depend on
session state, and it kept the `codex-tools` migration from taking a
meaningfully larger bite out of `spec.rs`.

This PR moves that reusable spec-building layer into `codex-tools` while
leaving feature gating, handler registration, and runtime-coupled
descriptions in `codex-core`.

## What changed

- added `codex-rs/tools/src/local_tool.rs` for the pure builders for
`exec_command`, `write_stdin`, `shell`, `shell_command`, and
`request_permissions`
- added `codex-rs/tools/src/view_image.rs` for the `view_image` tool
spec and output schema so the extracted modules stay right-sized
- rewired `codex-rs/core/src/tools/spec.rs` to call those extracted
builders instead of constructing these specs inline
- kept the `request_permissions` description source in `codex-core`,
with `codex-tools` taking the description as input so the crate boundary
does not grow a dependency on handler/runtime code
- moved the direct constructor coverage for this slice from
`codex-rs/core/src/tools/spec_tests.rs` into
`codex-rs/tools/src/local_tool_tests.rs` and
`codex-rs/tools/src/view_image_tests.rs`
- updated `codex-rs/tools/README.md` to reflect that `codex-tools` now
owns this local-host spec layer

## Test plan

- `CARGO_TARGET_DIR=/tmp/codex-tools-local-host cargo test -p
codex-tools`
- `CARGO_TARGET_DIR=/tmp/codex-core-local-tools cargo test -p codex-core
--lib tools::spec::`
- `just argument-comment-lint`

## References

- #15923
- #15928
- #15944
- #15953
- #16031
- #16047
- #16129
- #16132
2026-03-28 16:33:58 -07:00
Eric Traut 46b653e73c Fix skills picker scrolling in tui app server (#16109)
Fixes #16091.

The app-server TUI was truncating the filtered mention candidate list to
`MAX_POPUP_ROWS`, so the `$` skills picker only exposed the first 8
matches. That made it look like many skills were missing and prevented
keyboard navigation beyond the first page, even though direct
`$skill-name` insertion still worked.

Testing: I manually verified the regression and confirmed the fix.
2026-03-28 17:22:25 -06:00
Michael Bolin f7ef9599ed exec: make review-policy tests hermetic (#16137)
## Why

`thread_start_params_from_config()` is supposed to forward the effective
`approvals_reviewer` into the app-server request, but these tests were
constructing that config through `ConfigBuilder::build()`, which also
loads ambient system and managed config layers. On machines with an
admin or host-level reviewer override, the manual-only case could
inherit `guardian_subagent` and fail even though the exec-side mapping
was correct.

## What changed

- Set `approvals_reviewer` explicitly via `harness_overrides` in the two
`thread_start_params_*review_policy*` tests in
`codex-rs/exec/src/lib.rs`.
- Removed the dependence on default config resolution and temp
`config.toml` writes so the tests exercise only the reviewer-to-request
mapping in `codex-exec`.

## Testing

- `cargo test -p codex-exec`
2026-03-28 23:01:04 +00:00
Michael Bolin a16a9109d7 ci: use BuildBuddy for rust-ci-full non-Windows argument-comment-lint (#16136)
## Why

PR #16130 fixed the Windows `argument-comment-lint` regression in
`rust-ci-full`, but the next `main` runs still left the Linux and macOS
lint legs timing out.

In [run
23695263729](https://github.com/openai/codex/actions/runs/23695263729),
both non-Windows `argument-comment-lint` jobs were cancelled almost
exactly 30 minutes after they started. The remaining workflow difference
versus `rust-ci.yml` was that `rust-ci-full` did not pass
`BUILDBUDDY_API_KEY` into the non-Windows Bazel lint step, so
`run-bazel-ci.sh` fell back to local Bazel configuration instead of
using the faster remote-backed path available on `main`.

## What changed

- passed `BUILDBUDDY_API_KEY` to the non-Windows `rust-ci-full`
`argument-comment-lint` Bazel step
- left the Windows packaged-wrapper path from #16130 unchanged
- kept the change scoped to `rust-ci-full.yml`

## Test plan

- loaded `.github/workflows/rust-ci-full.yml` and
`.github/workflows/rust-ci.yml` with `python3` + `yaml.safe_load(...)`
- inspected run `23695263729` and confirmed `Argument comment lint -
Linux` and `Argument comment lint - macOS` were cancelled about 30
minutes after start
- verified the updated `rust-ci-full` step now matches the non-Windows
secret wiring already present in `rust-ci.yml`

## References

- #16130
- #16106
2026-03-28 15:36:01 -07:00
Michael Bolin 2238c16a91 codex-tools: extract code mode tool spec adapters (#16132)
## Why

The longer-term `codex-tools` migration is to move pure tool-definition
and tool-spec plumbing out of `codex-core` while leaving session- and
runtime-coupled orchestration behind.

The remaining code-mode adapter layer in
`core/src/tools/code_mode_description.rs` was a good next extraction
seam because it only transformed `ToolSpec` values for code mode and
already delegated the low-level description rendering to
`codex-code-mode`.

## What Changed

- added `codex-rs/tools/src/code_mode.rs` with
`augment_tool_spec_for_code_mode()` and
`tool_spec_to_code_mode_tool_definition()`
- added focused unit coverage in `codex-rs/tools/src/code_mode_tests.rs`
- rewired `core/src/tools/spec.rs` and `core/src/tools/code_mode/mod.rs`
to use the extracted adapters from `codex-tools`
- removed the old `core/src/tools/code_mode_description.rs` shim and its
test file from `codex-core`
- added the `codex-code-mode` dependency to `codex-tools`, updated
`Cargo.lock`, and refreshed the `codex-tools` README to reflect the
expanded boundary

## Test Plan

- `cargo test -p codex-tools`
- `CARGO_TARGET_DIR=/tmp/codex-core-code-mode-adapters cargo test -p
codex-core --lib tools::spec::`
- `CARGO_TARGET_DIR=/tmp/codex-core-code-mode-adapters cargo test -p
codex-core --lib tools::code_mode::`
- `just bazel-lock-update`
- `just bazel-lock-check`
- `just argument-comment-lint`

## References

- #15923
- #15928
- #15944
- #15953
- #16031
- #16047
- #16129
2026-03-28 15:32:35 -07:00
Michael Bolin c25c0d6e9e core: fix stale curated plugin cache refresh races (#16126)
## Why

The `plugin/list` force-sync path can race app-server startup's curated
plugin cache refresh.

Startup was capturing the configured curated plugin IDs from the initial
config snapshot. If `plugin/list` with `forceRemoteSync` removed curated
plugin entries from `config.toml` while that background refresh was
still in flight, the startup task could recreate cache directories for
plugins that had just been uninstalled.

That leaves the `plugin/list` response logically correct but the on-disk
cache stale, which matches the flaky Ubuntu arm failure seen in
`codex-app-server::all
suite::v2::plugin_list::plugin_list_force_remote_sync_reconciles_curated_plugin_state`
while validating [#16047](https://github.com/openai/codex/pull/16047).

## What

- change `codex-rs/core/src/plugins/manager.rs` so startup curated-repo
refresh rereads the current user `config.toml` before deciding which
curated plugin cache entries to refresh
- factor the configured-plugin parsing so the same logic can be reused
from either the config layer stack or the persisted user config value
- add a regression test that verifies curated plugin IDs are read from
the latest user config state before cache refresh runs

## Testing

- `cargo test -p codex-core
configured_curated_plugin_ids_from_codex_home_reads_latest_user_config
-- --nocapture`
- `cargo test -p codex-app-server
suite::v2::plugin_list::plugin_list_force_remote_sync_reconciles_curated_plugin_state
-- --nocapture`
- `just argument-comment-lint`
2026-03-28 15:00:39 -07:00
Michael Bolin 313fb95989 ci: keep rust-ci-full Windows argument-comment-lint on packaged wrapper (#16130)
## Why

PR #16106 switched `rust-ci-full` over to the native Bazel-backed
`argument-comment-lint` path on all three platforms.

That works on Linux and macOS, but the Windows leg in `rust-ci-full` now
fails before linting starts: Bazel dies while building `rules_rust`'s
`process_wrapper` tool, so `main` reports an `argument-comment-lint`
failure even though no Rust lint finding was produced.

Until native Windows Bazel linting is repaired, `rust-ci-full` should
keep the same Windows split that `rust-ci.yml` already uses.

## What changed

- restored the Windows-only nightly `argument-comment-lint` toolchain
setup in `rust-ci-full`
- limited the Bazel-backed lint step in `rust-ci-full` to non-Windows
runners
- routed the Windows runner back through
`tools/argument-comment-lint/run-prebuilt-linter.py`
- left the Linux and macOS `rust-ci-full` behavior unchanged

## Test plan

- loaded `.github/workflows/rust-ci-full.yml` and
`.github/workflows/rust-ci.yml` with `python3` + `yaml.safe_load(...)`
- inspected failing Actions run `23692864849`, especially job
`69023229311`, to confirm the Windows failure occurs in Bazel
`process_wrapper` setup before lint output is emitted

## References

- #16106
2026-03-28 14:50:19 -07:00
Michael Bolin 4e27a87ec6 codex-tools: extract configured tool specs (#16129)
## Why

This continues the `codex-tools` migration by moving another passive
tool-spec layer out of `codex-core`.

After `ToolSpec` moved into `codex-tools`, `codex-core` still owned
`ConfiguredToolSpec` and `create_tools_json_for_responses_api()`. Both
are data-model and serialization helpers rather than runtime
orchestration, so keeping them in `core/src/tools/registry.rs` and
`core/src/tools/spec.rs` left passive tool-definition code coupled to
`codex-core` longer than necessary.

## What changed

- moved `ConfiguredToolSpec` into `codex-rs/tools/src/tool_spec.rs`
- moved `create_tools_json_for_responses_api()` into
`codex-rs/tools/src/tool_spec.rs`
- re-exported the new surface from `codex-rs/tools/src/lib.rs`, which
remains exports-only
- updated `core/src/client.rs`, `core/src/tools/registry.rs`, and
`core/src/tools/router.rs` to consume the extracted types and serializer
from `codex-tools`
- moved the tool-list serialization test into
`codex-rs/tools/src/tool_spec_tests.rs`
- added focused unit coverage for `ConfiguredToolSpec::name()`
- simplified `core/src/tools/spec_tests.rs` to use the extracted
`ConfiguredToolSpec::name()` directly and removed the now-redundant
local `tool_name()` helper
- updated `codex-rs/tools/README.md` so the crate boundary reflects the
newly extracted tool-spec wrapper and serialization helper

## Test plan

- `cargo test -p codex-tools`
- `CARGO_TARGET_DIR=/tmp/codex-core-configured-spec cargo test -p
codex-core --lib tools::spec::`
- `CARGO_TARGET_DIR=/tmp/codex-core-configured-spec cargo test -p
codex-core --lib client::`
- `just fix -p codex-tools -p codex-core`
- `just argument-comment-lint`

## References

- #15923
- #15928
- #15944
- #15953
- #16031
- #16047
2026-03-28 14:24:14 -07:00
Michael Bolin ae8a3be958 bazel: refresh the expired macOS SDK pin (#16128)
## Why

macOS BuildBuddy started failing before target analysis because the
Apple CDN object pinned in
[`MODULE.bazel`](https://github.com/openai/codex/blob/fce0f76d577b5070f1e2b4a2abaa8350acfc38ff/MODULE.bazel#L28-L36)
now returns `403 Forbidden`. The failure report that triggered this
change was this [BuildBuddy
invocation](https://app.buildbuddy.io/invocation/c57590e0-1bdb-4e19-a86f-74d4a7ded228).

This repo uses `@llvm//extensions:osx.bzl` via `osx.from_archive(...)`,
and that API does not discover a current SDK URL for us. It fetches
exactly the `urls`, `sha256`, and `strip_prefix` we pin. Once Apple
retires that `swcdn.apple.com` object, `@macos_sdk` stops resolving and
every downstream macOS build fails during external repository fetch.

This is the same basic failure mode we hit in
[b9fa08ec61](https://github.com/openai/codex/commit/b9fa08ec619c96617a9ae2041c9ddb02d2c02434):
the pin itself aged out.

## How I tracked it down

1. I started from the BuildBuddy error and copied the exact
`swcdn.apple.com/.../CLTools_macOSNMOS_SDK.pkg` URL from the failure.
2. I reproduced the issue outside CI by opening that URL directly in a
browser and by running `curl -I` against it locally. Both returned `403
Forbidden`, which ruled out BuildBuddy as the root cause.
3. I searched the repo for that URL and found it hardcoded in
`MODULE.bazel`.
4. I inspected the `llvm` Bzlmod `osx` extension implementation to
confirm that `osx.from_archive(...)` is just a literal fetch of the
pinned archive metadata. There is no automatic fallback or catalog
lookup behind it.
5. I queried Apple's software update catalogs to find the current
Command Line Tools package for macOS 26.x. The useful catalog was:
-
`https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz`

This is scriptable; it does not require opening a website in a browser.
The catalog is a gzip-compressed plist served over HTTP, so the workflow
is just:

   1. fetch the catalog,
   2. decompress it,
   3. search or parse the plist for `CLTools_macOSNMOS_SDK.pkg` entries,
   4. inspect the matching product metadata.

   The quick shell version I used was:

   ```shell
   curl -L <catalog-url> \
     | gzip -dc \
     | rg -n -C 6 'CLTools_macOSNMOS_SDK\.pkg|PostDate|English\.dist'
   ```

That is enough to surface the current product id, package URL, post
date, and the matching `.dist` file. If we want something less
grep-driven next time, the same catalog can be parsed structurally. For
example:

   ```python
   import gzip
   import plistlib
   import urllib.request

url =
"https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz"
   with urllib.request.urlopen(url) as resp:
       catalog = plistlib.loads(gzip.decompress(resp.read()))

   for product_id, product in catalog["Products"].items():
       for package in product.get("Packages", []):
           package_url = package.get("URL", "")
           if package_url.endswith("CLTools_macOSNMOS_SDK.pkg"):
               print(product_id)
               print(product.get("PostDate"))
               print(package_url)
               print(product.get("Distributions", {}).get("English"))
   ```

In practice, `curl` was only the transport. The important part is that
the catalog itself is a machine-readable plist, so this can be
automated.
6. That catalog contains the newer `047-96692` Command Line Tools
release, and its distribution file identifies it as [Command Line Tools
for Xcode
26.4](https://swdist.apple.com/content/downloads/32/53/047-96692-A_OAHIHT53YB/ybtshxmrcju8m2qvw3w5elr4rajtg1x3y3/047-96692.English.dist).
7. I downloaded that package locally, computed its SHA-256, expanded it
with `pkgutil --expand-full`, and verified that it contains
`Payload/Library/Developer/CommandLineTools/SDKs/MacOSX26.4.sdk`, which
is the correct new `strip_prefix` for this pin.

The core debugging loop looked like this:

```shell
curl -I <stale swcdn URL>
rg 'swcdn\.apple\.com|osx\.from_archive' MODULE.bazel
curl -L <apple 26.x sucatalog> | gzip -dc | rg 'CLTools_macOSNMOS_SDK.pkg'
pkgutil --expand-full CLTools_macOSNMOS_SDK.pkg expanded
find expanded/Payload/Library/Developer/CommandLineTools/SDKs -maxdepth 1 -mindepth 1
```

## What changed

- Updated `MODULE.bazel` to point `osx.from_archive(...)` at the
currently live `047-96692` `CLTools_macOSNMOS_SDK.pkg` object.
- Updated the pinned `sha256` to match that package.
- Updated the `strip_prefix` from `MacOSX26.2.sdk` to `MacOSX26.4.sdk`.

## Verification

- `bazel --output_user_root="$(mktemp -d
/tmp/codex-bazel-sdk-fetch.XXXXXX)" build @macos_sdk//sysroot`

## Notes for next time

As long as we pin raw `swcdn.apple.com` objects, this will likely happen
again. When it does, the expected recovery path is:

1. Reproduce the `403` against the exact URL from CI.
2. Find the stale pin in `MODULE.bazel`.
3. Look up the current CLTools package in the relevant Apple software
update catalog for that macOS major version.
4. Download the replacement package and refresh both `sha256` and
`strip_prefix`.
5. Validate the new pin with a fresh `@macos_sdk` fetch, not just an
incremental Bazel build.

The important detail is that the non-`26` catalog did not surface the
macOS 26.x SDK package here; the `index-26-15-14-...` catalog was the
one that exposed the currently live replacement.
2026-03-28 21:08:19 +00:00
Michael Bolin bc53d42fd9 codex-tools: extract tool spec models (#16047)
## Why

This continues the `codex-tools` migration by moving another passive
tool-definition layer out of `codex-core`.

After `ResponsesApiTool` and the lower-level schema adapters moved into
`codex-tools`, `core/src/client_common.rs` was still owning `ToolSpec`
and the web-search request wire types even though they are serialized
data models rather than runtime orchestration. Keeping those types in
`codex-core` makes the crate boundary look smaller than it really is and
leaves non-runtime tool-shape code coupled to core.

## What changed

- moved `ToolSpec`, `ResponsesApiWebSearchFilters`, and
`ResponsesApiWebSearchUserLocation` into
`codex-rs/tools/src/tool_spec.rs`
- added focused unit tests in `codex-rs/tools/src/tool_spec_tests.rs`
for:
  - `ToolSpec::name()`
  - web-search config conversions
  - `ToolSpec` serialization for `web_search` and `tool_search`
- kept `codex-rs/tools/src/lib.rs` exports-only by re-exporting the new
module from `lib.rs`
- reduced `core/src/client_common.rs` to a compatibility shim that
re-exports the extracted tool-spec types for current core call sites
- updated `core/src/tools/spec_tests.rs` to consume the extracted
web-search types directly from `codex-tools`
- updated `codex-rs/tools/README.md` so the crate contract reflects that
`codex-tools` now owns the passive tool-spec request models in addition
to the lower-level Responses API structs

## Test plan

- `cargo test -p codex-tools`
- `cargo test -p codex-core --lib tools::spec::`
- `cargo test -p codex-core --lib client_common::`
- `just fix -p codex-tools -p codex-core`
- `just argument-comment-lint`

## References

- #15923
- #15928
- #15944
- #15953
- #16031
2026-03-28 13:37:00 -07:00
Eric Traut 178d2b00b1 Remove the codex-tui app-server originator workaround (#16116)
## Summary
- remove the temporary `codex-tui` special-case when setting the default
originator during app-server initialization
2026-03-28 13:53:33 -06:00
Eric Traut 48144a7fa4 Remove remaining custom prompt support (#16115)
## Summary
- remove protocol and core support for discovering and listing custom
prompts
- simplify the TUI slash-command flow and command popup to built-in
commands only
- delete obsolete custom prompt tests, helpers, and docs references
- clean up downstream event handling for the removed protocol events
2026-03-28 13:49:37 -06:00
Michael Bolin fce0f76d57 build: migrate argument-comment-lint to a native Bazel aspect (#16106)
## Why

`argument-comment-lint` had become a PR bottleneck because the repo-wide
lane was still effectively running a `cargo dylint`-style flow across
the workspace instead of reusing Bazel's Rust dependency graph. That
kept the lint enforced, but it threw away the main benefit of moving
this job under Bazel in the first place: metadata reuse and cacheable
per-target analysis in the same shape as Clippy.

This change moves the repo-wide lint onto a native Bazel Rust aspect so
Linux and macOS can lint `codex-rs` without rebuilding the world
crate-by-crate through the wrapper path.

## What Changed

- add a nightly Rust toolchain with `rustc-dev` for Bazel and a
dedicated crate-universe repo for `tools/argument-comment-lint`
- add `tools/argument-comment-lint/driver.rs` and
`tools/argument-comment-lint/lint_aspect.bzl` so Bazel can run the lint
as a custom `rustc_driver`
- switch repo-wide `just argument-comment-lint` and the Linux/macOS
`rust-ci` lanes to `bazel build --config=argument-comment-lint
//codex-rs/...`
- keep the Python/DotSlash wrappers as the package-scoped fallback path
and as the current Windows CI path
- gate the Dylint entrypoint behind a `bazel_native` feature so the
Bazel-native library avoids the `dylint_*` packaging stack
- update the aspect runtime environment so the driver can locate
`rustc_driver` correctly under remote execution
- keep the dedicated `tools/argument-comment-lint` package tests and
wrapper unit tests in CI so the source and packaged entrypoints remain
covered

## Verification

- `python3 -m unittest discover -s tools/argument-comment-lint -p
'test_*.py'`
- `cargo test` in `tools/argument-comment-lint`
- `bazel build
//tools/argument-comment-lint:argument-comment-lint-driver
--@rules_rust//rust/toolchain/channel=nightly`
- `bazel build --config=argument-comment-lint
//codex-rs/utils/path-utils:all`
- `bazel build --config=argument-comment-lint
//codex-rs/rollout:rollout`







---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16106).
* #16120
* __->__ #16106
2026-03-28 12:41:56 -07:00
Michael Bolin 65f631c3d6 fix: fix comment linter lint violations in Linux-only code (#16118)
https://github.com/openai/codex/pull/16071 took care of this for
Windows, so this takes care of things for Linux.

We don't touch the CI jobs in this PR because
https://github.com/openai/codex/pull/16106 is going to be the real fix
there (including a major speedup!).
2026-03-28 11:09:41 -07:00
Eric Traut 61429a6c10 Rename tui_app_server to tui (#16104)
This is a follow-up to https://github.com/openai/codex/pull/15922. That
previous PR deleted the old `tui` directory and left the new
`tui_app_server` directory in place. This PR renames `tui_app_server` to
`tui` and fixes up all references.
2026-03-28 11:23:07 -06:00
Eric Traut 3d1abf3f3d Update PR babysitter skill for review replies and resolution (#16112)
This PR updates the "PR Babysitter" skill to clarify that non-actionable
review comments should receive a direct reply explaining why no change
is needed, and actionable review comments should be marked "resolved"
after they are addressed.
2026-03-28 10:35:20 -06:00
Felipe CouryandEric Traut bede1d9e23 fix(tui): refresh footer on collaboration mode changes (#16026)
## Summary
- Moves status surface refresh (`refresh_status_surfaces` /
`refresh_status_line`) from `App` event handlers into `ChatWidget`
setters via a new `refresh_model_dependent_surfaces()` method
- Ensures model-dependent UI stays in sync whenever collaboration mode,
model, or reasoning effort changes, including the footer and terminal
title in both `tui` and `tui_app_server`
- Applies the fix to both `tui` and `tui_app_server` widgets

#15961

## Test plan
- [x] Added snapshot test
`status_line_model_with_reasoning_plan_mode_footer` verifying footer
renders correctly in plan mode
- [x] Added
`terminal_title_model_updates_on_model_change_without_manual_refresh` in
`tui_app_server`
- [ ] Verify switching collaboration modes updates the footer in real
TUI
- [ ] Verify model/reasoning effort changes reflect in the status bar
and terminal title

---------

Co-authored-by: Eric Traut <etraut@openai.com>
2026-03-28 08:55:32 -06:00
Michael Bolin e39ddc61b1 bazel: add Windows gnullvm stack flags to unit test binaries (#16074)
## Summary

Add the Windows gnullvm stack-reserve flags to the `*-unit-tests-bin`
path in `codex_rust_crate()`.

## Why

This is the narrow code fix behind the earlier review comment on
[#16067](https://github.com/openai/codex/pull/16067). That comment was
stale relative to the workflow-only PR it landed on, but it pointed at a
real gap in `defs.bzl`.

Today, `codex_rust_crate()` already appends
`WINDOWS_GNULLVM_RUSTC_STACK_FLAGS` for:

- `rust_binary()` targets
- integration-test `rust_test()` targets

But the unit-test binary path still omitted those flags. That meant the
generated `*-unit-tests-bin` executables were not built the same way as
the rest of the Windows gnullvm executables in the macro.

## What Changed

- Added `WINDOWS_GNULLVM_RUSTC_STACK_FLAGS` to the `unit_test_binary`
`rust_test()` rule in `defs.bzl`
- Added a short comment explaining why unit-test binaries need the same
stack-reserve treatment as binaries and integration tests on Windows
gnullvm

## Testing

- `bazel query '//codex-rs/core:*'`
- `bazel query '//codex-rs/shell-command:*'`

Those queries load packages that exercise `codex_rust_crate()`,
including `*-unit-tests-bin` targets. The actual runtime effect is
Windows-specific, so the real end-to-end confirmation still comes from
Windows CI.
2026-03-27 22:11:49 -07:00
Michael Bolin b94366441e ci: split fast PR Rust CI from full post-merge Cargo CI (#16072)
## Summary

Split the old all-in-one `rust-ci.yml` into:

- a PR-time Cargo workflow in `rust-ci.yml`
- a full post-merge Cargo workflow in `rust-ci-full.yml`

This keeps the PR path focused on fast Cargo-native hygiene plus the
Bazel `build` / `test` / `clippy` coverage in `bazel.yml`, while moving
the heavyweight Cargo-native matrix to `main`.

## Why

`bazel.yml` is now the main Rust verification workflow for pull
requests. It already covers the Bazel build, test, and clippy signal we
care about pre-merge, and it also runs on pushes to `main` to re-verify
the merged tree and help keep the BuildBuddy caches warm.

What was still missing was a clean split for the Cargo-native checks
that Bazel does not replace yet. The old `rust-ci.yml` mixed together:

- fast hygiene checks such as `cargo fmt --check` and `cargo shear`
- `argument-comment-lint`
- the full Cargo clippy / nextest / release-build matrix

That made every PR pay for the full Cargo matrix even though most of
that coverage is better treated as post-merge verification. The goal of
this change is to leave PRs with the checks we still want before merge,
while moving the heavier Cargo-native matrix off the review path.

## What Changed

- Renamed the old heavyweight workflow to `rust-ci-full.yml` and limited
it to `push` on `main` plus `workflow_dispatch`.
- Added a new PR-only `rust-ci.yml` that runs:
  - changed-path detection
  - `cargo fmt --check`
  - `cargo shear`
  - `argument-comment-lint` on Linux, macOS, and Windows
- `tools/argument-comment-lint` package tests when the lint itself or
its workflow wiring changes
- Kept the PR workflow's gatherer as the single required Cargo-native
status so branch protection can stay simple.
- Added `.github/workflows/README.md` to document the intended split
between `bazel.yml`, `rust-ci.yml`, and `rust-ci-full.yml`.
- Preserved the recent Windows `argument-comment-lint` behavior from
`e02fd6e1d3` in `rust-ci-full.yml`, and mirrored cross-platform lint
coverage into the PR workflow.

A few details are deliberate:

- The PR workflow still keeps the Linux lint lane on the
default-targets-only invocation for now, while macOS and Windows use the
broader released-linter path.
- This PR does not change `bazel.yml`; it changes the Cargo-native
workflow around the existing Bazel PR path.

## Testing

- Rebasing this change onto `main` after `e02fd6e1d3`
- `ruby -e 'require "yaml"; %w[.github/workflows/rust-ci.yml
.github/workflows/rust-ci-full.yml .github/workflows/bazel.yml].each {
|f| YAML.load_file(f) }'`
2026-03-27 21:08:08 -07:00
Michael Bolin e02fd6e1d3 fix: clean up remaining Windows argument-comment-lint violations (#16071)
## Why

The initial `argument-comment-lint` rollout left Windows on
default-target coverage because there were still Windows-only callsites
failing under `--all-targets`. This follow-up cleans up those remaining
Windows-specific violations so the Windows CI lane can enforce the same
stricter coverage, leaving Linux as the remaining platform-specific
follow-up.

## What changed

- switched the Windows `rust-ci` argument-comment-lint step back to the
default wrapper invocation so it runs full-target coverage again
- added the required `/*param_name*/` annotations at Windows-gated
literal callsites in:
  - `codex-rs/windows-sandbox-rs/src/lib.rs`
  - `codex-rs/windows-sandbox-rs/src/elevated_impl.rs`
  - `codex-rs/tui_app_server/src/multi_agents.rs`
  - `codex-rs/network-proxy/src/proxy.rs`

## Validation

- Windows `argument comment lint` CI on this PR
2026-03-27 20:48:21 -07:00
Michael Bolin f4d0cbfda6 ci: run Bazel clippy on Windows gnullvm (#16067)
## Why

We want more of the pre-merge Rust signal to come from `bazel.yml`,
especially on Windows. The Bazel test workflow already exercises
`x86_64-pc-windows-gnullvm`, but the Bazel clippy job still only ran on
Linux x64 and macOS arm64. That left a gap where Windows-only Bazel lint
breakages could slip through until the Cargo-based workflow ran.

This change keeps the fix narrow. Rather than expanding the Bazel clippy
target set or changing the shared setup logic, it extends the existing
clippy matrix to the same Windows GNU toolchain that the Bazel test job
already uses.

## What Changed

- add `windows-latest` / `x86_64-pc-windows-gnullvm` to the `clippy` job
matrix in `.github/workflows/bazel.yml`
- update the nearby workflow comment to explain that the goal is to get
Bazel-native Windows lint coverage on the same toolchain as the Bazel
test lane
- leave the Bazel clippy scope unchanged at `//codex-rs/...
-//codex-rs/v8-poc:all`

## Verification

- parsed `.github/workflows/bazel.yml` successfully with Ruby
`YAML.load_file`
2026-03-27 20:47:22 -07:00
Michael Bolin 343d1af3da bazel: enable the full Windows gnullvm CI path (#15952)
## Why

This PR is the current, consolidated follow-up to the earlier Windows
Bazel attempt in #11229. The goal is no longer just to get a tiny
Windows smoke job limping along: it is to make the ordinary Bazel CI
path usable on `windows-latest` for `x86_64-pc-windows-gnullvm`, with
the same broad `//...` test shape that macOS and Linux already use.

The earlier smoke-list version of this work was useful as a foothold,
but it was not a good long-term landing point. Windows Bazel kept
surfacing real issues outside that allowlist:

- GitHub's Windows runner exposed runfiles-manifest bugs such as
`FINDSTR: Cannot open D:MANIFEST`, which broke Bazel test launchers even
when the manifest file existed.
- `rules_rs`, `rules_rust`, LLVM extraction, and Abseil still needed
`windows-gnullvm`-specific fixes for our hermetic toolchain.
- the V8 path needed more work than just turning the Windows matrix
entry back on: `rusty_v8` does not ship Windows GNU artifacts in the
same shape we need, and Bazel's in-tree V8 build needed a set of Windows
GNU portability fixes.

Windows performance pressure also pushed this toward a full solution
instead of a permanent smoke suite. During this investigation we hit
targets such as `//codex-rs/shell-command:shell-command-unit-tests` that
were much more expensive on Windows because they repeatedly spawn real
PowerShell parsers (see #16057 for one concrete example of that
pressure). That made it much more valuable to get the real Windows Bazel
path working than to keep iterating on a narrowly curated subset.

The net result is that this PR now aims for the same CI contract on
Windows that we already expect elsewhere: keep standalone
`//third_party/v8:all` out of the ordinary Bazel lane, but allow V8
consumers under `//codex-rs/...` to build and test transitively through
`//...`.

## What Changed

### CI and workflow wiring

- re-enable the `windows-latest` / `x86_64-pc-windows-gnullvm` Bazel
matrix entry in `.github/workflows/bazel.yml`
- move the Windows Bazel output root to `D:\b` and enable `git config
--global core.longpaths true` in
`.github/actions/setup-bazel-ci/action.yml`
- keep the ordinary Bazel target set on Windows aligned with macOS and
Linux by running `//...` while excluding only standalone
`//third_party/v8:all` targets from the normal lane

### Toolchain and module support for `windows-gnullvm`

- patch `rules_rs` so `windows-gnullvm` is modeled as a distinct Windows
exec/toolchain platform instead of collapsing into the generic Windows
shape
- patch `rules_rust` build-script environment handling so llvm-mingw
build-script probes do not inherit unsupported `-fstack-protector*`
flags
- patch the LLVM module archive so it extracts cleanly on Windows and
provides the MinGW libraries this toolchain needs
- patch Abseil so its thread-local identity path matches the hermetic
`windows-gnullvm` toolchain instead of taking an incompatible MinGW
pthread path
- keep both MSVC and GNU Windows targets in the generated Cargo metadata
because the current V8 release-asset story still uses MSVC-shaped names
in some places while the Bazel build targets the GNU ABI

### Windows test-launch and binary-behavior fixes

- update `workspace_root_test_launcher.bat.tpl` to read the runfiles
manifest directly instead of shelling out to `findstr`, which was the
source of the `D:MANIFEST` failures on the GitHub Windows runner
- thread a larger Windows GNU stack reserve through `defs.bzl` so
Bazel-built binaries that pull in V8 behave correctly both under normal
builds and under `bazel test`
- remove the no-longer-needed Windows bootstrap sh-toolchain override
from `.bazelrc`

### V8 / `rusty_v8` Windows GNU support

- export and apply the new Windows GNU patch set from
`patches/BUILD.bazel` / `MODULE.bazel`
- patch the V8 module/rules/source layers so the in-tree V8 build can
produce Windows GNU archives under Bazel
- teach `third_party/v8/BUILD.bazel` to build Windows GNU static
archives in-tree instead of aliasing them to the MSVC prebuilts
- reuse the Linux release binding for the experimental Windows GNU path
where `rusty_v8` does not currently publish a Windows GNU binding
artifact

## Testing

- the primary end-to-end validation for this work is the `Bazel`
workflow plus `v8-canary`, since the hard parts are Windows-specific and
depend on real GitHub runner behavior
- before consolidation back onto this PR, the same net change passed the
full Bazel matrix in [run
23675590471](https://github.com/openai/codex/actions/runs/23675590471)
and passed `v8-canary` in [run
23675590453](https://github.com/openai/codex/actions/runs/23675590453)
- those successful runs included the `windows-latest` /
`x86_64-pc-windows-gnullvm` Bazel job with the ordinary `//...` path,
not the earlier Windows smoke allowlist

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15952).
* #16067
* __->__ #15952
2026-03-27 20:37:03 -07:00
Michael Bolin 5037a2d199 refactor: rewrite argument-comment lint wrappers in Python (#16063)
## Why

The `argument-comment-lint` entrypoints had grown into two shell
wrappers with duplicated parsing, environment setup, and Cargo
forwarding logic. The recent `--` separator regression was a good
example of the problem: the behavior was subtle, easy to break, and hard
to verify.

This change rewrites those wrappers in Python so the control flow is
easier to follow, the shared behavior lives in one place, and the tricky
argument/defaulting paths have direct test coverage.

## What changed

- replaced `tools/argument-comment-lint/run.sh` and
`tools/argument-comment-lint/run-prebuilt-linter.sh` with Python
entrypoints: `run.py` and `run-prebuilt-linter.py`
- moved shared wrapper behavior into
`tools/argument-comment-lint/wrapper_common.py`, including:
  - splitting lint args from forwarded Cargo args after `--`
- defaulting repo runs to `--manifest-path codex-rs/Cargo.toml
--workspace --no-deps`
- defaulting non-`--fix` runs to `--all-targets` unless the caller
explicitly narrows the target set
  - setting repo defaults for `DYLINT_RUSTFLAGS` and `CARGO_INCREMENTAL`
- kept the prebuilt wrapper thin: it still just resolves the packaged
DotSlash entrypoint, keeps `rustup` shims first on `PATH`, infers
`RUSTUP_HOME` when needed, and then launches the packaged `cargo-dylint`
path
- updated `justfile`, `rust-ci.yml`, and
`tools/argument-comment-lint/README.md` to use the Python entrypoints
- updated `rust-ci` so the package job runs Python syntax checks plus
the new wrapper unit tests, and the OS-specific lint jobs invoke the
wrappers through an explicit Python interpreter

This is a follow-up to #16054: it keeps the current lint semantics while
making the wrapper logic maintainable enough to iterate on safely.

## Validation

- `python3 -m py_compile tools/argument-comment-lint/wrapper_common.py
tools/argument-comment-lint/run.py
tools/argument-comment-lint/run-prebuilt-linter.py
tools/argument-comment-lint/test_wrapper_common.py`
- `python3 -m unittest discover -s tools/argument-comment-lint -p
'test_*.py'`
- `python3 ./tools/argument-comment-lint/run-prebuilt-linter.py -p
codex-terminal-detection -- --lib`
- `python3 ./tools/argument-comment-lint/run.py -p
codex-terminal-detection -- --lib`
2026-03-27 19:42:30 -07:00
Michael Bolin 142681ef93 shell-command: reuse a PowerShell parser process on Windows (#16057)
## Why

`//codex-rs/shell-command:shell-command-unit-tests` became a real
bottleneck in the Windows Bazel lane because repeated calls to
`is_safe_command_windows()` were starting a fresh PowerShell parser
process for every `powershell.exe -Command ...` assertion.

PR #16056 was motivated by that same bottleneck, but its test-only
shortcut was the wrong layer to optimize because it weakened the
end-to-end guarantee that our runtime path really asks PowerShell to
parse the command the way we expect.

This PR attacks the actual cost center instead: it keeps the real
PowerShell parser in the loop, but turns that parser into a long-lived
helper process so both tests and the runtime safe-command path can reuse
it across many requests.

## What Changed

- add `shell-command/src/command_safety/powershell_parser.rs`, which
keeps one mutex-protected parser process per PowerShell executable path
and speaks a simple JSON-over-stdio request/response protocol
- turn `shell-command/src/command_safety/powershell_parser.ps1` into a
long-running parser server with comments explaining the protocol, the
AST-shape restrictions, and why unsupported constructs are rejected
conservatively
- keep request ids and a one-time respawn path so a dead or
desynchronized cached child fails closed instead of silently returning
mixed parser output
- preserve separate parser processes for `powershell.exe` and
`pwsh.exe`, since they do not accept the same language surface
- avoid a direct `PipelineChainAst` type reference in the PowerShell
script so the parser service still runs under Windows PowerShell 5.1 as
well as newer `pwsh`
- make `shell-command/src/command_safety/windows_safe_commands.rs`
delegate to the new parser utility instead of spawning a fresh
PowerShell process for every parse
- add a Windows-only unit test that exercises multiple sequential
requests against the same parser process

## Testing

- adds a Windows-only parser-reuse unit test in `powershell_parser.rs`
- the main end-to-end verification for this change is the Windows CI
lane, because the new service depends on real `powershell.exe` /
`pwsh.exe` behavior
2026-03-27 19:33:41 -07:00
Joe LicciniandCodex 71923f43a7 Support Codex CLI stdin piping for codex exec (#15917)
# Summary

Claude Code supports a useful prompt-plus-stdin workflow:

```bash
echo "complex input..." | claude -p "summarize concisely"
```

Codex previously did not support the equivalent `codex exec` form. While
`codex exec` could read the prompt from stdin, it could not combine
piped input with an explicit prompt argument.

This change adds that missing workflow:

```bash
echo "complex input..." | codex exec "summarize concisely"
```

With this change, when `codex exec` receives both a positional prompt
and piped stdin, the prompt remains the instruction and stdin is passed
along as structured `<stdin>...</stdin>` context.

Example:

```bash
curl https://jsonplaceholder.typicode.com/comments \
  | ./target/debug/codex exec --skip-git-repo-check "format the top 20 items into a markdown table" \
  > table.md
```

This PR also adds regression coverage for:
- prompt argument + piped stdin
- legacy stdin-as-prompt behavior
- `codex exec -` forced-stdin behavior
- empty-stdin error cases

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-28 02:21:22 +00:00
Michael Bolin 61dfe0b86c chore: clean up argument-comment lint and roll out all-target CI on macOS (#16054)
## Why

`argument-comment-lint` was green in CI even though the repo still had
many uncommented literal arguments. The main gap was target coverage:
the repo wrapper did not force Cargo to inspect test-only call sites, so
examples like the `latest_session_lookup_params(true, ...)` tests in
`codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path.

This change cleans up the existing backlog, makes the default repo lint
path cover all Cargo targets, and starts rolling that stricter CI
enforcement out on the platform where it is currently validated.

## What changed

- mechanically fixed existing `argument-comment-lint` violations across
the `codex-rs` workspace, including tests, examples, and benches
- updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and
`tools/argument-comment-lint/run.sh` so non-`--fix` runs default to
`--all-targets` unless the caller explicitly narrows the target set
- fixed both wrappers so forwarded cargo arguments after `--` are
preserved with a single separator
- documented the new default behavior in
`tools/argument-comment-lint/README.md`
- updated `rust-ci` so the macOS lint lane keeps the plain wrapper
invocation and therefore enforces `--all-targets`, while Linux and
Windows temporarily pass `-- --lib --bins`

That temporary CI split keeps the stricter all-targets check where it is
already cleaned up, while leaving room to finish the remaining Linux-
and Windows-specific target-gated cleanup before enabling
`--all-targets` on those runners. The Linux and Windows failures on the
intermediate revision were caused by the wrapper forwarding bug, not by
additional lint findings in those lanes.

## Validation

- `bash -n tools/argument-comment-lint/run.sh`
- `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh`
- shell-level wrapper forwarding check for `-- --lib --bins`
- shell-level wrapper forwarding check for `-- --tests`
- `just argument-comment-lint`
- `cargo test` in `tools/argument-comment-lint`
- `cargo test -p codex-terminal-detection`

## Follow-up

- Clean up remaining Linux-only target-gated callsites, then switch the
Linux lint lane back to the plain wrapper invocation.
- Clean up remaining Windows-only target-gated callsites, then switch
the Windows lint lane back to the plain wrapper invocation.
2026-03-27 19:00:44 -07:00