## 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`
## Why
`codex-core` already owns too much of the tool stack, and `AGENTS.md`
explicitly pushes us to move shared code out of `codex-core` instead of
letting it keep growing. This PR takes the next incremental step in
moving `core/src/tools` toward `codex-rs/tools` by extracting
low-coupling tool configuration and image-detail gating logic into
`codex-tools`.
That gives later extraction work a cleaner boundary to build on without
trying to move the entire tools subtree in one shot.
## What changed
- moved `ToolsConfig`, `ToolsConfigParams`, shell backend config, and
unified-exec session selection from `core/src/tools/spec.rs` into
`codex-tools`
- moved original image-detail gating and normalization into
`codex-tools`
- updated `codex-core` to consume the new `codex-tools` exports and pass
a rendered agent-type description instead of raw role config
- kept `codex-rs/tools/src/lib.rs` exports-only, with extracted unit
tests living in sibling `*_tests.rs` modules
## Testing
- `cargo test -p codex-tools`
- `cargo test -p codex-core --lib tools::spec::`
## 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`
## 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/audio cfgs with pure Linux-vs-non-Linux cfgs
- shrink the workspace-manifest verifier allowlist to remove the remaining `codex-tui` exception
## 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/audio cfgs with pure Linux-vs-non-Linux cfgs
- shrink the workspace-manifest verifier allowlist to remove the remaining `codex-tui` exception
## 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`
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## 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
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## 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
Makes fuzzy file search use case-insensitive matching instead of
smart-case in `codex-file-search`. I find smart-case to be a poor user
experience -using the wrong case for a letter drops its match so
significantly, it often drops off the results list, effectively making a
search case-sensitive.
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## 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
## Why
The remaining `vt100-tests` and `debug-logs` features in `codex-tui` were only selecting debug and test-only behavior. Those are exactly the cases where this repo already accepts `#[cfg(debug_assertions)]` as the Cargo-free substitute.
## What changed
- delete `vt100-tests` and `debug-logs` from `codex-tui`
- gate the VT100 integration tests with `debug_assertions` instead of a Cargo feature
- gate the textarea debug log site with `debug_assertions`
- shrink the manifest verifier allowlist again so only the remaining real feature exceptions stay permitted
## Why
`codex-cloud-tasks-client` was still using Cargo features to select its HTTP and mock implementations. That leaks feature permutations into both Cargo and Bazel for a crate that does not need them.
## What changed
- delete the `online` and `mock` crate features from `codex-cloud-tasks-client`
- make `codex-backend-client` unconditional and always export both `HttpClient` and `MockClient`
- remove the internal `features = ["mock", "online"]` activation from `codex-cloud-tasks`
- remove the matching Bazel `crate_features` override
- shrink the manifest verifier allowlist to match the remaining exceptions
## 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