Preserve Guardian authorization across history compaction (#41660)

## Why

Compaction and host-injected context can rewrite the model-visible conversation
without changing what the user authorized. Treating those updates as authorization
changes prevents Guardian from reusing an otherwise valid review.

## What changed

- Track a host-owned user-message revision separately from the conversation history
  generation.
- Advance the revision for genuine user messages and history resets, while preserving
  it across compaction and internal context injection.
- Use message content-kind metadata to distinguish host context from user input,
  conservatively treating unknown or incomplete metadata as user authorization.

## Testing

Added coverage that cached Guardian authorization survives compaction and internal
context, but is invalidated by user input and rollback.

GitOrigin-RevId: c7960fa182d1686042c23764d2abc58acbc4b882
This commit is contained in:
jif authored and copyberry committed 2026-08-30 11:56:24 +00:00
1 parent 28327355b8
commit 0a12b855a0
14 files changed
+281 -22

No files matched your search

+11 -2
View File
@@ -201,6 +201,7 @@ use crate::config::PermissionProfileState;
use crate::config::StartedNetworkProxy;
use crate::config::resolve_web_search_mode_for_turn;
use crate::context_manager::ContextManager;
use crate::context_manager::HistoryReplacement;
use crate::thread_rollout_truncation::initial_history_has_prior_user_turns;
use codex_config::CONFIG_TOML_FILE;
use codex_config::ConfigLayerSource;
@@ -1533,7 +1534,11 @@ impl Session {
.collect();
{
let mut state = self.state.lock().await;
state.replace_annotated_history(history, reference_context_item);
state.replace_annotated_history(
history,
reference_context_item,
HistoryReplacement::Reset,
);
if let Some(world_state) = world_state_baseline {
state.history.set_world_state_baseline(world_state);
}
@@ -3641,7 +3646,11 @@ impl Session {
let mut world_state_item = None;
{
let mut state = self.state.lock().await;
state.replace_annotated_history(items, reference_context_item.clone());
state.replace_annotated_history(
items,
reference_context_item.clone(),
HistoryReplacement::Compaction,
);
if let Some(world_state) = world_state_baseline {
let snapshot = world_state.snapshot();
world_state_item = Some(WorldStateItem::full(snapshot.clone().into_object()));