Centralize Guardian context mode and checkpoint policy (#43458)

## What changed

Resolve `GuardianContextMode` once at session construction and share it across history retention, replay, evidence capture, compaction, and review consumers.

Extract synchronous reviewer context policy and consolidate Guardian V2 parent checkpoint selection so sampling and fast approval use the same eligibility checks. Preserve legacy checkpoint omission and strict compatibility requirements for thread-owned context.

## Testing

Adapt existing review and history tests to the explicit context mode. Move checkpoint tests alongside the extracted selector, retaining coverage for latest-item identity, unusable checkpoints, and complete-item size limits.

GitOrigin-RevId: c73fb6fea556921acfffe758a5f709d7494019dd
This commit is contained in:
felixxia-oai
2026-09-07 12:53:57 +00:00
committed by copyberry
parent f3f53ee949
commit 8260619cb6
26 changed files with 599 additions and 482 deletions
@@ -0,0 +1,23 @@
//! Immutable session mode shared by history, evidence projection, and reviewer policy.
//! Resolve the rollout flag at session construction, not independently at each consumer.
use codex_features::Feature;
use codex_features::Features;
/// Selects legacy compatibility or thread-owned evidence for a session's lifetime.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum GuardianContextMode {
#[default]
Legacy,
ThreadOwned,
}
impl GuardianContextMode {
pub(crate) fn from_features(features: &Features) -> Self {
if features.enabled(Feature::GuardianThreadContext) {
Self::ThreadOwned
} else {
Self::Legacy
}
}
}
@@ -10,8 +10,6 @@ use std::sync::Mutex;
use std::sync::PoisonError;
use codex_extension_api::ConversationHistorySnapshot;
use codex_features::Feature;
use codex_features::Features;
use codex_protocol::models::ContentItemKind;
use codex_protocol::models::ResponseItem;
use codex_protocol::protocol::GuardianAssessmentEvent;
@@ -20,6 +18,7 @@ use codex_protocol::request_user_input::RequestUserInputResponse;
use serde_json::json;
use super::ContextualUserFragment;
use super::GuardianContextMode;
use crate::codex_thread::GuardianAuthorizationVersion;
use crate::codex_thread::GuardianRootMessage;
use crate::guardian::guardian_truncate_text;
@@ -30,13 +29,6 @@ const MAX_TRUSTED_SKILL_PATHS_BYTES: usize = 2_048;
const MAX_GUARDIAN_USER_INPUT_ANSWERS: usize = 8;
const MAX_GUARDIAN_USER_INPUT_TOKENS: usize = 900;
#[derive(Debug, Default)]
enum GuardianContextMode {
#[default]
Legacy,
ThreadOwned,
}
/// Selected answer fragments and the authorization state they describe.
pub struct GuardianUserInputSnapshot {
pub fragments: Vec<String>,
@@ -65,17 +57,13 @@ struct GuardianReviewEvidenceState {
impl GuardianReviewEvidence {
/// Reports the fixed thread mode used for both capture and reviewer policy.
pub fn uses_thread_owned_context(&self) -> bool {
matches!(self.mode, GuardianContextMode::ThreadOwned)
pub fn context_mode(&self) -> GuardianContextMode {
self.mode
}
pub(crate) fn from_features(features: &Features) -> Self {
pub(crate) fn new(mode: GuardianContextMode) -> Self {
Self {
mode: if features.enabled(Feature::GuardianThreadContext) {
GuardianContextMode::ThreadOwned
} else {
GuardianContextMode::Legacy
},
mode,
state: Mutex::default(),
}
}
+2
View File
@@ -11,6 +11,7 @@ mod developer_instructions;
mod environment_context;
mod environments_instructions;
mod guardian_approved_action;
mod guardian_context_mode;
mod guardian_followup_review_reminder;
mod guardian_node_repl_policy;
mod guardian_policy;
@@ -65,6 +66,7 @@ pub(crate) use current_time_reminder::CurrentTimeReminder;
pub(crate) use developer_instructions::DeveloperInstructions;
pub(crate) use environments_instructions::EnvironmentsInstructions;
pub(crate) use guardian_approved_action::GuardianApprovedAction;
pub use guardian_context_mode::GuardianContextMode;
pub(crate) use guardian_followup_review_reminder::GuardianFollowupReviewReminder;
pub(crate) use guardian_node_repl_policy::GuardianNodeReplPolicy;
pub(crate) use guardian_policy::GuardianPolicy;