Commit Graph
248 Commits
Author SHA1 Message Date
ioanbudea-OAI 3e9264fb18 Defer synchronous Guardian evidence limits to preparation (#57295)
## What changed

Collect original retained instructions, assistant context, and verified answers before applying synchronous request limits in `guardian-context` preparation. Carry original record sizes through collection, preserving whole-record omission notices, source ordering, and host assistant-context framing.

Apply retained transcript source size checks during synchronous transcript preparation as well.

## Testing

Extend regression assertions for synchronous/asynchronous retained-context parity and equivalent verified-answer omissions when oversized records are filtered during preparation.

GitOrigin-RevId: 9042ee3fe60ebd455f6656b4008efb2acc44ac3d
2026-10-26 22:27:05 +00:00
felixxia-oai 7848e3393c Remove Guardian snapshot-specific context helpers (#56559)
## What changed

Remove snapshot instruction deduplication, separate retained-assistant framing, and the associated omission-metadata special cases. Use `retain_new_instructions` in transcript rendering tests and replace the test-only Decisions snapshot adapter with the conversation adapter.

## Testing

Extend retained-source delivery and incomplete-metadata coverage to both synchronous and asynchronous context profiles. Keep Decisions HTTP, eviction, and cancellation tests exercising the conversation adapter.

GitOrigin-RevId: 3906f7d7349f73931e570ffa649377c3a235317a
2026-10-23 18:50:29 +00:00
felixxia-oai 2d86506823 Exercise retained sampling in Guardian transport tests (#56557)
## Why

The transport tests used a separate, test-only snapshot sampler instead of the production retained sampler, leaving them exercising different response ownership and cancellation paths.

## What changed

Route the transport test helper through `sample_retained` and remove snapshot execution, its active-request supersession bookkeeping, and test-only compaction compatibility fields. Simplify request-token metrics to reflect the remaining admitted-request path.

## Testing

Update tests to verify early score delivery while the retained response remains pending, WebSocket cancellation and connection reuse, and HTTP cancellation before headers or during response draining. Assert that HTTP cancellation releases classification permits.

GitOrigin-RevId: 33250103ff376af6bcd0f81ef27cdcf057f2bc5f
2026-10-23 18:48:35 +00:00
felixxia-oai 4b1cf9a4c9 Use conversations for all Guardian v2 async classification (#56556)
## What changed

- Always use the retained conversation backend for asynchronous classification; keep snapshot sampling test-only.
- Accept legacy `async_classifier_mode` values in configuration and model metadata but ignore them. Emit a startup warning when `[features.guardianv2].async_classifier_mode` is configured.
- Ignore legacy classifier mode differences when checking model-switch compatibility, and fail closed if the conversation backend is missing.

## Testing

Update coverage for legacy configuration warnings, model-switch compatibility, retained approval-review context, and conversation-based scoring.

GitOrigin-RevId: 5e8bb7e4e6e7d1589572f38bfe2498c9fa6825a0
2026-10-23 18:48:10 +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
jif a6839a4812 Skip conversation scoring superseded by newer scores and history (#55913)
## Why

A delayed conversation classification can reach execution after a newer request has already published a score and committed history, leaving it with no useful work to contribute.

## What changed

Pass the classification's sampling timestamp into conversation requests and check for newer scores and retained history before starting inference. Return `Superseded` only when both have advanced; keep requests that can still contribute either a score or history.

## Testing

Add regression tests covering supersession of scores and history separately and together, including a classification delayed by permissions. Verify skipped requests send no inference request and preserve cached scores, approvals, and score progress.

GitOrigin-RevId: ef78a59e2010a82ac4f1fb93568a562447187099
2026-10-21 14:43:51 +00:00
swastik-oai 2f5e242d9f Omit reasoning and compaction from Decisions snapshot comparisons (#55666)
## Why

Decisions snapshot comparisons reject requests containing reasoning or compaction, while conversation comparisons already omit those items. A parent compaction also causes snapshot comparisons to be rejected.

## What changed

- Share filtering of reasoning, compaction, and context compaction across both comparison modes, and ignore parent compaction when building the Decisions request.
- Distinguish malformed request setup from unsupported input items. Record setup errors as failures and unsupported input items as skipped comparisons.

## Testing

Extend the HTTP contract test to cover both comparison modes with reasoning, compaction, context compaction, and parent compaction while preserving message content. Update assertions for the distinct setup and unsupported-input errors.

GitOrigin-RevId: e3ba0cce3b6457b3e3eab3589352b70288cbb1ef
2026-10-20 20:21:14 +00:00
swastik-oai a13ab7e4ed Enable Decisions comparisons for Guardian V2 conversation mode (#55635)
## Why

Guardian V2 previously skipped optional Decisions comparisons in conversation mode as unsupported evidence.

## What changed

- Start comparisons from the prepared conversation input, including retained history or rebuilt evidence after a history reset.
- Extract the classifier rubric and preserve evidence message roles, content order, and boundaries. Omit retained reasoning and compaction items while continuing to reject other unsupported evidence.
- Measure baseline sampling through the usable score, before history draining and commit, and report skipped comparisons when preparation fails or the request is superseded.

## Testing

Extend coverage to both classifier modes for comparison disagreements, failures, and disabled or uninitialized comparisons without changing baseline scores. Verify conversation evidence across history reuse and resets, malformed input rejection, and budget failures before either backend sends a request.

GitOrigin-RevId: ce32cf876d15d3b82e0b83ac02c33447e7724a51
2026-10-20 17:21:31 +00:00
swastik-oai aa081afb1b Refactor Guardian v2 Decisions snapshot comparison (#55623)
## What changed

- Rename the snapshot comparison entry point to `start_snapshot_comparison` and extract request spawning into `spawn_request`.
- Accept a `ContentItem` rubric and an iterator of evidence in the request adapter.
- Read the Decisions comparison feature flag once per classification and simplify the budget rejection test setup.

GitOrigin-RevId: b4a294eeecb6069db0f80ff6e4f13f558cbd7815
2026-10-20 16:31:41 +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
swastik-oai 464add4958 Separate Guardian conversation preparation from execution (#55533)
## What changed

Split retained conversation scoring into `Reservation::prepare` and `PreparedConversation::run`, exposing the complete admitted input before model execution. Keep the history fork and capacity permit owned by the prepared conversation, and recheck authorization, score expiry, and backend generation before execution.

## Testing

Extend conversation tests to verify that preparation sends no model request, execution uses the prepared input, dropping a prepared conversation releases capacity, and stale prepared reviews cannot start model execution.

GitOrigin-RevId: c96cc6fac69179a78ecd7bcdb8e5a4b3087aa6e6
2026-10-20 10:52:46 +00:00
jif e645309723 Deduplicate native agent messages in Guardian review context (#55391)
## Why

Full-transcript fallback can select encrypted agent messages already present in the reviewer's history. These duplicates should not consume the input budget or displace new evidence.

## What changed

- Reconcile native agent messages with the effective reviewer history and earlier messages in the pending input before budgeting, including after compaction.
- Deduplicate messages with nonempty IDs while preserving messages without IDs. Allow delivery again when the prior copy is absent from the current history.
- Reject conflicting authors, recipients, or content under the same ID without modifying the pending context.

## Testing

Add coverage for duplicate admission, conflicting payloads, redelivery after history removal, and retained reviewer requests. Extend the history eviction regression to verify that full-transcript fallback reuses the reviewer and preserves a single encrypted agent message.

GitOrigin-RevId: 97e90f6359a7cf5a75d1c5967fc98cd885afb4e4
2026-10-19 22:01:41 +00:00
ioanbudea-OAI eb354a928b Add Guardian review routing and cached score metrics (#55237)
## What changed

- Count adaptive reviews and record synchronous review routes as `async_fallback` or `required_sync`, with the review reason in snake case.
- Record cached score readiness and score age in milliseconds, measured from input sampling time and including inference time.

## Testing

Extend approval tests to assert fallback routing, adaptive review counts, score readiness, and sampled score age.

GitOrigin-RevId: 1200b3297add6c4467e460de87b4a6d8d31e1fc4
2026-10-19 10:22:38 +00:00
ioanbudea-OAI 9dc3a1ce7e Record Guardian sampling retries, attempts, and delivery outcomes (#55234)
## What changed

- Add sampling retry counters that distinguish transport retries from authentication recovery, with failure reasons.
- Record attempt counts and final outcomes for successful, failed, cancelled, and superseded sampling requests.
- Carry retained-score telemetry until the consumer accepts or discards the score, so queued scores that expire are recorded as superseded and accepted early scores remain successful even if response draining fails.

## Testing

Add metric assertions for transient recovery, retry exhaustion, authentication recovery, cancellation, supersession, and retained-score acceptance or discard, including expiry while a score is queued.

GitOrigin-RevId: 36babd6f431f22cf15b73355e6e026a256a81004
2026-10-19 09:48:19 +00:00
ioanbudea-OAI 99f617bf74 Bucket admitted Guardian request metrics by input size (#55226)
## Why

Guardian request counts grouped by input size should reflect admitted sampling inputs without counting synchronous transport retries more than once.

## What changed

- Add a shared `token_bucket` label to admitted total-input observations in `codex.guardian.context.request_tokens` for synchronous and asynchronous reviews. Use inclusive upper bounds in 20k-token steps through 240k, followed by 256k and overflow buckets.
- Record synchronous request tokens after budget admission, once per sampling step, including the complete input. A fresh step counts again even when its input is identical.
- Preserve asynchronous component histograms for oversized classifications, but omit `token_bucket` so rejected inputs do not contribute to counts grouped by that label.

## Testing

Add coverage for bucket boundaries, synchronous retry deduplication and budget rejection, asynchronous retained-history reuse and reset, and admitted versus oversized classification metrics.

GitOrigin-RevId: fac2f102a4c48c5fd21d56bfa701b95a1ff852d0
2026-10-19 09:03:12 +00:00
Charlie Marsh 1cc7dc8f2a Share additional tool declarations across response item clones (#54945)
## Why

Cloning `ResponseItem::AdditionalTools` deep-copies its tool declarations for history and request copies.

## What changed

Store `tools` in an `Arc<[serde_json::Value]>` so clones share immutable declarations. Update constructors and existing test fixtures to use the shared representation.

GitOrigin-RevId: eb8831774afb45fe8431a796f34ae9d1243e884a
2026-10-17 23:17:51 +00:00
pakrym-oai ce0323f2f2 Support typed content in contextual prompt fragments (#54776)
## Why

Contextual fragments and extension-owned world-state sections currently return strings, limiting them to text content.

## What changed

- Return `ContentItem` from fragment bodies and rendering, preserving classification and attribution. Apply text markers only to `InputText`; pass other content through unchanged.
- Allow extension prompt and world-state contributions to carry typed content, and preserve media in context-window hints.
- Hash non-text world-state fragments by their serialized content and role while retaining the existing text hashing behavior.
- Add shared content-to-tool-output conversion that preserves image references, image detail, and audio.

## Testing

Add coverage for typed world-state hashing and preservation of image content and attribution. Expand code-mode output tests to cover input text, output text, file-backed and inline images, and audio.

GitOrigin-RevId: 2ed00d466a3f169b151202f3eef71e667ea64be1
2026-10-17 04:02:21 +00:00
swastik-oai 144779cd24 Preserve evidence message structure in Guardian Decisions requests (#54589)
## Why

The optional Guardian Decisions comparison rejected non-user messages and trusted skill evidence, and folded trusted tool evidence into the classification rubric.

## What changed

Send evidence as separate messages with their original roles, content order, boundaries, and optional `phase`. Support both `input_text` and `output_text`, keeping trusted tool and skill evidence separate from the rubric. Continue to accept inline images only in user messages and reject unsupported evidence.

## Testing

Update adapter and HTTP contract tests to cover mixed message roles and assistant output. Extend lifecycle coverage to verify that trusted skill evidence reaches Decisions while comparison results leave the baseline risk unchanged.

GitOrigin-RevId: 1b6814fe6db5891fb61604d6846a008c9e456054
2026-10-16 12:35:55 +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
swastik-oai 1f7fe9b0af Distinguish unsupported evidence in Decisions comparison metrics (#54057)
## Why

Unsupported evidence currently shares a single Decisions comparison reason, making it difficult to distinguish why a comparison was skipped.

## What changed

Report separate reasons for unsupported developer messages, other non-user messages, trusted skills, images, and audio. Keep these outcomes classified as `skipped` and retain the generic reason for other unsupported evidence. Expose `TrustedSkills::KIND` for identifying trusted skill fragments.

## Testing

Expand adapter tests for the distinct rejection reasons and add a lifecycle case verifying that trusted skill evidence skips the Decisions request, reports `trusted_skills`, and preserves the baseline score.

GitOrigin-RevId: 98f076d1aa6771d0209e7f5910eed0dcc40c6263
2026-10-14 17:57:29 +00:00
tongzhou wang 1b6e0d8145 Track content provenance through prompt assembly and compaction (#53831)
## Why

Message roles and content classifications do not identify who supplied each context part. Source attribution needs to survive prompt assembly and history truncation, including messages that combine text from different producers.

## What changed

- Add per-part `ContentItemMetadata` for user input, developer instructions, `AGENTS.md`, skills, harness context, command hooks, and tool context with optional callable namespaces.
- Carry attribution alongside content and classifications through contextual fragments, extension prompts, hook output, and agent messages. Keep tool-provided context-window hints separate from harness text.
- Preserve the source of retained text slices during compaction and attribute generated truncation notices to the harness. Default missing historical attribution to unknown.
- Attribute host MCP calls using cached tool namespaces only when catalog revisions remain stable, without starting servers or refreshing catalogs for attribution.
- Send the new metadata to Responses Lite and strip it from requests to endpoints that do not support it.

## Testing

Extend compaction tests to cover mixed sources, missing or extra metadata entries, and discarded media. Update Responses Lite request assertions to verify endpoint-specific attribution handling.

GitOrigin-RevId: b0ebc929b7c60f3ec49d1affbf897312d63edcc8
2026-10-14 02:01:49 +00:00
felixxia-oai 4d82d36ccf Default Guardian v2 async classification to conversation mode (#53733)
## What changed

Use `conversation` when neither a local `async_classifier_mode` override nor a model default specifies a mode. Keep `snapshot` available as an explicit override and update the configuration documentation and schema to describe the new fallback.

## Testing

Expand configuration tests to cover all local override and model default combinations. Update app-server approval tests to exercise conversation mode without an explicit override, and explicitly select snapshot mode in tests that depend on it.

GitOrigin-RevId: a62479a3f6454bf28d589373a236d8b0ab5023b9
2026-10-13 18:08:10 +00:00
felixxia-oai f6aca7dc46 Cancel Guardian V2 classifications that exceed the tool-call lag window (#53699)
## Why

Pending classifications can outlive the `max_tool_call_lag` window in which their scores are reusable, keeping metadata waits or classifier transports active after the result becomes stale.

## What changed

- Expire pending classifications when tool-call progress exceeds the configured lag allowance, preserving the wrapper discount while nested code-mode actions remain active.
- Cancel metadata waits and sampling in snapshot and conversation modes, including snapshot response drains after an early score.
- Treat expiry as supersession, preserving cached scores and the last completed conversation checkpoint and transcript cursor.

## Testing

Add regression coverage for lag boundaries, active wrapper discounts, transport cancellation before and after early scores, expired requests skipping preparation, and conversation history and transcript deltas surviving cancellation.

GitOrigin-RevId: 892ff13a05fd2b1573cef9842b934d1fc865d951
2026-10-13 15:25:12 +00:00
felixxia-oai ffc1402633 Interrupt and drain canceled classifier responses before socket reuse (#53698)
## Why

Canceled classifier requests need bounded cleanup that preserves received token usage and returns only safe WebSocket connections to the pool.

## What changed

- Own classifier response streams and connection leases together, interrupting dropped responses with a one-second cleanup deadline.
- Require a matching interruption acknowledgement and response completion before reusing a canceled response's socket. Retire sockets on rejection, invalid acknowledgements, or timeout while preserving any received completion and token usage.
- Skip requests canceled before dispatch and return their unused sockets to the pool.
- Distinguish cancellation from ordinary steering, which continues draining without requiring an interruption acknowledgement.

## Testing

Add regression coverage for cancellation, acknowledgement ordering and failures, cleanup timeouts, socket reuse, and token accounting under backpressure. Extend steering tests to cover rejected and missing acknowledgements.

GitOrigin-RevId: c4e7aac49d36cea2c2d0e9f2ba5f6147f67471dd
2026-10-13 15:24:00 +00:00
ioanbudea-OAI 979771476a Account for replay caches in encrypted compaction budgets (#53691)
## Why

Encrypted compaction payloads can include sampled-token replay caches that increase their size roughly threefold. Budgeting them as ordinary text can reject checkpoints that fit the model context budget.

## What changed

Use a shared estimate of one token per twelve ciphertext bytes, rounded up, for encrypted `Compaction` and `ContextCompaction` items in history and Guardian context budgeting. Guardian continues to count framing and metadata separately.

Check parent compactions against the configured token budget and a separate hard wire-size limit. Preserve the complete encrypted checkpoint when it fits. The token estimate remains a heuristic and can underestimate legacy checkpoints without replay caches.

## Testing

Add coverage for token-estimate rounding, parent compaction token and wire-size limits, and reviewer continuation with a cached compaction preserved intact.

GitOrigin-RevId: cc18ca29802491865167eef992830efcf93d97da
2026-10-13 15:05:16 +00:00
swastik-oai 90f00bd89e Add an environment API key fallback for Guardian Decisions (#53633)
## What changed

Allow Guardian Decisions to use `OPENAI_API_KEY` when the default `openai` provider has no custom base URL and neither `CODEX_GUARDIAN_DECISIONS_API_KEY` nor a cached API key is available. Preserve cached API key precedence over the environment fallback.

Report missing credentials as `credentials_unavailable` instead of `provider_error` in Decisions failure metrics.

## Testing

Add tests for cached API key precedence and the environment fallback with ChatGPT authentication. Run each test in a child process to isolate environment changes.

GitOrigin-RevId: fbb772dcb9287d9e1be1b34292ad9bdffeb3d6b3
2026-10-13 10:43:13 +00:00
jif bc9cad3473 Treat incomplete responses as terminal errors (#53451)
## Why

Incomplete responses such as `max_output_tokens` were classified as stream errors, allowing retries and compaction model fallback after the response had hit its output limit.

## What changed

Introduce `ResponseIncomplete` errors that preserve the server-provided reason and stop stream processing immediately. Make these errors non-retryable and stop compaction without falling back to the selected model. Record incomplete responses separately in sampler failure metrics.

## Testing

Add regression tests that verify incomplete responses surface a terminal error without retries over SSE and WebSocket, and that compaction stops without retrying or switching models for both local and remote compaction.

GitOrigin-RevId: 6e107d441b9bf03fa47ea47b88eeb94b71a9f729
2026-10-12 18:53:49 +00:00
ioanbudea-OAI cab328f275 Distinguish Guardian parent-compaction failure reasons (#53393)
## Why

The generic `parent_compaction_error` classification metric does not distinguish serialization failures, oversized compactions, and unusable compactions.

## What changed

Record separate `failure_reason` values for each case: `parent_compaction_serialization`, `parent_compaction_oversized`, and `parent_compaction_unusable`.

## Testing

Extend parent-compaction reuse tests to cover unusable checkpoints in parent-context mode and assert specific failure reasons. Verify rejected compactions receive the maximum risk score, provide no cached approval, and do not reuse stale context.

GitOrigin-RevId: 103c4173b2ebbdc33eb71bce7f8ecb56f73055f6
2026-10-12 14:16:27 +00:00
swastik-oai 27e6192e84 Use cached login credentials for Guardian decisions (#53389)
## Why

Reading `OPENAI_API_KEY` directly bypasses login credentials reloaded by `AuthManager`.

## What changed

Use the API key from `AuthManager`'s cached authentication for Guardian decisions when the provider is `openai` and has no custom base URL. Keep `CODEX_GUARDIAN_DECISIONS_API_KEY` as the highest-priority override.

## Testing

Add a regression test covering a reloaded API-key login, override precedence, and rejection of the login-key fallback for a custom base URL. Assertions avoid printing credentials on failure.

GitOrigin-RevId: 10b2e6c28d3268c3808c25b2be94d9b6c31f597a
2026-10-12 14:08:33 +00:00
pakrym-oai 5ef96ab278 Add opt-in output token replay for OpenAI requests (#52742)
## What changed

- Add the disabled-by-default `output_token_replay` feature to request `output.encrypted_content` from OpenAI providers.
- Preserve encrypted message and tool-call output, message and function-call status, and output-text `annotations` and `logprobs` through history and replay. Update the generated protocol schemas and SDK types.
- Strip output ciphertext from requests to other providers while retaining it in stored history, including after replay is disabled. Remove encrypted content from memory extraction inputs.

## Testing

Add integration coverage for the feature/provider combinations, metadata replay across follow-up requests, and history preservation when resuming with replay disabled.

GitOrigin-RevId: 77729a021b6771933402aebe74ece8eb39c057e2
2026-10-10 01:25:00 +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
Adam Perry @ OpenAI 806d2d1cc1 Remove per-content source attribution metadata (#52329)
## What changed

- Remove `ContentItemMetadata`, provenance and namespace types, and the `content_item_metadata` protocol field while retaining `content_item_kinds` classifications.
- Simplify context fragments, extension contributions, and hook output to carry content without source attribution. Return MCP tool results directly without an attribution wrapper.
- Render context-window hints together in a single text fragment.

## Testing

Update Responses and Responses Lite request assertions to expect content-kind classifications without per-content attribution, and adapt context, hook, and extension tests to the simplified types.

GitOrigin-RevId: 201894cd4c93c6d4b4c41c845e7a9af1dd3c95ca
2026-10-08 23:57:36 +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
Ankush Gupta 75e0b4088e Add opt-in Guardian trust for orchestrator connector identities (#52250)
## What changed

Add the disabled-by-default `guardian_trust_orchestrator_connectors` feature flag. When enabled, Guardian V2 accepts connectors with nonblank IDs from the host-owned plugin service orchestrator as a trusted source without requiring a matching user configuration declaration.

Distinguish orchestrator provenance from user configuration in trusted-tool context. Trust remains scoped to the exact server or connector identity and source; descriptions, outputs, other tools, and other connectors remain untrusted.

## Testing

Add coverage for host-owned connector context, rejection of extension-owned Apps lookalikes and blank connector IDs, source-specific trust metadata, and context token limits. Snapshot the connector approval request history.

GitOrigin-RevId: fbd87dd71110ca7b2b92d50eef02e1e739a74a02
2026-10-08 20:04:38 +00:00
tongzhou wang ad54b75574 Track source attribution for individual context parts (#52195)
## What changed

- Add `ContentItemMetadata` to distinguish user input, developer instructions, `AGENTS.md`, skills, harness context, and tool-supplied context independently of message role and content classification.
- Keep attribution attached to content through prompt assembly, history processing, and hook-output spilling. Distinguish command hooks from MCP hooks and retain tool namespaces when known.
- Treat missing historical attribution as unknown and send per-content metadata only to Responses Lite.

## Testing

Update request and history assertions to cover attribution persistence and Responses Lite metadata handling.

GitOrigin-RevId: 24e56005f5bdb98bf82f2b3943f29c4c81f3d587
2026-10-08 17:56:54 +00:00
felixxia-oai 624b45c4dc Run Guardian conversation classifiers concurrently and preserve action order (#52061)
## Why

A conversation classifier waiting for preparation or full response completion can block newer classifications. Concurrent reviews also need to prevent a later action's evidence or low-risk score from being reused for an earlier action.

## What changed

- Run conversation classifications independently, forking the latest compatible completed history from an earlier action. Only a valid completion with a newer action index can replace retained history.
- Keep admission and observation ordering atomic, and hold capacity permits through full response completion.
- Reject cached low-risk scores from later actions for tool-linked approvals, including initial approval checks.
- Track originating tool-call IDs separately from approval display IDs, preserving stdin write provenance and excluding synthetic MCP elicitation IDs from tool ordering.

## Testing

Add regression coverage for delayed preparation, capacity admission, out-of-order completion, cancellation, invalid retained output, and history snapshots. Exercise pending approval ordering in both `snapshot` and `conversation` modes, and verify linked and unlinked MCP elicitation provenance.

GitOrigin-RevId: 097476ccb3b8718369a69f55c3c39132f7f1a4c1
2026-10-08 10:42: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 5b0b253035 Stabilize Guardian snapshot prefixes by separating assistant context (#51627)
## Why

Retained assistant context changes as the conversation grows. Keeping it separate from retained user instructions lets independent Guardian snapshots preserve a reusable instruction and transcript prefix.

## What changed

Move retained user instructions before the transcript and place assistant originals and their omission notice in a separate `RETAINED ASSISTANT CONTEXT` section afterward. Preserve evidence, delivery roles, source metadata, and deduplication across both retained sections. Clear omission delivery metadata when a split assistant notice cannot be attributed to a single section.

## Testing

Add regression coverage for prefix stability as assistant context and previous reviews change, evidence preservation, repeated preparation, and deduplication. Update approval-routing and scorer tests to check the new section order and retention of assistant text outside a smaller transcript budget.

GitOrigin-RevId: 15cda59d24bee0106f6a66c067f6a790fa91df69
2026-10-07 09:07:52 +00:00
felixxia-oai b2592701e1 Keep Guardian transcript records structured through budget recovery (#51466)
## What changed

Introduce `TranscriptRecord` and `PreparedTranscript` to retain attributed transcript text through preparation and composition. Cache rendered content, byte counts, and token estimates, refreshing them when text or framing changes.

Keep JSON records structured during budget recovery so truncation replaces only `text`, preserving metadata, field order, and framing without reparsing serialized JSON. Preserve whole-entry truncation for line transcripts and update synchronous and asynchronous consumers to use the preparation API.

## Testing

Expand coverage for cached estimates and delivery with escaped text, Unicode, and large payloads; metadata and framing preservation during recovery; and stable asynchronous history prefixes in both line and JSON formats.

GitOrigin-RevId: 8b3b5231ca4a6ee47d17dcc788ea68c56dd1a9bc
2026-10-06 19:31:24 +00:00
felixxia-oai 61969074a7 Add an optional JSON transcript format for Guardian (#51465)
## Why

Transcript content can contain forged role headers, transcript boundaries, or claims of user approval. Guardian needs to distinguish that content from host-assigned authorship metadata.

## What changed

- Add `features.guardianv2.transcript_mode` with `line` (the default) and `json` options for synchronous review and asynchronous scoring.
- Render JSON transcript entries with host-assigned metadata and escaped `text`, and prepend matching provenance instructions to reviewer and classifier prompts.
- Preserve JSON metadata when budget recovery shortens historical text, and keep provenance instructions outside the configured classifier prompt limit.

## Testing

Add coverage for forged roles and approvals remaining within their original entries, JSON metadata surviving budget recovery, and provenance instructions surviving prompt limits. Extend review and scoring integration tests to verify JSON evidence and matching instructions.

GitOrigin-RevId: 81a3580390d3c4d1a664e554976cda5f1adc9a2c
2026-10-06 19:30:57 +00:00
jif a4ebc509f4 Prevent later Guardian scores from releasing earlier pending reviews (#51400)
## Why

A low-risk score for a later action could release an earlier pending Guardian review when the thread's score lag reached zero, bypassing that action's synchronous review result.

## What changed

Track the accepted score's source action and allow it to release a pending review only when it comes from that action or an earlier one. Keep cached-score approval available before synchronous review starts, but prevent the initial computer-use allowance from releasing an already pending review.

## Testing

Add an app-server regression test with two pending reviews: a later low-risk score approves its own action while the earlier action remains pending and honors its synchronous denial.

GitOrigin-RevId: ed8b9c4793b2538f634edfc5699797a6983358cc
2026-10-06 15:43:56 +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 73178e7ca6 Keep Guardian v2 WebSocket pools warm with concurrent replenishment (#51378)
## Why

Serial connection opens let a stalled handshake delay healthy sockets. Waiting until the idle pool is empty to refill also leaves classification bursts using HTTP fallback.

## What changed

- Open up to four WebSockets concurrently and start replenishing when the idle pool falls to half capacity. Preserve successful in-flight opens when another open fails or times out.
- Make explicit prewarming wait for an existing refill before checking readiness.
- Add `ResponsesWebsocketClient::connect_with_connector` and reuse one connector per sampler, initializing TLS configuration on a blocking task while retaining per-connection authentication and destination policy checks.
- Record connection lease durations for admission, setup, and total time, tagged by transport.

## Testing

Add regression tests for a stalled handshake alongside a healthy socket and replenishment before the last idle socket is leased. Update cooldown, authentication, and transport retry tests to account for concurrent handshake completion.

GitOrigin-RevId: f4a8258977c1f2a58e00c6badc7b599280ef22ad
2026-10-06 14:42:57 +00:00
pakrym-oai c9253c4977 Send base instructions as Responses input messages (#51156)
## What changed

Move base instructions from the top-level `instructions` field into a prefixed `developer` message in `input` for standard Responses requests, matching Responses Lite. Remove the field from HTTP and WebSocket request types and assign instruction messages stable IDs derived from the thread and instruction text.

## Testing

Extend standard and Responses Lite tests to cover instruction message serialization, stable IDs, and resume consistency. Update WebSocket tests to verify that changed instructions trigger a full request without `previous_response_id`.

GitOrigin-RevId: e2de4b8e30a9339377fac133ceda981abd1a112b
2026-10-05 18:52:51 +00:00
swastik-oai 4c9f42f4f8 Allow Guardian Decisions to fall back to OPENAI_API_KEY (#51133)
## What changed

Use `OPENAI_API_KEY` for the Guardian Decisions sampler when `CODEX_GUARDIAN_DECISIONS_API_KEY` is absent, the provider is `openai`, and no custom base URL is configured. Preserve dedicated-key precedence, including empty values, and do not fall back for other providers or custom base URLs.

## Testing

Add a credential-selection test covering fallback, dedicated-key precedence, empty dedicated keys, and provider and base URL restrictions.

GitOrigin-RevId: a2a62c28789597f013544b51e142b21f9e214080
2026-10-05 17:24:06 +00:00
swastik-oai 823ea830c0 Preserve trusted-tool context in Guardian Decisions requests (#51070)
## Why

The Decisions adapter rejected developer messages, including host-annotated trusted-tool context. Requests containing that context could not be classified.

## What changed

Append developer text annotated with `TrustedTool::KIND` to the classification rubric, preserving its authority while keeping user evidence in the input messages. Accept only a single text part with a single matching annotation; continue rejecting other developer messages and unsupported evidence.

## Testing

Add a regression test covering trusted-tool context alongside untrusted user text, plus rejection of incorrect roles, missing or mismatched annotations, multiple annotations or content parts, and image content.

GitOrigin-RevId: 65b6301b2ee1ac54d67275978ccb5e37dcac7c16
2026-10-05 10:16:03 +00:00
swastik-oai 315f0efb34 Scope Guardian V2 response timing to snapshot sampling (#51065)
## What changed

Measure `responses_duration` directly around `sampler.sample()` in the snapshot classification path. Leave it unset for conversation classification instead of timing submission and waiting for the score.

GitOrigin-RevId: 4cfac9db6f19f3c8513d7bf839ea9631d41bf3ac
2026-10-05 09:52:25 +00:00
swastik-oai ca466061d6 Record Guardian V2 Decisions agreement and latency metrics (#50273)
## What changed

Record `agree`, `disagree`, or `unavailable` comparisons between Decisions risk classifications and accepted Responses scores. Emit paired latency histograms only when both backends succeed, and include request preparation and queue time in Decisions duration. Report unavailable comparisons when the comparison feature is enabled but the Decisions sampler is not initialized.

## Testing

Extend lifecycle coverage for an uninitialized Decisions sampler, checking skipped outcome and unavailable comparison metrics while preserving the baseline score.

GitOrigin-RevId: f11789ab5d5fd6957b7913d849bbb2ae7006d3ed
2026-10-02 10:44:29 +00:00
swastik-oai 59f18e8133 Add opt-in Decisions comparison for Guardian V2 (#50099)
## What changed

Add the disabled-by-default `guardianv2_decisions_comparison` feature to run Decisions alongside Guardian V2 snapshot classification using the same policy and evidence. Initialize the comparison sampler with `CODEX_GUARDIAN_DECISIONS_API_KEY`.

Publish the baseline score before awaiting comparison results, and keep comparison results and failures from changing approvals. Apply Guardian's input token budget, skip conversation evidence, and cancel comparison work when the baseline classification is superseded. Record success, failure, and skip outcomes with bounded diagnostic reasons, including setup failures.

## Testing

Add lifecycle tests covering disabled comparison, disagreeing classifications, backend failures, unchanged published scores, matching policy and evidence, and rejection of over-budget requests before either backend sends them.

GitOrigin-RevId: 743d34c8ee440362da94f001058366027b39bd11
2026-10-01 21:05:10 +00:00
swastik-oai d91294c39e Add a bounded Decisions transport for Guardian comparison classification (#50066)
## What changed

Add a Decisions sampler under `#[cfg(test)]` for Guardian's optional comparison classifier, without wiring a runtime caller.

- Encode text and inline image evidence as a `guardian_risk` choice request using `gpt-6-luna`, accepting only `low` or `high` responses. Reject the complete request when evidence cannot be represented.
- Bound concurrency to 16 requests, cancel the oldest unfinished request at capacity, and abort unfinished work when its owning task is dropped.
- Enforce a six-second HTTP deadline, an 8 MiB inline image data limit, and a 16 KiB response limit. Keep credentials and wire bodies out of errors.

## Testing

Add tests for the HTTP contract, unsupported evidence, inline image preservation and size limits, response validation, oldest-request cancellation, and capacity release when a caller is dropped while awaiting completion.

GitOrigin-RevId: e7209ca49a04505acf10ff1aeaca941514589e13
2026-10-01 18:28:26 +00:00