mirror of
https://github.com/openai/codex.git
synced 2026-11-15 06:51:36 +00:00
Retain user instructions in guardian thread context (#42762)
## Why Guardian review needs the original user instructions alongside verified answers, even after compaction, resume, or rollback. A summarized or legacy checkpoint cannot establish a complete instruction history. ## What changed - Capture text user messages in retained context when `guardian_thread_context` is enabled, preserving their message identity through compaction and replay. - Keep retained instructions and verified answers in arrival order, with independent size and completeness tracking for each family. - Roll back retained evidence at the exact user-message boundary, including steers that share a turn ID, and apply the same semantics during rollout migration. - Treat checkpoints without retained user messages as incomplete while preserving their verified answers. ## Testing - Cover capture, compaction, resume, rollback, child forks, legacy checkpoints, storage bounds, and rollout migration. GitOrigin-RevId: 72706731b54e5ac8645db61b446d2401afb42235
This commit is contained in:
1 parent
cc4b8bdeb8
commit
80d7ca34bc
18 files changed
+1058
-103
No files matched your search
@@ -1590,7 +1590,9 @@ impl Session {
|
||||
state
|
||||
.history
|
||||
.restore_guardian_history(guardian_history.as_ref());
|
||||
state.history.restore_retained_context(&retained_context);
|
||||
state
|
||||
.history
|
||||
.restore_retained_context(Some(&retained_context));
|
||||
if let Some(world_state) = world_state_baseline {
|
||||
state.history.set_world_state_baseline(world_state);
|
||||
}
|
||||
|
||||
@@ -339,15 +339,16 @@ impl Session {
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
let mut history = ContextManager::new();
|
||||
if self.enabled(Feature::GuardianThreadContext) {
|
||||
history.enable_user_message_retention();
|
||||
}
|
||||
let mut saw_legacy_compaction_without_replacement_history = false;
|
||||
if let Some(checkpoint) = base_compaction
|
||||
&& let Some(items) = &checkpoint.compacted.replacement_history
|
||||
{
|
||||
history.replace_annotated(items.clone());
|
||||
history.restore_guardian_history(checkpoint.compacted.guardian_history.as_ref());
|
||||
if let Some(retained) = &checkpoint.compacted.retained_context {
|
||||
history.restore_retained_context(retained);
|
||||
}
|
||||
history.restore_retained_context(checkpoint.compacted.retained_context.as_ref());
|
||||
}
|
||||
// Materialize exact history semantics from the replay-derived suffix. The eventual lazy
|
||||
// design should keep this same replay shape, but drive it from a resumable reverse source
|
||||
@@ -386,8 +387,15 @@ impl Session {
|
||||
// prompt shape.
|
||||
// TODO(ccunningham): if we drop support for None replacement_history compaction items,
|
||||
// we can get rid of this second loop entirely and just build `history` directly in the first loop.
|
||||
let user_messages =
|
||||
compact::collect_annotated_user_messages(history.annotated_items());
|
||||
let identity = if self.enabled(Feature::GuardianThreadContext) {
|
||||
compact::CompactedMessageIdentity::Preserve
|
||||
} else {
|
||||
compact::CompactedMessageIdentity::Regenerate
|
||||
};
|
||||
let user_messages = compact::collect_annotated_user_messages(
|
||||
history.annotated_items(),
|
||||
identity,
|
||||
);
|
||||
let rebuilt = compact::build_compacted_history(
|
||||
Vec::new(),
|
||||
&user_messages,
|
||||
@@ -395,7 +403,7 @@ impl Session {
|
||||
);
|
||||
let retained_context = history.retained_context().clone();
|
||||
history.replace_annotated(rebuilt);
|
||||
history.restore_retained_context(&retained_context);
|
||||
history.restore_retained_context(Some(&retained_context));
|
||||
}
|
||||
}
|
||||
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(rollback)) => {
|
||||
|
||||
@@ -1488,6 +1488,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_
|
||||
}],
|
||||
});
|
||||
let mut retained = codex_history::RetainedContext::default();
|
||||
retained.mark_user_messages_incomplete();
|
||||
retained.record(&answer);
|
||||
let rollout_items = vec![
|
||||
RolloutItem::ResponseItem(user_message("before compact").into()),
|
||||
|
||||
@@ -1266,6 +1266,9 @@ impl Session {
|
||||
session_configuration.clone(),
|
||||
initial_auto_compact_window_ids,
|
||||
);
|
||||
if config.features.enabled(Feature::GuardianThreadContext) {
|
||||
state.history.enable_user_message_retention();
|
||||
}
|
||||
state.base_instructions_provenance = base_instructions_provenance.clone();
|
||||
let managed_network_requirements_configured = config
|
||||
.config_layer_stack
|
||||
|
||||
Reference in new issue
Block a user