mirror of
https://github.com/openai/codex.git
synced 2026-11-05 08:28:29 +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
@@ -66,6 +66,7 @@ fn user_message(text: &str) -> ResponseItem {
|
||||
|
||||
fn compacted_user_message(text: &str) -> CompactedUserMessage {
|
||||
CompactedUserMessage {
|
||||
id: None,
|
||||
message: text.to_string(),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
harness_metadata: None,
|
||||
@@ -129,7 +130,13 @@ fn collect_user_messages_extracts_user_text_only() {
|
||||
|
||||
let collected = collect_user_messages(&items);
|
||||
|
||||
assert_eq!(vec![compacted_user_message("first")], collected);
|
||||
assert_eq!(
|
||||
vec![CompactedUserMessage {
|
||||
id: Some(ResponseItemId::with_suffix("msg", "user")),
|
||||
..compacted_user_message("first")
|
||||
}],
|
||||
collected,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -142,10 +149,11 @@ fn collect_annotated_user_messages_extracts_user_text_only() {
|
||||
ResponseItemEnvelope::new(ResponseItem::Other),
|
||||
];
|
||||
|
||||
let collected = collect_annotated_user_messages(&items);
|
||||
let collected = collect_annotated_user_messages(&items, CompactedMessageIdentity::Preserve);
|
||||
|
||||
assert_eq!(
|
||||
vec![CompactedUserMessage {
|
||||
id: None,
|
||||
message: "first".to_string(),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
harness_metadata: Some(CodexHarnessMetadata::default()),
|
||||
@@ -223,6 +231,7 @@ fn build_token_limited_compacted_history_truncates_overlong_user_messages() {
|
||||
let max_tokens = 16;
|
||||
let big = "word ".repeat(200);
|
||||
let user_message = CompactedUserMessage {
|
||||
id: Some(ResponseItemId::with_suffix("msg", "long-user")),
|
||||
message: big.clone(),
|
||||
internal_chat_message_metadata_passthrough: None,
|
||||
harness_metadata: Some(CodexHarnessMetadata::default()),
|
||||
@@ -261,6 +270,7 @@ fn build_token_limited_compacted_history_truncates_overlong_user_messages() {
|
||||
other => panic!("unexpected item in history: {other:?}"),
|
||||
};
|
||||
assert_eq!(summary_text, "SUMMARY");
|
||||
assert_eq!(history[0].id(), user_message.id.as_ref());
|
||||
assert_eq!(history[0].metadata, Some(CodexHarnessMetadata::default()));
|
||||
assert_eq!(history[1].metadata, None);
|
||||
}
|
||||
@@ -292,6 +302,7 @@ fn build_compacted_history_preserves_user_message_passthrough_metadata() {
|
||||
let history = build_compacted_history(
|
||||
Vec::new(),
|
||||
&[CompactedUserMessage {
|
||||
id: Some(ResponseItemId::with_suffix("msg", "user")),
|
||||
message: "first user message".to_string(),
|
||||
internal_chat_message_metadata_passthrough: Some(
|
||||
InternalChatMessageMetadataPassthrough {
|
||||
@@ -314,7 +325,7 @@ fn build_compacted_history_preserves_user_message_passthrough_metadata() {
|
||||
vec![
|
||||
ResponseItemEnvelope {
|
||||
item: ResponseItem::Message {
|
||||
id: None,
|
||||
id: Some(ResponseItemId::with_suffix("msg", "user")),
|
||||
role: "user".to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: "first user message".to_string(),
|
||||
|
||||
Reference in new issue
Block a user