## What changed
- Expand the Guardian sampling pool from 8 to 16 WebSocket connections.
- When the pool is full, supersede the oldest request that has already produced a score before replacing an unfinished classification. Treat superseded classifications as a no-op in the extension.
- Stop response WebSocket work when its event consumer is dropped, including while waiting for the connection lock or draining a completed sample.
- Allow retries across both initially warmed connections for retryable stream failures.
## Testing
- Add a concurrent sampler test that fills the pool and verifies scored drains are replaced before an unfinished classification.
GitOrigin-RevId: 9e4df7b01516094726ff3e11878f8ca742d21b03
## What changed
- Give approval review contributors the first opportunity to resolve an action when automatic review is not required for the model.
- Return an extension's decision directly and fall back to Guardian when no extension claims the review.
- Update Guardian V2 to approve actions below its risk threshold through the review contributor API, and remove the extension approval-policy API.
## Testing
- Verify that an extension approval bypasses both the Guardian model call and the user approval prompt.
- Cover Guardian V2 review decisions for low-risk, high-risk, and disabled threads.
GitOrigin-RevId: 5be56941143aff6f358b75b5f8101b7c047147ae
## Why
Oversized tool arguments could make Guardian V2's model-visible action unbounded.
## What changed
- Cap serialized actions at 10,000 tokens while preserving the trusted tool name and `call_id`.
- Truncate nested string values evenly across the available budget.
- Omit lower-priority fields when the JSON structure alone exceeds the limit, while retaining useful action fields when they fit.
## Testing
Add coverage for oversized nested strings, arrays, and object keys, including spoofed identity fields and omission-marker collisions.
GitOrigin-RevId: 13f7dc93da3761db18a34087225196318a3b8098
## Why
Concurrent Guardian samples can finish out of order, allowing an older sample to
replace the thread's newer in-memory security risk score.
## What changed
- Record when each `SecurityRiskScore` sample starts while preserving compatibility
with records that have no timestamp.
- Add `ExtensionData::insert_if` so checking and replacing a typed attachment happen
under the same lock.
- Update Guardian V2 to replace the thread's risk score only when the completed sample
is newer than the stored one.
## Testing
- Verify concurrent conditional inserts retain the newest value.
- Verify Guardian-generated risk scores include a sampling timestamp.
GitOrigin-RevId: 6543a4e5497da4c623331050789e91613f931c4b
## What changed
- Add a thread-scoped extension API for requesting automatic review, resolving
multiple contributors to the strongest requirement.
- Have Guardian v2 request automatic review when it is enabled and the latest
`action_risk` score is at least `0.8`.
- Honor extension review requirements across tool approvals, MCP elicitation,
and remote execution while preserving host configuration and managed-policy
constraints.
## Testing
- Cover contributor registration and requirement resolution.
- Verify Guardian v2 requests review at the threshold, returns to the default
below it, and does not affect threads where the extension is disabled.
- Exercise extension-requested strict review with a remote model override.
GitOrigin-RevId: 6329fc23585d5cc7173c39bb9952c3109ec3884b
## What changed
- Replace the single `category` and `score` fields in `SecurityRiskScore` with a
deterministic map of category names to scores.
- Validate the full Guardian V2 classifier response before storing it as one
thread extension value and, for non-ephemeral threads, one rollout item.
- Cover serialization and rollout loading with snapshots containing multiple
score categories.
GitOrigin-RevId: 24525de691f96bd34ccfe04acab2f01aca309837
## Why
Guardian V2 classification requests should retain compacted conversation context only when the parent and classifier model configurations can share the encrypted compaction.
## What changed
- Resolve the classifier model's compaction compatibility hash when initializing its sampler.
- Add the latest encrypted parent compaction to classification input when both models have the same non-empty compatibility hash.
- Ignore missing, empty, or unidentified compactions, and omit parent context when compatibility cannot be established.
## Testing
- Cover latest-compaction selection and invalid compaction data.
- Cover matching, mismatched, missing, empty, and changed compatibility hashes.
GitOrigin-RevId: f0fcb09fd028cd2f397fdbc3d541b4bc464b0beb
## What changed
- Represent Guardian sampling input as an ordered list of text entries.
- Send each transcript entry and approval-request delimiter as a separate input
content item while preserving the existing transcript byte limit.
## Testing
- Update transcript and sampler tests to verify entry boundaries, multi-item
request serialization, and bounded transcript behavior.
GitOrigin-RevId: 433e2e6ca18ce9288025715f5956295bfe852e98
## What changed
- Register Guardian V2 for thread startup as well as tool-call lifecycle events.
- When `guardianv2` is enabled, create and store a thread-local Luna sampler using the thread's model provider, authentication policy, session metadata, originator, and service tier.
- Emit a warning if sampler initialization fails, and skip tool classification when the thread has no sampler.
## Testing
- Update the extension test to enable `guardianv2`, run thread startup, and verify tool-call sampling through the initialized connection.
GitOrigin-RevId: 5ab732e85c9827495c67f57117eb5be450a7f90e
## What changed
- Parse and validate the structured risk scores returned for each classified tool call.
- Publish each score through thread extension data and persist it in rollout history for non-ephemeral threads.
- Report parsing, thread lookup, validation, and persistence failures through the extension warning sink.
## Testing
- Extend the Guardian V2 tool-classification test to verify that the sampled `action_risk` score is available from thread extension data and written to rollout history.
GitOrigin-RevId: 46614fe0d686736dfb1f09398c6fcd848c7d8b2c
## Why
Guardian V2 needs the requested action and its conversation context to assess
risk; a tool name and call ID alone do not describe what the tool will do.
## What changed
- Expose the original, pre-hook `ToolPayload` to tool lifecycle contributors.
- Build Guardian V2 classifier input from the bounded conversation transcript
and a structured planned-action object containing the tool name and arguments.
- Warn and skip classification if the planned action cannot be serialized.
## Testing
- Verify lifecycle contributors receive tool arguments.
- Verify Guardian V2 sends transcript history and planned-action JSON to the
classifier.
GitOrigin-RevId: 28266ef7c1d2267ba705fcfbd9be4ef48e64e104
## What changed
- Register a tool lifecycle contributor when Guardian V2 is installed.
- On tool start, asynchronously ask the existing Luna sampler for a low-effort
`action_risk` score constrained to the range from `0.0` to `1.0`.
- Bound the tool metadata supplied to the classifier and treat it as untrusted
input.
- Emit an extension warning if classification sampling fails.
## Testing
Add an integration test that verifies the contributor reuses the configured
Luna pool and sends the expected model, attribution metadata, reasoning effort,
strict output schema, and tool-call context.
GitOrigin-RevId: 6b69fcc0443086544086849c38bcdd90560a291f