Commit Graph
7950 Commits
Author SHA1 Message Date
Charlie Marsh da66c4780e Clear rejected review attachments when not deferred 2026-06-29 21:24:38 -04:00
Charlie Marsh 65462b1b22 Document TUI task activity 2026-06-29 09:39:15 -04:00
Charlie Marsh f490e1a5a6 Preserve slash commands with pending turns 2026-06-29 09:39:15 -04:00
Charlie Marsh 333e703772 Trim redundant MCP startup coverage 2026-06-29 09:39:15 -04:00
Charlie Marsh fcda7ed4ee Preserve rejected review draft attachments 2026-06-29 09:39:14 -04:00
Charlie Marsh 4d13a6c70a Preserve MCP activity across thread switches 2026-06-29 09:39:14 -04:00
Charlie Marsh f6e8c636d2 Simplify review MCP isolation 2026-06-29 09:39:14 -04:00
Charlie Marsh 3f75f965da Reset MCP guards after replayed reviews 2026-06-29 09:39:14 -04:00
Charlie Marsh d4665d4754 Keep rejected review drafts editable 2026-06-29 09:39:14 -04:00
Charlie Marsh 65f74c63f7 Track MCP-only startup tasks 2026-06-29 09:39:14 -04:00
Charlie Marsh cd3765ead5 Keep review behind queued prompts 2026-06-29 09:39:14 -04:00
Charlie Marsh 86234a3991 Preserve blocked review drafts 2026-06-29 09:39:14 -04:00
Charlie Marsh 6fbf2c54c2 Ignore MCP lag recovery during review 2026-06-29 09:39:14 -04:00
Charlie Marsh 29bfc614d3 Restore MCP suppression for replayed reviews 2026-06-29 09:39:14 -04:00
Charlie Marsh 8794e18441 Ignore late updates from pre-review MCP startup 2026-06-29 09:39:13 -04:00
Charlie Marsh 2ed06e03d3 Restore MCP updates after review setup errors 2026-06-29 09:39:13 -04:00
Charlie Marsh 928b4481cd Arm MCP suppression when review is submitted 2026-06-29 09:39:13 -04:00
Charlie Marsh 7152247808 Update task gating tests for review exception 2026-06-29 09:39:13 -04:00
Charlie Marsh 06ac479c9b Track review popup snapshot 2026-06-29 09:39:13 -04:00
Charlie Marsh df4b4401fb Suppress skipped MCP startup updates during review 2026-06-29 09:39:13 -04:00
Charlie Marsh 7807ffc65b Allow review while MCPs are loading 2026-06-29 09:39:13 -04:00
Charlie Marsh 45b3fd1788 Document review MCP access policy 2026-06-29 09:38:55 -04:00
Charlie Marsh 9dc640ecb4 Fix review tests across executors 2026-06-29 09:25:42 -04:00
Charlie Marsh d63f5c7d09 Trim redundant ready-MCP coverage 2026-06-28 22:42:54 -04:00
Charlie Marsh 28d3673af2 Use MCP in reviews after startup completes 2026-06-28 22:37:39 -04:00
Charlie Marsh 133958a7ba Cover configured MCP tools in reviews 2026-06-28 22:37:38 -04:00
Charlie Marsh 315b5267e8 Simplify review MCP isolation 2026-06-28 22:37:38 -04:00
Charlie Marsh 1a911227db Cover MCP resource tools in reviews 2026-06-28 22:37:37 -04:00
Charlie Marsh d0f9cfd7d3 Run review tests across executors 2026-06-28 22:37:37 -04:00
Charlie Marsh af0c2460f0 Scope review tool suppression 2026-06-28 22:37:37 -04:00
Charlie Marsh 11d7da66e4 Skip MCP auth discovery during review 2026-06-28 22:37:36 -04:00
Charlie Marsh b387b7dabb Disable tool suggestions during review 2026-06-28 22:37:36 -04:00
Charlie Marsh 7b64fce3e3 Bypass MCP startup for review sessions 2026-06-28 22:37:35 -04:00
Charlie Marsh a466b78c73 Preserve plugin policy hooks during review 2026-06-28 22:37:35 -04:00
Charlie Marsh 11d806e1fa Keep review MCP runtime isolated 2026-06-28 22:37:35 -04:00
Charlie Marsh 7d4b2a9b5a Exclude MCP tools from review turns 2026-06-28 22:37:34 -04:00
Charlie Marsh fdc56e4608 Allow review while MCPs are loading 2026-06-28 22:37:33 -04:00
ani-oai 6b5f5743b3 [codex] Use model metadata for skills usage instructions (#29740)
## Summary

- add a false-by-default `include_skills_usage_instructions` model
metadata field
- enable the field for the bundled `gpt-5.5` model metadata
- consume the metadata in both core and extension skill rendering
- remove hardcoded legacy-model matching and its marker plumbing
2026-06-29 09:44:36 +09:00
Felipe Coury 850da19dc4 fix(tui): clear completed safety buffering prompt (#30490)
## Why

The safety-buffering prompt is a modal TUI view, but the normal
successful-turn path only hid the running status indicator. If the turn
completed while the prompt was open, the stale modal remained over the
composer until the user dismissed it or another turn started.

This aligns the TUI with the app behavior: keep the safety notice
visible while the turn is active, then remove it when the turn becomes
terminal. It also prevents the stale retry action from changing the
model and reasoning effort for a future turn after the buffered turn has
already completed.

| New copy |
|---|
| <img width="1014" height="313" alt="CleanShot 2026-06-28 at 20 27 18"
src="https://github.com/user-attachments/assets/f0f37359-5d77-442f-add2-9d1874bdc422"
/> |

## What changed

- Clear the active safety-buffering view and retry state when a turn
completes successfully.
- Update the retry-capable message to say “Hang tight or retry with a
faster model”.
- Extend the safety-buffering regression coverage to verify that the
prompt remains visible after assistant output starts and disappears when
the turn completes.
- Update the TUI snapshot for the revised copy.

This is a follow-up to #29919.

## How to Test

1. Start a TUI turn that receives `model/safetyBuffering/updated` with
`showBufferingUi: true` and a `fasterModel`.
2. Confirm the prompt says “Hang tight or retry with a faster model”.
3. Let the turn continue and confirm the prompt remains visible while
the turn is active.
4. Let the turn finish successfully and confirm the prompt disappears
and the composer is restored without requiring an extra keypress.
5. Confirm a buffering update without a faster model still shows the
shorter non-retry message.

Targeted automated coverage:

- `just test -p codex-tui safety_buffering` — 4 passed.
- `just test -p codex-tui` — 2,951 passed; two unrelated Guardian
feature-flag tests failed identically on `main` in this environment.

The argument-comment lint was also audited manually. The workspace Bazel
invocation was blocked by a missing external LLVM `compiler-rt` BUILD
file, and the packaged per-crate fallback uses a nightly older than the
current `sqlx` minimum Rust version.
2026-06-28 20:55:53 -03:00
xl-openai e428a12d22 [codex] Enable remote plugins by default (#30297)
## Summary

- enable the remote plugin feature by default
- promote the remote plugin feature from under development to stable
- preserve the existing `features.remote_plugin` override for explicitly
disabling it
- keep legacy disabled-path coverage explicit in TUI and app-server
tests

## Impact

Remote plugin functionality is enabled by default for configurations
that do not set the feature flag. The existing Codex backend
authentication gate still applies.

## Validation

- `just fmt`
- `just test -p codex-features`
- `just test -p codex-tui
plugins_popup_remote_section_fallback_states_snapshot`
- targeted `codex-app-server` plugin-list and skills-list tests
- `git diff --check`

The full TUI and app-server suites were also exercised locally. All
remote-plugin-related coverage passed; unrelated local
sandbox/test-binary failures remain outside this change.
2026-06-28 11:46:25 -07:00
rka-oai bdd282f3bb [app-server] increase currentTime/read timeout (#30384)
## Summary

Increase the external currentTime/read request timeout from 5 seconds to
10 seconds.

## Validation

- just fmt
- Focused app-server test build was stopped to defer validation to CI.
2026-06-27 16:42:03 -07:00
xl-openai 9dbdb4e2c0 [plugins] Enforce marketplace source policy at runtime (#29691)
## Summary

- project effective marketplace/plugin config through the enterprise
source policy so blocked installed plugins become inactive
- filter plugin list/read/discovery and CLI marketplace source/snapshot
reporting using the same policy
- enforce source admission for background marketplace cache refreshes
- continue refreshing/upgrading independent marketplaces and plugins
when one entry fails, returning per-entry errors
- include policy-projected plugin state in cache and refresh keys so
requirement changes invalidate stale results

## Stack

This is PR 2 of 2 and is based on #29690. Review the admission model and
source matcher in #29690 first; this PR contains only runtime
enforcement.

## Test plan

- `just test -p codex-core-plugins` (287 tests)
- `just test -p codex-cli
plugin_list_ignores_implicit_system_marketplace_roots_without_manifests`
- `cargo check -p codex-cli -p codex-app-server --tests`
2026-06-27 15:22:05 -07:00
Max JohnsonandMichael Bolin e2398d0b16 [app-server] expose environment info RPC (#30291)
## Why

App-server clients that configure named execution environments need to
discover an environment's shell and working directory before selecting
it for a thread or turn. Because the environment can run on a different
operating system than app-server, its working directory is represented
as a canonical `file:` URI rather than a host-local path string. The
probe also needs a bounded response time: an exec-server that completes
initialization but never answers `environment/info` must not hold the
environment serialization queue indefinitely.

## What changed

- Add an experimental `environment/info` app-server RPC for named
environments.
- Route the probe through the managed environment connection and return
target-native shell metadata plus the default working directory as a
`PathUri`.
- Return connection and protocol failures as JSON-RPC errors.
- Bound the exec-server probe response to 30 seconds and remove
timed-out calls from the pending-request table so later environment
mutations can proceed.
- Cover successful responses, omitted working directories, unknown
environments, connection failures, and pending-call cleanup.

## Protocol examples

Request:

```json
{
  "id": 42,
  "method": "environment/info",
  "params": {
    "environmentId": "remote-a"
  }
}
```

Successful response:

```json
{
  "id": 42,
  "result": {
    "shell": {
      "name": "zsh",
      "path": "/bin/zsh"
    },
    "cwd": "file:///workspace"
  }
}
```

If the exec-server initializes but does not answer the probe within 30
seconds:

```json
{
  "id": 42,
  "error": {
    "code": -32603,
    "message": "failed to get info for environment `remote-a`: exec-server protocol error: timed out waiting for exec-server `environment/info` response after 30s"
  }
}
```

## Testing

- App-server integration coverage for successful info (including omitted
`cwd`), unknown environments, and connection failures.
- Exec-server RPC coverage verifying a timed-out call is removed from
the pending-request table.

---------

Co-authored-by: Michael Bolin <mbolin@openai.com>
2026-06-27 19:34:10 +00:00
Michael Bolin d2885dc3cd core: stabilize synthesized call output IDs (#30327)
## Why

Response item IDs represent stable conversation identity.
`ContextManager::for_prompt` repairs an unmatched call by synthesizing
an `"aborted"` output in the disposable prompt projection, but that
output previously had no ID. Assigning a fresh ID on every prompt build
would make retries and resumes change otherwise identical model context
and reduce prompt-cache reuse.

The concrete bug is that these normalization-created outputs bypass the
regular item-ID allocation path. Even with item IDs enabled, a prompt
could therefore contain an identified call paired with a synthetic
output whose `id` was missing. This change closes that gap by deriving
the output ID from the source call's item ID. For legacy calls that have
no item ID, the output remains ID-less because there is no stable source
identity to derive from.

The originating call already has a stable item ID under the item-ID
model introduced in #28814. A prompt-only output can therefore derive
stable identity from that call without mutating canonical history or
persisted rollouts. This addresses the failure exposed by #30311 while
keeping normalization read-only outside its detached prompt snapshot.

UUIDv5 is intentional here because it is the standard namespaced,
deterministic UUID construction. Using the output kind and source call
ID as the name produces the same UUID on every projection while keeping
output kinds in separate name domains. UUIDv7 would introduce randomness
and time, so keeping it stable would require persisting the synthetic
repair. UUIDv5 uses SHA-1 internally, but this is only an identity
mapping—not an authenticity or security boundary.

## What changed

- Derive a deterministic UUIDv5 ID for each synthesized call output from
the source call item ID.
- Use the Responses API prefix appropriate for function, custom-tool,
tool-search, and local-shell outputs.
- Preserve the existing insertion position immediately after the
unmatched call.
- Keep synthesized outputs prompt-only; no rollout, task-lifecycle,
compaction, or raw-response behavior changes.

## Testing

- `just test -p codex-core
for_prompt_assigns_stable_id_to_synthetic_output_without_reordering_history`
- `just test -p codex-core
synthetic_call_output_id_is_stable_across_resumes`
- `just test -p codex-core normalize_adds_missing_output`
- `just test -p codex-core response_item_ids`
2026-06-27 10:47:54 -07:00
nhamidi-oai 328e95110c Preserve namespaces on custom tool calls (#30302)
## Summary

- Preserve the optional namespace on custom tool calls during response
deserialization and app-server replay.
- Use the namespaced tool identifier for streaming argument handling and
tool dispatch.
- Regenerate app-server protocol schemas.
- Add regression tests covering namespace serialization and routing.

## Testing

- Ran affected protocol and app-server test suites.
- Ran the full core test suite; two load-sensitive timing tests passed
when rerun individually.
- Ran Clippy and formatting checks.
- Verified with a local end-to-end app-server replay that the namespace
is preserved through the complete request/response flow.
2026-06-27 09:54:56 -07:00
Eric Traut c464468493 Update security check wording (#30317) 2026-06-26 20:05:32 -07:00
Michael Bolin 4f1b5a4b73 app-server: structure and test JSON shutdown logs (#30314)
## Why

`LOG_FORMAT=json` and `RUST_LOG` are supported by app-server, but the
behavior was only covered indirectly. We should verify the actual JSONL
written by both user-facing entry points: `codex app-server` and the
standalone `codex-app-server` binary.

The existing processor shutdown message also always said the channel
closed, even though the processor can exit for several different
reasons. Structured fields make that event more accurate and useful to
log consumers.

## What changed

- Record the processor `exit_reason`, remaining connection count, and
forced-shutdown state as structured tracing fields.
- Add a shared process-test helper that enables JSON logging, validates
every stderr line as JSON, and verifies the top-level timestamp is RFC
3339.
- Cover both `codex app-server` and `codex-app-server`, asserting the
stable `level`, `fields`, and `target` payload.

## Test plan

- `just test -p codex-app-server
standalone_app_server_emits_json_info_events`
- `just test -p codex-cli app_server_emits_json_info_events`
2026-06-26 18:19:56 -07:00
Adam Perry @ OpenAI 3ae0543fdd core: overlap diff root discovery with world state (#30286)
## Why

Remote diff-root discovery is independent of world-state construction,
but it ran afterward and added filesystem metadata latency before the
first model request. Overlap the independent work so thread-cold turns
do not pay those waits serially.

## What

- Run `record_context_updates_and_set_reference_context_item` and
`turn_diff_display_roots` with `tokio::join!`.
- Reuse the same resolved display roots when constructing
`TurnDiffTracker`; no cache or behavior lifecycle changes are
introduced.

## Validation

A synthetic executor-skill benchmark with artificial network delay:
thread-cold model-request p50 improved from about 1.79 s to 1.58 s.
2026-06-26 18:07:41 -07:00
richardopenai d4ec08b8f0 [codex] consume pushed exec-server process events (#30273)
## Summary

- complete unified-exec processes from the ordered event stream instead
of issuing a final zero-wait `process/read`
- add optional executor sandbox-denial state to `process/exited`
- retain `process/read` as a retained-output and compatibility fallback
for receiver lag, sequence gaps, and legacy servers
- recover sandbox-denial state across transport reconnection
- cover the real `TestCodex` remote-exec path without adding a public
test-only event constructor

## Why

A successful one-shot tool call currently receives its output and
terminal notifications, then pays another wide-area `process/read` round
trip before returning. Staging traces showed that remote response wait
accounted for more than 99.8% of RPC time; local serialization,
queueing, and deserialization were below 0.6 ms.

## Measured impact

A direct staging A/B used the same build and route and changed only
completion mode. Each arm ran three times with 30 one-shot
`/usr/bin/true` calls per run. The table reports the median of the three
per-run percentiles.

| Metric | Final `process/read` | Pushed events | Change |
| --- | ---: | ---: | ---: |
| End-to-end completion p50 | 159.5 ms | 118.7 ms | -40.8 ms (-25.6%) |
| End-to-end completion p95 | 182.4 ms | 131.7 ms | -50.6 ms (-27.8%) |
| Completion-wait p50 | 80.1 ms | 41.5 ms | -38.5 ms (-48.1%) |
| Final `process/read` RPC p50 | 79.9 ms | eliminated | -79.9 ms |

TCP_NODELAY was enabled in both A/B arms, so its effect cancels out. The
successful, complete, in-order event path issued zero final
`process/read` calls.

## Compatibility and recovery

- new servers send `sandboxDenied` on `process/exited`
- legacy servers omit it, which triggers one compatibility
`process/read`
- broadcast lag or a sequence gap triggers a retained-output read
- recovery remains bounded by the server's existing 1 MiB
retained-output window
- complete, in-order event streams issue no completion read
- sandbox denial is attached to the exit event before consumers can
observe process completion
- server-first and client-first rollouts remain wire-compatible;
server-first realizes the latency win immediately

## Integration coverage

The `TestCodex` suite exercises four distinct remote-exec contracts:

- complete pushed output/exit/close with zero reads
- direct pushed sandbox denial with zero reads
- legacy missing denial metadata with exactly one compatibility read
- count-bounded replay eviction recovered from retained output without
duplication

## Validation

- `just test -p codex-core
exec_command_consumes_pushed_remote_process_events`: 4 passed
- `just test -p codex-core unified_exec::process_tests::`: 4 passed
- `just test -p codex-exec-server`: 294 passed, 2 skipped
- `just test -p codex-exec-server-protocol`: 5 passed
- `just test -p codex-rmcp-client`: 89 passed, 2 skipped
- focused Bazel `//codex-rs/core:core-all-test`: passed across 16 shards
- scoped `just fix` passed for core and exec-server
- `just fmt` passed

The complete workspace suite was not rerun; focused Cargo and Bazel
coverage passed for the changed behavior.
2026-06-26 18:05:52 -07:00
Anton Panasenko d047c33a1b fix(remote-control): avoid server token refresh retry storms (#30201)
## Why

Remote-control websocket reconnects and pairing requests proactively
refresh their server token. When `/server/refresh` returns a transient
error such as `502`, the still-valid token was discarded as a usable
connection path, causing reconnect failures and repeated refresh
attempts that could amplify an upstream incident.

## What Changed

- Start proactive refresh five minutes before token expiry and
distinguish it from a required refresh for missing or expired tokens.
- Continue websocket and pairing operations with the existing valid
token after `429`, `5xx`, or timeout failures.
- Share an in-memory `next_refresh_at` throttle across websocket and
pairing callers, honoring both `Retry-After` formats and otherwise using
a jittered 24–36 second delay.
- Keep required refreshes strict, preserve `404` enrollment replacement,
and clear token/throttle state for `401` and `403` auth recovery.
- Preserve refresh response metadata internally and add focused
wire-level and integration coverage.

## Verification

Added behavioral coverage proving that:

- a valid near-expiry token still completes websocket and pairing
requests after transient refresh failures;
- `Retry-After` suppresses a subsequent refresh across websocket and
pairing callers;
- request and response-body timeouts are classified as transient;
- an expired token, including one that expires during refresh, cannot
proceed to websocket connection;
- auth failures clear the attempted token without overwriting a
concurrently rotated token.
2026-06-26 17:34:52 -07:00