## What changed
- Share the root thread's current service tier across its agent tree.
- Apply that tier to each subagent request when the selected child model supports it, including remote compaction requests.
- Propagate root service-tier updates to existing and newly spawned subagents without rewriting child-owned settings.
- Remove per-spawn and role-level service-tier overrides so routing remains controlled by the root thread.
## Testing
- Cover supported and unsupported child models, full-history forks, live tier changes, remote compaction, new subagents, and reloaded subagents.
GitOrigin-RevId: 6c299e224e90b41a558788fb7aa4d5f336fa383a
## What changed
- Add `codex-agent-roles` for agent role configuration types, parsing,
discovery, validation, and layered loading.
- Update `codex-core` to consume the new crate's public role configuration and
parsing APIs.
GitOrigin-RevId: 5a963a219a581b2848dae6fd071aa31a0b5ff22c
## Why
Agent roles should customize a child agent without expanding the authority or changing the provider configuration inherited from its parent session.
## What changed
- Apply only supported role overrides for model behavior, developer instructions, personality, service tier, and capability reductions.
- Preserve parent-owned permissions, model providers, endpoints, MCP servers, notifications, and other unrestricted configuration.
- Keep managed feature requirements effective when a role disables capabilities, and reject symlinked user role files.
- Use the same bounded role application path for both multi-agent implementations and resumed agents.
## Testing
Add coverage for authority preservation, managed feature requirements, symlink rejection, provider inheritance, and provider routing after resume.
GitOrigin-RevId: c528d615b691f9c02bfbc21154d514ea07743010
## What changed
- Add the under-development `psp` feature and expose it in the config schema.
- Use the feature to attach the PSP cookie to first-party ChatGPT clients.
- Remove the hidden `--psp` flag and its process-scoped configuration plumbing.
- Preserve configured ChatGPT cookies when creating the PSP client used for GET and POST requests.
## Testing
- Update the config manager service test to verify that enabling `features.psp` retains the setting in the effective config and configures the expected ChatGPT cookie.
GitOrigin-RevId: 53acb5495d2ff71e4ed25f674a0cff787aea474a
## Why
Persisted base instructions need to retain whether they were explicitly customized or generated from a model template. Without that distinction, forks and config-lock replays can treat model-generated instructions as custom and keep the wrong template after a model or personality change.
## What changed
- Record custom or model provenance with base instructions in rollouts and config locks.
- Preserve custom instructions across model changes, while allowing model-generated instructions to follow the selected model and personality.
- Keep legacy rollouts without provenance compatible and propagate provenance through forks and spawned agents.
## Testing
- Cover provenance serialization and legacy rollout decoding.
- Cover role personality changes, forked model changes, config-lock replay, and multi-agent configuration.
GitOrigin-RevId: 801c26559835f558027ce5112700c0cd31fcb21b
## What changed
- Add a hidden global `--psp` runtime flag and propagate it through TUI, exec,
app-server, remote-control, and in-process startup paths.
- Attach the `oai-chat-psp=true` cookie to first-party ChatGPT requests when
enabled, using a cached cookie-aware client with sensitive request logging
disabled.
- Keep the routing selection out of persistent configuration layers while
preserving it across config refreshes and agent role changes.
## Testing
- Cover global flag parsing, app-server propagation, config-layer isolation,
and preservation across config rebuilds and role changes.
GitOrigin-RevId: 05cdc61ffd7162d8e48fc1e166f4732113e5a816
## Why
Trusting a directory enables project-local config, hooks, and exec policies, which can increase exposure to prompt injection. Require an explicit decision instead of automatically trusting projects whose trust level is unset.
## What changed
- Add a directory-trust step to TUI onboarding, with options to trust and continue or quit.
- Apply trust to the Git repository root when starting from a subdirectory, persist the decision, and reload config before continuing.
- Keep the prompt active and show the config error when trust cannot be persisted. Skip the prompt for remote workspaces and projects with an explicit trust level.
## Testing
- Cover trust-screen rendering, keyboard selection, persistence failures, and prompt visibility for explicit trust and Windows sandbox states.
GitOrigin-RevId: 850e6f54aec84d584cd161348ecdb1da89aaabd4
## What changed
- Replace the TUI directory-trust prompt with automatic trust for local projects whose trust level is unset. Keep explicit trust settings and remote workspaces unchanged.
- Persist trust for the resolved Git or configured project root, then reload configuration so project-local settings take effect.
- Fall back to an in-memory trust override and an embedded app server when the config update cannot be persisted.
## Testing
- Cover persisted and in-memory trust, custom project-root markers, and the working directories selected by resume and fork flows.
GitOrigin-RevId: 8fd51eb4cd88267073324bfd7dc4106a56d7c745
## What changed
- Replace the ordering enum and `include_disabled` boolean with named
`ConfigLayerStack` iterators for each precedence direction.
- Keep enabled-only iteration separate from `all_layers_*` iteration, which
includes disabled layers.
- Update config consumers to use the iterator matching their precedence and
disabled-layer requirements without allocating an intermediate `Vec`.
## Testing
- Add coverage that verifies ordering and disabled-layer filtering for all four
iterators.
GitOrigin-RevId: d14df3db4a2eae80ba97cdec246bff405e6c5f3d
## What changed
- Add `features.multi_agent_v2.subagent_developer_instructions` to override inherited developer instructions for subagents that do not define role-specific instructions.
- Preserve role-specific instructions as the higher-precedence setting, and carry the effective instructions through full and bounded forks, compacted histories, and cold resume without duplication.
- Treat an unset override as inheritance and a blank override as clearing inherited instructions.
## Testing
- Cover configuration parsing and materialization, instruction precedence, fork modes, compaction, role application, and resumed subagents.
GitOrigin-RevId: 32321e61abc59b14a1be5f31e6bd6570bb1cd89d
## What changed
- Apply `agents.default_subagent_model` and
`agents.default_subagent_reasoning_effort` when a spawn request does not
provide explicit values, including agent job workers.
- Allow full-history forks to use configured defaults or explicit model and
reasoning-effort overrides while retaining the parent conversation context.
- Preserve the selected model and reasoning effort when an agent role does not
override them.
## Testing
- Cover configured defaults, explicit override precedence, full-history forks,
role application, and agent job workers.
GitOrigin-RevId: b1efa8c9abeee82355088fceef57560433144595
## Why
The `agent_type` argument is only useful when agent roles are configured. Avoid
advertising an inapplicable override in the model-visible `spawn_agent` schema.
## What changed
- Include `agent_type` in the V1 and V2 spawn tools only when configured roles
are available.
- Clarify that `agent_type` is an explicit override and document its interaction
with context forking.
- Remove the unused `agents.support_agent_type` configuration field.
## Testing
- Add coverage for hiding `agent_type` without roles and exposing it when a role
is configured.
GitOrigin-RevId: 32e0f123b15f317e9cdb71774029375bc073d9ad
## Why
Config layer provenance describes how effective configuration was
assembled, so it belongs with the config loader rather than in
app-server's serialized API types.
## What changed
- Moved `ConfigLayerSource`, `ConfigLayerMetadata`, and `ConfigLayer`
ownership into `codex-config`.
- Kept app-server's wire payloads unchanged and added explicit
conversions at the app boundary.
- Removed lower-level app-server-protocol dependencies from config
consumers.
## Stack
This is PR 3 of 6, stacked on [PR
#29721](https://github.com/openai/codex/pull/29721). Review only the
delta from `codex/split-auth-domain-types`. Next: [PR
#29723](https://github.com/openai/codex/pull/29723).
## Validation
- `codex-config` coverage passed.
- App-server config-manager and config RPC coverage passed.
## Summary
- drop the dead legacy profile usage metric and active-profile
conversation-start fields
- update role comments so they describe provider and service-tier
preservation without legacy config-profile wording
- pair the code cleanup with the file-backed profile docs update in
openai/developers-website#1476
## Testing
- `just fmt`
- `cargo test -p codex-otel`
- `cargo test -p codex-core` *(fails: existing stack overflow in
`mcp_tool_call::tests::guardian_mode_mcp_denial_returns_rationale_message`)*
- `cargo test -p codex-core --lib
mcp_tool_call::tests::guardian_mode_mcp_denial_returns_rationale_message`
*(fails with the same stack overflow)*
## Why
Custom agent roles are ordinary config layers, so a role file can
already express `service_tier` just like other config values. The
spawned-agent tier path needs to preserve that effective role config and
follow the same precedence pattern as model/reasoning.
## What changed
- Apply an explicit spawn-time `service_tier` onto the child config
before role application, so a role config layer can override it just
like role-defined model/reasoning settings do.
- Validate the final effective child tier after the final child model is
known, while still falling back to the parent tier when no child tier
survives.
- Add focused integration coverage for both v1 and v2 proving role TOML
loads a service tier, spawned children keep that role-configured tier,
and a role tier wins over a conflicting spawn-time tier.
## Validation
- `just fmt`
- `git diff --check`
- Local Rust tests not run, per repo guidance; CI should exercise the
new coverage.
## Why
Config loading had become split across crates: `codex-config` owned the
config types and merge logic, while `codex-core` still owned the loader
that assembled the layer stack. This change consolidates that
responsibility in `codex-config`, so the crate that defines config
behavior also owns how configs are discovered and loaded.
To make that move possible without reintroducing the old dependency
cycle, the shell-environment policy types and helpers that
`codex-exec-server` needs now live in `codex-protocol` instead of
flowing through `codex-config`.
This also makes the migrated loader tests more deterministic on machines
that already have managed or system Codex config installed by letting
tests override the system config and requirements paths instead of
reading the host's `/etc/codex`.
## What Changed
- moved the config loader implementation from `codex-core` into
`codex-config::loader` and deleted the old `core::config_loader` module
instead of leaving a compatibility shim
- moved shell-environment policy types and helpers into
`codex-protocol`, then updated `codex-exec-server` and other downstream
crates to import them from their new home
- updated downstream callers to use loader/config APIs from
`codex-config`
- added test-only loader overrides for system config and requirements
paths so loader-focused tests do not depend on host-managed config state
- cleaned up now-unused dependency entries and platform-specific cfgs
that were surfaced by post-push CI
## Testing
- `cargo test -p codex-config`
- `cargo test -p codex-core config_loader_tests::`
- `cargo test -p codex-protocol -p codex-exec-server -p
codex-cloud-requirements -p codex-rmcp-client --lib`
- `cargo test --lib -p codex-app-server-client -p codex-exec`
- `cargo test --no-run --lib -p codex-app-server`
- `cargo test -p codex-linux-sandbox --lib`
- `cargo shear`
- `just bazel-lock-check`
## Notes
- I did not chase unrelated full-suite failures outside the migrated
loader surface.
- `cargo test -p codex-core --lib` still hits unrelated proxy-sensitive
failures on this machine, and Windows CI still shows unrelated
long-running/timeouting test noise outside the loader migration itself.
Migrate `cwd` and related session/config state to `AbsolutePathBuf` so
downstream consumers consistently see absolute working directories.
Add test-only `.abs()` helpers for `Path`, `PathBuf`, and `TempDir`, and
update branch-local tests to use them instead of
`AbsolutePathBuf::try_from(...)`.
For the remaining TUI/app-server snapshot coverage that renders absolute
cwd values, keep the snapshots unchanged and skip the Windows-only cases
where the platform-specific absolute path layout differs.
## Why
Once the repo-local lint exists, `codex-rs` needs to follow the
checked-in convention and CI needs to keep it from drifting. This commit
applies the fallback `/*param*/` style consistently across existing
positional literal call sites without changing those APIs.
The longer-term preference is still to avoid APIs that require comments
by choosing clearer parameter types and call shapes. This PR is
intentionally the mechanical follow-through for the places where the
existing signatures stay in place.
After rebasing onto newer `main`, the rollout also had to cover newly
introduced `tui_app_server` call sites. That made it clear the first cut
of the CI job was too expensive for the common path: it was spending
almost as much time installing `cargo-dylint` and re-testing the lint
crate as a representative test job spends running product tests. The CI
update keeps the full workspace enforcement but trims that extra
overhead from ordinary `codex-rs` PRs.
## What changed
- keep a dedicated `argument_comment_lint` job in `rust-ci`
- mechanically annotate remaining opaque positional literals across
`codex-rs` with exact `/*param*/` comments, including the rebased
`tui_app_server` call sites that now fall under the lint
- keep the checked-in style aligned with the lint policy by using
`/*param*/` and leaving string and char literals uncommented
- cache `cargo-dylint`, `dylint-link`, and the relevant Cargo
registry/git metadata in the lint job
- split changed-path detection so the lint crate's own `cargo test` step
runs only when `tools/argument-comment-lint/*` or `rust-ci.yml` changes
- continue to run the repo wrapper over the `codex-rs` workspace, so
product-code enforcement is unchanged
Most of the code changes in this commit are intentionally mechanical
comment rewrites or insertions driven by the lint itself.
## Verification
- `./tools/argument-comment-lint/run.sh --workspace`
- `cargo test -p codex-tui-app-server -p codex-tui`
- parsed `.github/workflows/rust-ci.yml` locally with PyYAML
---
* -> #14652
* #14651
## Why
PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This
applies the same extraction pattern across the rest of `codex-rs/core`
so the production modules stay focused on runtime code instead of large
inline test blocks.
Keeping the tests in sibling files also makes follow-up edits easier to
review because product changes no longer have to share a file with
hundreds or thousands of lines of test scaffolding.
## What changed
- replaced each inline `mod tests { ... }` in `codex-rs/core/src/**`
with a path-based module declaration
- moved each extracted unit test module into a sibling `*_tests.rs`
file, using `mod_tests.rs` for `mod.rs` modules
- preserved the existing `cfg(...)` guards and module-local structure so
the refactor remains structural rather than behavioral
## Testing
- `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`)
- `just fix -p codex-core`
- `cargo fmt --check`
- `cargo shear`
- tell agents when a role pins model or reasoning effort so they know
those settings are not changeable
- add prompt-builder coverage for the locked-setting notes
Support loading plugins.
Plugins can now be enabled via [plugins.<name>] in config.toml. They are
loaded as first-class entities through PluginsManager, and their default
skills/ and .mcp.json contributions are integrated into the existing
skills and MCP flows.
## Why
`codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs` previously
located `codex-execve-wrapper` by scanning `PATH` and sibling
directories. That lookup is brittle and can select the wrong binary when
the runtime environment differs from startup assumptions.
We already pass `codex-linux-sandbox` from `codex-arg0`;
`codex-execve-wrapper` should use the same startup-driven path plumbing.
## What changed
- Introduced `Arg0DispatchPaths` in `codex-arg0` to carry both helper
executable paths:
- `codex_linux_sandbox_exe`
- `main_execve_wrapper_exe`
- Updated `arg0_dispatch_or_else()` to pass `Arg0DispatchPaths` to
top-level binaries and preserve helper paths created in
`prepend_path_entry_for_codex_aliases()`.
- Threaded `Arg0DispatchPaths` through entrypoints in `cli`, `exec`,
`tui`, `app-server`, and `mcp-server`.
- Added `main_execve_wrapper_exe` to core configuration plumbing
(`Config`, `ConfigOverrides`, and `SessionServices`).
- Updated zsh-fork shell escalation to consume the configured
`main_execve_wrapper_exe` and removed path-sniffing fallback logic.
- Updated app-server config reload paths so reloaded configs keep the
same startup-provided helper executable paths.
## References
- [`Arg0DispatchPaths`
definition](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/arg0/src/lib.rs#L20-L24)
- [`arg0_dispatch_or_else()` forwarding both
paths](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/arg0/src/lib.rs#L145-L176)
- [zsh-fork escalation using configured wrapper
path](https://github.com/openai/codex/blob/e355b43d5c2a771f045296a6deae10d7c9c36ec6/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs#L109-L150)
## Testing
- `cargo check -p codex-arg0 -p codex-core -p codex-exec -p codex-tui -p
codex-mcp-server -p codex-app-server`
- `cargo test -p codex-arg0`
- `cargo test -p codex-core tools::runtimes::shell::unix_escalation:: --
--nocapture`
The idea is to have 2 family of agents.
1. Built-in that we packaged directly with Codex
2. User defined that are defined using the `agents_config.toml` file. It
can reference config files that will override the agent config. This
looks like this:
```
version = 1
[agents.explorer]
description = """Use `explorer` for all codebase questions.
Explorers are fast and authoritative.
Always prefer them over manual search or file reading.
Rules:
- Ask explorers first and precisely.
- Do not re-read or re-search code they cover.
- Trust explorer results without verification.
- Run explorers in parallel when useful.
- Reuse existing explorers for related questions."""
config_file = "explorer.toml"
```
## Why
We currently carry multiple permission-related concepts directly on
`Config` for shell/unified-exec behavior (`approval_policy`,
`sandbox_policy`, `network`, `shell_environment_policy`,
`windows_sandbox_mode`).
Consolidating these into one in-memory struct makes permission handling
easier to reason about and sets up the next step: supporting named
permission profiles (`[permissions.PROFILE_NAME]`) without changing
behavior now.
This change is mostly mechanical: it updates existing callsites to go
through `config.permissions`, but it does not yet refactor those
callsites to take a single `Permissions` value in places where multiple
permission fields are still threaded separately.
This PR intentionally **does not** change the on-disk `config.toml`
format yet and keeps compatibility with legacy config keys.
## What Changed
- Introduced `Permissions` in `core/src/config/mod.rs`.
- Added `Config::permissions` and moved effective runtime permission
fields under it:
- `approval_policy`
- `sandbox_policy`
- `network`
- `shell_environment_policy`
- `windows_sandbox_mode`
- Updated config loading/building so these effective values are still
derived from the same existing config inputs and constraints.
- Updated Windows sandbox helpers/resolution to read/write via
`permissions`.
- Threaded the new field through all permission consumers across core
runtime, app-server, CLI/exec, TUI, and sandbox summary code.
- Updated affected tests to reference `config.permissions.*`.
- Renamed the struct/field from
`EffectivePermissions`/`effective_permissions` to
`Permissions`/`permissions` and aligned variable naming accordingly.
## Verification
- `just fix -p codex-core -p codex-tui -p codex-cli -p codex-app-server
-p codex-exec -p codex-utils-sandbox-summary`
- `cargo build -p codex-core -p codex-tui -p codex-cli -p
codex-app-server -p codex-exec -p codex-utils-sandbox-summary`