## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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