Commit Graph
74 Commits
Author SHA1 Message Date
jif 9def09afa7 Use serving assessments for adaptive Guardian review (#58075)
## What changed

- Match final serving assessments to their response and output item, then retain them with tool invocations and code cells across waits.
- Use matching assessments instead of asynchronous scoring for adaptive review: low-risk actions can skip synchronous review, while elevated-risk actions require it.
- Revalidate captured authorization and policy before approval. Require fresh review for stale or incomplete authorization, preserve explicit review requirements, and discard assessments when hooks rewrite tool input.
- Keep asynchronous scoring as the fallback when an assessment is missing or does not match.

## Testing

Add integration coverage for direct and nested tool calls, hook rewrites, explicit escalation, interrupted responses, catalog-driven policy, incomplete authorization, and assessment retention across code-cell yields and waits.

GitOrigin-RevId: 4346a227204137f018c03c34b302d6f1e9592c96
2026-10-29 12:54:39 +00:00
swastik-oai 3da7de59b6 Add isolated Guardian assessments for prepared actions (#57834)
## What changed

Add `ReviewInput` to bundle an approval request with its captured parent history and review context. Its `assess_isolated` method runs a fresh reviewer without publishing a live approval, honors deadlines and cancellation, and returns a `GuardianAssessment` or review error.

Share review parameter construction with the live review path and extract assessment parsing and error conversion into `GuardianReviewSessionOutcome::into_assessment`.

## Testing

Add a mock-backed test that verifies the isolated assessment is returned and the reviewer receives the captured history without instructions added after capture.

GitOrigin-RevId: 10dd5fddf5fc58bfab124f5962a6b7f45d435c83
2026-10-28 21:07:36 +00:00
ioanbudea-OAI c6fce1cace Centralize synchronous Guardian prompt preparation (#57790)
## What changed

- Separate evidence collection from prompt preparation and pass reviewer history, model limits, and image preparation policy through shared `guardian-context` APIs.
- Detect captured images before composition and measure reviewer history tokens only when images and a valid context window require it.
- Share instruction and native-message delivery filtering across budget checks, including restoration of retained evidence after history changes.

GitOrigin-RevId: 65ef53cf0bc22e1bde9abfb7a9ffce65cfab6f1c
2026-10-28 17:13:33 +00:00
jif 7c11b8074d Include terminal launch commands in Guardian stdin reviews (#57758)
## Why

Guardian's `write_stdin` approval requests lacked the command used to launch the receiving terminal, leaving reviews without that context.

## What changed

- Carry `original_command` from the terminal's launch command into the approval request and Guardian action JSON. This describes the original launch, not the terminal's current state.
- Exclude `original_command` from the 8,000-byte stdin approval size check so launch context does not consume the budget for input, permission details, and the approval reason. Launch context remains subject to Guardian's normal request budget.

## Testing

Extend serialization coverage to check `original_command` and the strict stdin review integration test to verify that a launch command longer than 8,000 bytes reaches Guardian intact.

GitOrigin-RevId: cc765a6bf80d080baf94c959eafa6227b2889e1f
2026-10-28 15:10:52 +00:00
jif ce2d47bdc4 Move Guardian MCP elicitation helpers into the reviewer crate (#57743)
## What changed

Extract MCP approval elicitation parsing and review-decision response conversion from `core/src/session/mcp.rs` into `codex-guardian-reviewer`. Export the helpers and `GuardianElicitationReview` for the session code to use, while keeping session lookup, provenance checks, and approval enforcement in the host.

## Testing

Move the existing elicitation tests into the reviewer crate, retaining coverage for request construction, opt-in requirements, unsupported forms, decision mapping, and model-specific timeout instructions.

GitOrigin-RevId: fb745fa0e49a29f015bbda16c14b5fc2b12278b9
2026-10-28 13:56:17 +00:00
jif 5d5e5c507d Move ReviewAction into the Guardian reviewer crate (#57720)
## What changed

Export `ReviewAction` and its conversion from `GuardianApprovalRequest` from
`codex-guardian-reviewer`. Keep host-specific approval preparation and environment
validation in core as standalone functions, and update callers accordingly.

## Testing

Move the `write_stdin` serialization and tool-call provenance test into the
reviewer crate, preserving coverage for input, Windows working directories, and
sandbox permission modes.

GitOrigin-RevId: 9a1caf9bbb67ba017e4950a2da9ef2543b013007
2026-10-28 12:31:24 +00:00
jif e6de6a2423 Move Guardian review evidence into the reviewer extension (#57702)
## What changed

Move review evidence storage, authorization snapshots, sender exchange selection,
and bounded Node REPL evidence into `codex-guardian-reviewer`. Update core to
call or re-export these APIs while retaining host-specific context rendering and
capture-mode selection.

Move the existing Node REPL evidence and text truncation tests alongside their
implementations in the reviewer crate.

GitOrigin-RevId: d851cd353cf9f31eb47ce13f43f6f935dc2f5d93
2026-10-28 11:25:13 +00:00
jif 13b0217567 Move Guardian context policy and prompts into the reviewer extension (#57698)
## What changed

Move `GuardianContextMode`, parent compaction checkpoint policy, and reviewer instruction assembly into `codex-guardian-reviewer`. Export the conversation-history prompt and follow-up reminder from the same crate, and update core to use these shared definitions.

Keep session-specific authorization version lookup in core while preserving existing context selection, checkpoint validation, and prompt behavior.

GitOrigin-RevId: a4cadb6c8ad95e756467316b7d8658e8cd527b24
2026-10-28 11:02:51 +00:00
jif d09a5cd8cf Move Guardian review state into the reviewer extension (#57697)
## What changed

Move review state, fork history, checkpoint recovery bookkeeping, and Node REPL evidence admission into `codex-guardian-reviewer`. Expose helpers for session initialization and snapshot publication, and update core to delegate to them while preserving the existing review logic.

GitOrigin-RevId: 56d6a0124301a3c70908614d4bc3bfe970ac1c85
2026-10-28 11:01:32 +00:00
swastik-oai 19d730175f Add isolated reviews to the guardian reviewer pool (#57522)
## What changed

Add `ReviewerPool::review_isolated` to run a review in a temporary session without reading or changing the reusable reviewer. Build the request context without a previous session and spawn without a cached snapshot.

## Testing

Add a test verifying that an isolated review receives no snapshot, uses a separate session, and preserves the prewarmed session for the next regular review.

GitOrigin-RevId: 6cceff0c399f30f3c3303b0bf5232c274c902e3a
2026-10-27 17:29:03 +00:00
ioanbudea-OAI 6574bcdba8 Defer synchronous Guardian heartbeat compression to preparation (#57519)
## What changed

Keep original scheduled messages and heartbeat provenance during synchronous transcript collection. Add `prepare_sync_context` to compress repeated heartbeat instructions across the complete collected transcript before selecting the requested suffix, preserving reference numbering in full and delta prompts.

Route synchronous reviewer prompts through this preparation step and reject composition of unprepared scheduled messages. Move transcript profiles and REPL evidence rendering into the preparation module. Asynchronous heartbeat compression remains in collection.

## Testing

Extend heartbeat transcript coverage to compare prepared full and delta prompts with the existing rendering and verify that direct composition rejects unprepared scheduled messages.

GitOrigin-RevId: c9824b8862021301a1f537a74f83bc7eb20aa0ad
2026-10-27 17:19:51 +00:00
jif 73bdd06fed Extract Guardian planned-action assembly into the reviewer crate (#57509)
## What changed

Move planned-action construction from the core Guardian prompt builder into the exported `codex_guardian_reviewer::build_guardian_planned_action` helper. Keep the existing action kinds, MCP tool and connector descriptions, and reason selection unchanged.

GitOrigin-RevId: 119323523ed2e199c998c1139fb8e6255bc730d9
2026-10-27 16:37:01 +00:00
jif 479f7046eb Move Guardian request mappings into the reviewer crate (#57506)
## What changed

Move approval-request assessment and analytics mappings, target item lookup, and turn ID selection into `codex-guardian-reviewer`. Export the helpers from the crate and re-export them in core, preserving existing behavior.

## Testing

Move the apply-patch serialization test into the reviewer crate. It checks that Windows paths are preserved and patch text is omitted from the assessment action.

GitOrigin-RevId: 3a011db0bc51c653bb0877c4b0cb52eb61c63244
2026-10-27 16:28:42 +00:00
jif 6b56106ed9 Move Guardian action JSON formatting into the reviewer crate (#57493)
## What changed

Move approval request serialization and model-visible action formatting from `codex-core` into `codex-guardian-reviewer`, expose both helpers publicly, and re-export them from core. Preserve the existing JSON shapes and formatting.

## Testing

Move the MCP tool-call and network-access trigger serialization tests into the reviewer crate, retaining coverage for omitted optional fields and Windows path rendering.

GitOrigin-RevId: c0093c023b2f4c1be16bac481f1173a5da6ac25c
2026-10-27 15:49:32 +00:00
jif 3b600d0566 Move guardian prompt composition into the reviewer crate (#57488)
## What changed

Export `GuardianPromptItems` and `compose_guardian_prompt` from `codex-guardian-reviewer`, and delegate prompt composition from core to the new helper. Core continues to collect context sections and choose the history version.

Preserve full and delta transcript selection, empty-transcript placeholders, cursor accounting, and Node REPL evidence sequencing.

GitOrigin-RevId: e3e2b2a87a42709ddb5441f47cbb7461b0130579
2026-10-27 15:39:10 +00:00
jif 75667b341a Move Guardian approval request types into the reviewer crate (#57478)
## What changed

Export `GuardianApprovalRequest`, `GuardianNetworkAccessTrigger`, and
`GuardianMcpAnnotations` from `codex-guardian-reviewer` and re-export them in
core. Move environment lookup and scope classification with the request type,
preserving existing classification and credential-safe debug output.

GitOrigin-RevId: 5253a5124d5e370a1230b46aa7dc48b24b1c902e
2026-10-27 15:01:35 +00:00
jif e344f4b6fc Move Guardian session helpers into the reviewer crate (#57476)
## What changed

Move Guardian session-source detection, the reviewer name constant, and parent-thread prompt cache key generation into `codex-guardian-reviewer`. Re-export them from core, preserving existing behavior.

## Testing

Move the existing prompt cache key test into the reviewer crate, retaining coverage for parent-thread scoping, key length, and missing or inapplicable inputs.

GitOrigin-RevId: c14b3c030ba93676a0799aba56b23a676dbbc56d
2026-10-27 14:56:16 +00:00
jif 50983c7a93 Move Guardian token usage calculation into the reviewer crate (#57458)
## What changed

Export `token_usage_delta` from `codex-guardian-reviewer` and use it in the core review session. Preserve the existing calculation, including clamping negative deltas to zero.

## Testing

Move the existing nonnegative token usage delta test alongside the helper in the reviewer crate.

GitOrigin-RevId: fcfce24b8d50a63dcd1122a4204939bc6750feda
2026-10-27 14:01:44 +00:00
Tom Leach (@toml) 6a6e2fb1f0 Distinguish policy-restricted capacity failures from server overloads (#57452)
## What changed

- Recognize `policy_capacity_unavailable` in HTTP and streaming API errors and expose it as `policyCapacityUnavailable` through the app-server protocol and generated bindings.
- Display “Policy-restricted capacity is unavailable. Please try again later.” while preserving overload retry behavior based on `Retry-After`.
- Handle the new error in TUI overload rendering, reviewer retries, and error telemetry.

## Testing

Add coverage for HTTP and streaming error classification, retry advice, WebSocket terminal error attribution, protocol serialization, and TUI rendering with and without an upstream message.

GitOrigin-RevId: 1b9536fba1e11cc891dcf689aee35410d82f5412
2026-10-27 13:31:38 +00:00
jif ed1b92fa45 Add opt-in synchronous Guardian review for native tool calls (#57433)
## What changed

- Add `CoreToolRuntime::requires_guardian_review` to review opted-in function calls before dispatch and stop execution when review rejects the call.
- Deliver proposed calls as native review evidence, preserving encrypted argument metadata. When hooks rewrite arguments, review the updated arguments and discard the original encrypted replay content.
- Deduplicate native call evidence against reviewer history and include paired evidence outputs in input budgets.
- Keep review accounting and metrics for native calls without emitting action-specific client assessment events, and omit approval payloads from debug output.

## Testing

Extend regression coverage for rewritten native calls across review retries, denied calls that never execute their handlers, oversized native evidence, and review metrics without client events.

GitOrigin-RevId: c3b22c0220344581c2b38f233001abaed49cba34
2026-10-27 11:37:24 +00:00
Charlie Marsh 60adfa8513 Treat model-not-found provider errors as terminal failures (#56445)
## Why

Provider errors with code `model_not_found` should end the turn immediately and preserve the provider's message instead of triggering retries.

## What changed

- Recognize `model_not_found` in HTTP 400, 403, and 404 responses and in streamed `error` and `response.failed` events.
- Preserve the provider message and any available HTTP status, and expose `modelNotFound` through the app-server protocol and generated schemas and SDK types.

## Testing

Add coverage for HTTP classification, statusless stream errors, and terminal failures without retries across HTTP, SSE, and WebSocket responses. Verify that `thread/read` preserves the error reported by the live notification.

GitOrigin-RevId: 88f824ac03c8c9669915b1e40c67b76c08326fbe
2026-10-23 11:43:14 +00:00
Vivian Fang d6817454d7 Make the Guardian review timeout configurable (#56371)
## What changed

Add `auto_review.timeout_ms` to configure the overall Guardian review budget, including setup and retries. Keep the default at 90,000 milliseconds; setting it to `0` disables the review deadline while preserving cancellation, retry attempt limits, and independent transport timeouts.

Carry the configured deadline through review execution and report the configured budget in review telemetry, using zero for unlimited reviews.

## Testing

Add coverage for shared setup budgets, configured timeouts, cancellation with unlimited reviews, and retry attempt limits without a deadline.

GitOrigin-RevId: 00404e0cb2f2cfaf6de183d6e27f5e4a371942a8
2026-10-23 06:34:00 +00:00
ioanbudea-OAI 2213359bd3 Measure Guardian review latency once with a monotonic clock (#55846)
## Why

Guardian review metrics derived duration from wall-clock timestamps, while analytics measured elapsed time when tracking the result. Clock changes and delayed tracking could produce inconsistent latencies.

## What changed

Capture one monotonic duration at review completion and pass it to both metrics and analytics. Preserve wall-clock timestamps for event ordering, and saturate analytics latency conversion at `u64::MAX`.

## Testing

Add a regression test covering skewed wall-clock timestamps and delayed tracking, verifying that the duration metric uses the captured interval and completion timestamps are preserved.

GitOrigin-RevId: 19eafb8e1f1a3d13a751bdc72c218e4cafeae410
2026-10-21 09:52:45 +00:00
ioanbudea-OAI 60d78332fc Measure Guardian approval blocking time per turn (#55591)
## What changed

Record `codex.guardian.turn.blocking_ms` when a turn completes or aborts, with an `outcome` label. Count overlapping approval waits once, exclude idle gaps, and split pending reviews across the active turns they span. Use each turn's telemetry so samples retain the servicing turn's model attribution.

## Testing

Add unit coverage for overlapping waits, idle gaps, late turn completion, and duplicate stops. Extend integration coverage to verify attribution across turns and model changes for yielded command reviews and MCP elicitation, including aborted turns.

GitOrigin-RevId: a3e6a0c32a06fe58ea93119ecd941076100fb82c
2026-10-20 14:43:08 +00:00
jif affa861ddf Roll back interrupted Guardian reviews to preserve evidence (#55395)
## Why

Cancelled or timed-out Guardian reviews can admit transcript evidence without completing a review. Reusing that session can leave subsequent reviews without the evidence they need.

## What changed

Mark interrupted reviews for rollback to the last completed review instead of reusing their live context. Preserve committed review history and replay pending evidence on the next review.

## Testing

Add cancellation and timeout regression coverage that verifies encrypted evidence appears exactly once in the next review, the last completed review survives rollback, and interrupted or denied commands do not execute. Update session disposition assertions and make the program-change session reuse test wait for review completion before releasing the classifier result.

GitOrigin-RevId: f39552b24db5309cffddd9eda97280256be3e97b
2026-10-19 22:03:06 +00:00
ioanbudea-OAI 941b32bf57 Add Guardian retry metrics and preserve turn attribution (#55347)
## What changed

- Record review attempt counts and final outcomes with a `retried` tag.
- Measure retry waits by failure reason and whether the wait ends in a retry, cancellation, or deadline; count retries only when another attempt will run.
- Count required synchronous reviews with the `required_sync` route.
- Use the originating turn's telemetry for Guardian reviews so metrics retain that turn's model attribution.

## Testing

Add metric assertions for attempt counts, retry outcomes, and waits interrupted by cancellation or deadlines. Extend the delayed cached-score integration test to verify route and retry-wait metrics use the originating turn's model after a model override.

GitOrigin-RevId: 681a719ad5dd9e4436cb37b6f5f972cb11a5c890
2026-10-19 18:49:48 +00:00
felixxia-oai 5fff6378d6 Share Guardian image deduplication and checkpoint restoration (#54278)
## What changed

- Add `ComposedContext::retain_new_images` and use it in Guardian review sessions and the async scorer. Compare host-prepared image references against admitted history, ignoring image detail, and skip scanning history when no images need checking.
- Restore `ConversationState` directly from a checkpoint, retaining committed history for rollback or transferring it with `take_history` for ephemeral forks.

## Testing

Extend tests for prepared-image matching across differing detail levels, image-free continuations that avoid scanning history, and checkpoint restoration and history transfer.

GitOrigin-RevId: bafeb6de9babc721182be43d0eb1a653955a0ebb
2026-10-15 12:42:15 +00:00
jif b687844674 Track Guardian transcript admission across failed reviews (#54264)
## Why

A failed Guardian inference can retain its input in a reusable session. Tracking transcript progress only after successful reviews can admit the same evidence again on retry.

## What changed

Advance transcript progress when a failed turn has retained its input and the session remains reusable, without counting it as a completed review or changing the committed fork checkpoint. Leave progress unchanged when failure occurs before input admission.

## Testing

Extend regression coverage for encrypted agent messages across review retries, pending evidence after compaction failures, and fork checkpoints after transcript admission without a completed review.

GitOrigin-RevId: 36239ec9d47f484bcfe68d65e7c8d8ab8660db0d
2026-10-15 11:22:45 +00:00
vkg-oai 3ee99cde70 Track approval cancellation sources and Guardian context changes (#54046)
## What changed

- Preserve approval resolution sources through tool errors and tag cancelled MCP approvals with `error_type=approval`, `error_code=cancelled`, and `approval_source` (`guardian`, `user`, `hook`, or `unknown`). The source identifies the reviewer, not who caused cancellation.
- Record `context_changed` when validating a Guardian allow against changed authorization or review context, even when a concurrent stop or history reset determines the outcome. Retain the flag across retries and fresh-checkpoint recovery, and include it in the Guardian review counter.

GitOrigin-RevId: a19a986a7565f9a78a9bb2eaabdb5651834d28b8
2026-10-14 17:33:28 +00:00
jif 5388581653 Return async Guardian approvals before review cleanup finishes (#54039)
## Why

An asynchronous approval currently waits for the redundant synchronous review to finish cancellation cleanup before returning a decision.

## What changed

Cancel the redundant review and let it drain under the parent's `ReviewerTasks` tracker so a current approval can return immediately. Revalidate the approval and check cancellation before approving the action. Hosts without a task tracker continue to wait for cleanup.

Keep the reviewer reservation held until cleanup completes, and let shutdown join the tracked attempt. Discard late results and evidence from the cancelled review.

## Testing

Add tests covering current, invalidated, and cancelled approvals while cleanup is blocked, suppression of late evidence, reviewer reservations during cleanup, and shutdown waiting for abandoned attempts.

GitOrigin-RevId: f227738e545243f99c19a6c557a78d330f9d2767
2026-10-14 17:10:30 +00:00
jif 835cd7552d Skip service backoff for stale Guardian authorization retries (#53987)
## Why

Stale authorization requires refreshing local evidence, so service retry backoff unnecessarily delays the next review attempt.

## What changed

Yield cooperatively before retrying `StaleAuthorization`, then check cancellation and the shared deadline. Keep retries within the existing attempt budget.

## Testing

Extend paused-time tests to cover recovery with fresh evidence and exhaustion of the shared attempt budget, asserting that retries incur no backoff and return the final attempt's evidence.

GitOrigin-RevId: fda7ddd040a761d08883740bb5e7aaecacfa6091
2026-10-14 13:55:47 +00:00
Dane Schneider 10da569252 Forward per-turn Cyber access programs to Guardian (#52689)
## What changed

Pass the parent turn's `cyber_access_program` to Guardian reviewers and asynchronous classifiers. Use `daybreak_blue` for either Daybreak selection, preserve `standard`, and omit `access_programs` when no program is selected.

Capture the selection with the owning turn so asynchronous observations retain it across later turns. Resolve classifier programs using current authentication and the same provider and API-key feature policy as ordinary model requests.

## Testing

Add regression tests for program changes across reused reviewer sessions with API-key and ChatGPT authentication, snapshot and conversation classifiers at low and high risk, and enabled, disabled, and unsupported-provider API-key policies. Verify parent requests retain their selected program.

GitOrigin-RevId: 447f306df3a6bd6805464b819950690c751b04b4
2026-10-09 20:14:04 +00:00
ioanbudea-OAI 6ac8b1b50b Add structured tracing for Guardian reviews and background scoring (#52274)
## What changed

- Add debug spans with review, thread, turn, and tool-call identifiers to correlate approval reviews and background scoring.
- Log review retry scheduling with failure details, attempt limits, backoff, and remaining deadline budget.
- Emit warnings for Guardian V2 background scoring failures with the failure reason, context mode, and duration, even when metrics are unavailable.

GitOrigin-RevId: 3e20d16836576f834998af473815bfb55e671de5
2026-10-08 21:02:08 +00:00
ioanbudea-OAI be2e129ecd Require assessment text in the Guardian parser (#52065)
All callers already check that an assessment payload is present before parsing it. Change `parse_guardian_assessment` to accept `&str` instead of `Option<&str>` and remove its redundant missing-payload check.

Update the callers and existing parser tests to pass text directly.

GitOrigin-RevId: e4fb4bf7aca5b20f25f5b27300ce9a6f22c97939
2026-10-08 11:01:28 +00:00
olliem-oai 3421c660d0 Roll back stale Guardian reviews before reusing reviewer history (#51683)
## Why

Authorization updates during a pending Guardian approval can invalidate its decision. Retries need the updated guidance without inheriting the invalidated review or losing earlier valid context.

## What changed

- Validate authorization while the reviewer is reserved, before publishing its history checkpoint.
- Roll back stale attempts to the last committed review, preserving earlier valid reviews across repeated invalidations.
- Pin the issuing action's repository instruction snapshot for reviewers and retries, avoiding fresh instruction discovery through disconnected executors.
- Treat stale authorization as a request for a new review rather than a failed decision.

## Testing

Add regression coverage for repeated approval invalidation, retention of earlier valid context, exclusion of stale decisions, and execution of the pending action exactly once. Extend the disconnected-executor test to verify that retries retain repository instructions and use updated authorization.

GitOrigin-RevId: 0bff6cc551fee1f0905082eb97ccdecaa8628867
2026-10-07 13:05:06 +00:00
jif 30bdfec59d Persist Guardian review failures for reports across restarts (#51651)
## Why

Failed Guardian review evidence was process-local, so restarting Codex lost the context needed for later diagnostic reports.

## What changed

- Persist failed-review records in SQLite before reviewer cleanup, retaining at most 64 records globally, eight per thread, and 8 MiB of evidence. Delete persisted evidence when its reviewed thread is deleted.
- Recover and deduplicate persisted and in-memory records for the reported task tree when uploading `auto-review-failures.jsonl`.
- Bound persistence attempts to 250 ms and retain an in-memory fallback when storage is unavailable. Keep capture gated by user opt-in and non-ephemeral sessions, and export evidence only when logs are included.

## Testing

Add coverage for persistence across reopen and process restart, retention limits, cascading deletion, busy-storage fallback, and report uploads with and without logs, including SQLite log failures.

GitOrigin-RevId: ea2da1818d4a5da3da29f211042ca45e834342bc
2026-10-07 11:18:05 +00:00
Adam Perry @ OpenAI 404cd42aa5 Accept environment requests at thread and turn settings boundaries (#51422)
## What changed

Add `TurnEnvironmentRequests` to carry environment requests together with their fallback working directory. Update thread settings overrides and active turn settings to accept requests, constructing `TurnEnvironmentSelection` values in the receiving thread before validation and runtime use.

Adapt app-server callers, reviewer settings, and existing tests to supply requests or explicitly convert runtime selections back into requests.

GitOrigin-RevId: 8028f804bebe3fde553f57bb450f6dca3970cc4a
2026-10-06 17:11:07 +00:00
Eddie Chen cfc946f4e1 Expose and persist turn lineage across the app server (#51415)
## Why

Clients starting delegated work need to attribute descendant turns to the original turn and retain that attribution through completion and history reads.

## What changed

- Accept optional `parentTurnId` and `rootTurnId` in `turn/start`, and expose `rootTurnId` on returned turns and lifecycle notifications.
- Default new turns to their own root when none is supplied. Preserve the active turn's root when steering, ignoring incoming lineage fields.
- Carry root IDs through completion, interruption, recovery, and fork boundaries, and persist them for paginated history reads. Leave unknown roots null in older history.
- Update protocol schemas and generated TypeScript and Python bindings.

## Testing

Extend coverage for default and explicit roots, steering without changing lineage, interrupted and recovered turns, history reads after restart in both history modes, nested fork pagination, and compatibility with older database writers.

GitOrigin-RevId: f1a570a12bd11742929fd2e8b017e5d35aa07dcb
2026-10-06 16:56:39 +00:00
jif 57d57df608 Let late low-risk scores complete pending Guardian reviews (#51396)
## Why

A synchronous Guardian review could keep an action waiting even after an asynchronous score supplied valid low-risk evidence for approval.

## What changed

- In adaptive mode, race the synchronous review against score updates that satisfy the existing cached-approval checks, unless a fresh review is required.
- When asynchronous approval wins, cancel and drain the pending review, then revalidate the action and history lifetime and enforce cancellation and timeout limits before approving.
- Emit an approved review completion without a synchronous assessment or risk level, and use the cached-approval path for the final decision.

## Testing

Add an app-server regression case that holds the synchronous review pending, releases a low-risk score, and verifies approval completes without a risk level. Sequence existing scenarios to finish synchronous reviews before releasing classification results when they test synchronous evidence.

GitOrigin-RevId: 04f5ad6b960b819b565fccb1b85c8039ccbd0479
2026-10-06 15:33:14 +00:00
jif 79cae5f7fb Count Guardian denial-limit interruptions in telemetry (#51334)
## What changed

Increment `codex.guardian.denial_limit_reached` when automatic approval review reaches a turn's denial limit, immediately before interrupting the turn. Record the counter once per turn, matching the denial warning's existing behavior.

GitOrigin-RevId: ec8eeeff6a681a261572496e59cf694e87e813ce
2026-10-06 10:50:06 +00:00
jif f5fa209bb0 Measure total Guardian approval decision duration (#51330)
## What changed

Add `codex.guardian.decision.duration_ms` around the complete approval decision operation, including fast decisions, preparation, and cancellation alongside model review time.

GitOrigin-RevId: e5a8d5a3b9a0ff81e1b866be87b8f3a439ae6a1d
2026-10-06 10:39:52 +00:00
felixxia-oai 16cb72218c Force fresh Guardian sessions for parent-checkpoint recovery (#51139)
## Why

A Guardian review restarting from the parent checkpoint must bypass cached reviewer sessions and snapshots, even when another review is using the cached session.

## What changed

- Add `ReviewerRequest::requires_fresh_session` and enable it for parent-checkpoint recovery.
- Replace an idle cached session with a fresh reusable session, or start a fresh ephemeral session when the cached session is busy. Neither recovery path inherits a cached snapshot.
- Reserve the review permit before validating a cached session and before exposing a newly spawned session to concurrent requests.

## Testing

Add tests covering recovery with idle and busy cached sessions, verifying that recovery receives no cached snapshot and that subsequent reviews reuse the appropriate session.

GitOrigin-RevId: 894f685736da54312336932aa2037e74a20629d9
2026-10-05 17:36:33 +00:00
felixxia-oai 5f300d3f74 Add retained conversation support to Guardian async sampling (#49792)
## What changed

- Add request preparation that preserves committed classifier history and appends transcript deltas, filtering instructions and images already delivered. Account for the complete input budget before transferring history; rejected requests leave the checkpoint and cursor intact.
- Add retained sampling that publishes the early score while collecting completed assistant output and encrypted reasoning for reuse. Preserve item IDs and input metadata, and discard unusable history without retracting an already published score.
- Keep the existing snapshot sampling path and share input preparation and execution with the new retained path. Retained sampling is not yet wired into the active backend.

## Testing

Add coverage for transcript and image deduplication, immutable history prefixes, budget boundaries, rejected preparation, WebSocket output retention, and retention failures that preserve the early score.

GitOrigin-RevId: 0fa33db8b8ea4483eb64d75e207690f1d349123b
2026-10-01 01:11:10 +00:00
felixxia-oai d79a95bdf8 Record Guardian context mode in review and classification telemetry (#49294)
## Why

Guardian review and classification telemetry lacks the context mode needed to distinguish `legacy`, `independent`, and `thread_owned` reviews.

## What changed

- Add `guardian_context_mode` to review and classification analytics and `context_mode` to their metrics.
- Capture the mode from the conversation history snapshot before review preparation or classification setup so failure metrics retain it, including when review preparation or reviewer startup fails.
- Use `unknown` for review metric tags when no context mode is available.

## Testing

Update metric assertions to cover `thread_owned` classification tags and the `unknown` review fallback.

GitOrigin-RevId: 79f7d11b3e4ccfc53681890d75fbc7c54e1ce7de
2026-09-29 16:09:48 +00:00
Won Park d7748e1185 Add opt-in structured errors for Guardian circuit-breaker interruptions (#48796)
## Why

Guardian denial-limit interruptions lack a structured error identifying the cause. Make this opt-in because older clients may not recognize the new error in shared history.

## What changed

- Add `auto_review.circuit_break_action = "strict"` to attach `TooManyDenials` to the interrupted turn. The default leaves the error unset.
- Expose `turn.error.codexErrorInfo = "tooManyDenials"` in app-server notifications and saved history, and update protocol schemas and generated types.
- Preserve the warning, denial limit, and interrupted status without emitting a separate error notification.

## Testing

Add an integration test covering omitted, `default`, and `strict` settings, checking warnings, live turn errors, the absence of separate error notifications, and persisted turn errors after restart.

GitOrigin-RevId: cb5d379e64728d4d7b9daf834c13756e4a70db31
2026-09-27 22:05:19 +00:00
felixxia-oai 86be5320b0 Deduplicate retained instructions across Guardian reviews (#48060)
## Why

Reused Guardian sessions already contain previously delivered instructions. Follow-up reviews can avoid repeating that evidence, but must deliver it again if it changes or compaction removes it.

## What changed

- Track retained source identity, revision, and completeness in host-owned history metadata, preserving revisions during replay.
- Omit retained instructions from synchronous review inputs only when the same complete revision remains in reviewer history.
- Restore missing evidence after reviewer compaction, enforcing the request budget before persisting additions. Classify restored evidence as context rather than new user authorization.
- Keep source-order labels stable across eviction and retain full delivery for legacy records without reliable provenance.

## Testing

Add coverage for consecutive-review deduplication, changed revisions, missing or incomplete metadata, and restoring compacted evidence exactly once. Extend compaction and resume coverage to verify retained revisions.

GitOrigin-RevId: e90fca16cde0a0970da36dd873af2ca1dbaaf4d3
2026-09-25 10:49:50 +00:00
Steve Coffey dafb133c5b Surface Flex capacity failures as a distinct terminal error (#47967)
## What changed

- Recognize `flex_unavailable` in HTTP 429 responses and streamed `error` and `response.failed` events. End normal turns without retries and report `Flex capacity unavailable.`
- Expose `flexUnavailable` through the core and app-server protocols and generated schemas and SDK types.
- Keep Flex capacity failures eligible for Guardian review and sampler retries, with a distinct telemetry classification.
- Map unexpected HTTP responses to `HttpConnectionFailed`, preserving their status codes.

## Testing

Add regression coverage for terminal Flex failures over HTTP, SSE, and WebSocket, HTTP 504 status preservation after a stream retry, and protocol serialization. Update Guardian retry and sampler recovery tests to cover Flex failures.

GitOrigin-RevId: f2e03a6d2d36a6d9748c35952e40397f8670d121
2026-09-24 23:33:38 +00:00
jif 30758e5c77 Add opt-in OTLP logging for Guardian assessments (#47870)
## What changed

Add `otel.log_guardian_assessments`, disabled by default and requiring an OTLP HTTP or gRPC log exporter. Emit `codex.guardian_assessment` when a synchronous Guardian review finishes, including review identifiers, status, risk level, user authorization, and rationale. Include `allow` or `deny` outcomes only for completed model assessments, not review errors, timeouts, or cancellations.

Cap exported rationales at 64 KiB on a UTF-8 character boundary and record their original byte length and truncation status. Use the log-only route to exclude assessment payloads from trace export, local state logs, and bug-report log buffers. Cached V2 approvals are not included.

## Testing

Add coverage for configuration gating, enabled and disabled denial logging, terminal statuses and outcomes, UTF-8 rationale truncation, export routing, and bug-report log buffer exclusion.

GitOrigin-RevId: dcbb5b429c8726a5a5c80ff82f9d625e81796ede
2026-09-24 16:06:07 +00:00
jif 61e23bc6a1 Bind Guardian async scores to target environment permissions (#47830)
## Why

Asynchronous Guardian scoring omitted the target environment's denied-read restrictions, and cached score authorization did not include that permission context. A score from one environment could therefore be reused for an action in another environment with different restrictions.

## What changed

- Share permission resolution between synchronous review and asynchronous scoring, including resolving `write_stdin` targets from the owning terminal session.
- Include environment identity and denied-read paths/globs in async scoring context and cached score authorization.
- Fall back to synchronous review when permission evidence cannot be resolved or exceeds the async limit of 3,000 bytes, rather than omitting restrictions.

## Testing

Add regression coverage for rejecting cached scores with different environments or denied paths, passing the target environment's restrictions to the classifier, and rejecting oversized async permission evidence.

GitOrigin-RevId: 14b6f3454bbea458be037560eb1da47d22874df1
2026-09-24 12:34:04 +00:00
teddywyly-oai 49862b62be Retry Guardian reviews when authorization changes (#47819)
## Why

New user input during a Guardian review invalidated an in-flight approval and aborted the pending action, even when the input was only a status inquiry. Review the action again against the latest authorization evidence so it can proceed or be denied based on the updated instructions.

## What changed

- Treat stale authorization as a retryable review error within the existing attempt budget and shared deadline.
- Refresh authorization evidence for each attempt while keeping the pending action fixed, and record evidence from the completed attempt.
- Preserve cancellation and history-reset aborts, and deny approval if stale authorization exhausts the retry budget.

## Testing

Add and update coverage for parent status updates, authorization revocation, repeated updates, cancellation, history resets, and retry deadlines. Verify that refreshed reviews see the latest input and that the pending action executes exactly once only after approval.

GitOrigin-RevId: c683e2efb6f07840b99d0d34acf0d38c9ddfe9bd
2026-09-24 11:19:16 +00:00