Unify Guardian context section collection (#42076)

## What changed

- Add typed context sections for root-conversation evidence, trusted user answers, and conversation transcripts to `codex-guardian-context`.
- Use the shared section registry when building core Guardian prompts and asynchronous Guardian V2 scoring context.
- Preserve source-role labeling while delivering authorization evidence as user-role context, and fail closed when context collection fails.

## Testing

- Cover shared section ordering and role preservation for synchronous and asynchronous targets.
- Verify trusted user answers appear exactly once as user-role input in Guardian V2 approval flows.

GitOrigin-RevId: 1d5d793ffbf166077411a66e85e039596907fb7e
This commit is contained in:
felixxia-oai authored and copyberry committed 2026-09-01 15:22:21 +00:00
1 parent d141438342
commit 2350823caa
15 files changed
+357 -108

No files matched your search

+27 -4
View File
@@ -14,8 +14,12 @@ use std::sync::LazyLock;
use codex_protocol::models::ResponseItem;
use authorization::RootConversationSection;
use authorization::TrustedUserAnswersSection;
use transcript::ConversationTranscriptSection;
pub use authorization::GuardianRootMessage;
pub use entry::ConversationTranscriptEntry;
pub use entry::ConversationTranscriptEntryKind;
pub use history::TranscriptHistory;
@@ -30,6 +34,7 @@ pub use transcript::TranscriptRetentionConfig;
pub use transcript::collect_transcript;
pub use truncation::truncate_text;
mod authorization;
mod entry;
mod history;
mod retention;
@@ -76,6 +81,10 @@ pub struct SectionInput<'a> {
pub history: &'a dyn SectionHistory,
/// Evidence sources and per-entry limits for this collection.
pub transcript: &'a ConversationTranscriptConfig,
/// Bounded root evidence resolved by the host; empty when not applicable.
pub root_conversation: &'a [GuardianRootMessage],
/// Bounded, role-labeled answers verified and matched to history by the host.
pub trusted_user_answers: &'a [String],
}
/// Supplies repeatable, zero-copy access to a host-owned conversation snapshot.
@@ -153,6 +162,8 @@ pub struct SectionRegistry {
pub fn default_registry() -> &'static SectionRegistry {
static REGISTRY: LazyLock<SectionRegistry> = LazyLock::new(|| {
let mut registry = SectionRegistry::default();
registry.register(RootConversationSection);
registry.register(TrustedUserAnswersSection);
registry.register(ConversationTranscriptSection);
registry
});
@@ -178,11 +189,23 @@ impl SectionRegistry {
}
}
/// Ordered transcript evidence produced by one section contributor.
/// Ordered evidence with a stable section identity and source-specific content.
///
/// Variants preserve provenance: transcript entries carry their original roles,
/// root messages remain line-role-labeled, and answers are host-verified fragments.
/// All currently supported sections are delivered as user-role evidence. Source
/// attribution never promotes their contents to developer instructions.
#[derive(Clone, Debug, PartialEq)]
pub struct ContextSection {
/// Structured evidence before consumer-specific selection and rendering.
pub items: Vec<ConversationTranscriptEntry>,
pub enum ContextSection {
ConversationTranscript {
items: Vec<ConversationTranscriptEntry>,
},
RootConversation {
items: Vec<String>,
},
TrustedUserAnswers {
items: Vec<String>,
},
}
#[cfg(test)]