Apply elastic entry caps to Guardian classifier evidence (#61346)

## Why

Trusted classifier evidence needs to fit configured entry limits while preserving complete records and metadata that reflects only delivered reviews.

## What changed

Apply elastic caps before rendering trusted tools, trusted skills, and previous reviews into developer messages. Omit oversized tool attestations and review fragments whole, retain only complete skill paths that fit, and record omissions for the request's omission notice. Keep review IDs aligned with retained fragments and preserve fixed-budget behavior.

## Testing

Add coverage for whole-record omissions, retained review IDs, and omission notices. Exercise orchestrator connector evidence with both fixed budgeting and an elastic tool entry cap.

GitOrigin-RevId: 729db452026f93b59765a3936730b9b6dddfcf9a
This commit is contained in:
ioanbudea-OAI
2026-11-13 18:47:15 +00:00
committed by copyberry
parent a655b50de9
commit 6919e2cd8e
10 changed files with 381 additions and 78 deletions
@@ -3,7 +3,6 @@ use codex_extension_api::ResponseItem;
pub(crate) use codex_features::GuardianV2TranscriptSource as TranscriptSource;
use codex_guardian_context::CollectedContext;
use codex_guardian_context::ComposedContext;
use codex_guardian_context::ContextBudgeting;
use codex_guardian_context::ContextPresentation;
use codex_guardian_context::ContextProfile;
use codex_guardian_context::ContextTarget;
@@ -26,8 +25,7 @@ use codex_guardian_context::TranscriptRetentionConfig;
use codex_guardian_context::TranscriptSelection;
use codex_guardian_context::TrustedTool;
use codex_guardian_context::default_registry;
use codex_guardian_context::prepare_context;
use std::borrow::Cow;
use codex_guardian_context::prepare_async_context;
const DEFAULT_PROFILE: &ContextProfile = &ContextProfile::asynchronous();
pub(crate) const MAX_MESSAGE_ENTRY_TOKENS: usize =
@@ -185,17 +183,13 @@ impl CollectedTranscript {
TranscriptSelection::Full(_) => (0, ContextPresentation::Async),
TranscriptSelection::Delta { offset, .. } => (offset, ContextPresentation::AsyncDelta),
};
let mut context = prepare_context(
Cow::Borrowed(&self.context),
let mut context = prepare_async_context(
&self.context,
&self.profile,
offset,
presentation,
if self.elastic.is_some() {
ContextBudgeting::Elastic
} else {
ContextBudgeting::Fixed
},
reviewer_history,
self.elastic.as_ref(),
)?;
if self.elastic.is_none() {
context.retain_new_native_messages(reviewer_history)?;