Box session metadata and compaction payloads in RolloutItem (#55733)

## What changed

Store `RolloutItem::SessionMeta` and `RolloutItem::Compacted` payloads in `Box` values and update their producers, consumers, and test fixtures. Preserve the existing serialized rollout format.

GitOrigin-RevId: 59fcc4beb47d23160872dcb6e95ace9b142d3d11
This commit is contained in:
Charlie Marsh
2026-10-21 02:41:05 +00:00
committed by copyberry
parent d571eaf1f6
commit c7234c1174
52 changed files with 254 additions and 232 deletions
@@ -4602,7 +4602,7 @@ mod tests {
model_context_window: None,
collaboration_mode_kind: Default::default(),
})),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: None,
retained_context: None,
@@ -4615,7 +4615,7 @@ mod tests {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
root_turn_id: None,
turn_id: "turn-compact".into(),
@@ -210,7 +210,7 @@ fn ignores_legacy_abort_without_turn_id_and_context_only_records() {
duration_ms: None,
},
)));
let compacted = project(RolloutItem::Compacted(CompactedItem {
let compacted = project(RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: None,
retained_context: None,
@@ -223,7 +223,7 @@ fn ignores_legacy_abort_without_turn_id_and_context_only_records() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}));
})));
let security_risk = project(RolloutItem::SecurityRiskScore(SecurityRiskScore {
scores: BTreeMap::from([("action_risk".to_string(), 0.92)]),
call_id: None,
@@ -742,7 +742,7 @@ mod tests {
let mut lines = vec![RolloutLine {
timestamp: "2026-07-24T00:00:00Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: codex_protocol::protocol::SessionMeta {
cwd: tempdir.path().to_path_buf(),
base_instructions: Some(codex_protocol::models::BaseInstructions {
@@ -752,7 +752,7 @@ mod tests {
..Default::default()
},
git: None,
}),
})),
}];
lines.extend(turns.iter().map(|(turn_id, model, effort)| {
RolloutLine {
@@ -989,10 +989,10 @@ mod thread_processor_behavior_tests {
let line = RolloutLine {
timestamp: timestamp.clone(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: session_meta.clone(),
git: None,
}),
})),
};
fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?;
@@ -1057,10 +1057,10 @@ mod thread_processor_behavior_tests {
let line = RolloutLine {
timestamp,
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: session_meta,
git: None,
}),
})),
};
fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?;
@@ -1100,10 +1100,10 @@ mod thread_processor_behavior_tests {
let line = RolloutLine {
timestamp,
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: session_meta,
git: None,
}),
})),
};
fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?;
@@ -173,7 +173,11 @@ async fn thread_fork_creates_new_thread_and_emits_started() -> Result<()> {
);
let mut session_meta = read_session_meta_line(&original_path).await?;
session_meta.meta.multi_agent_version = Some(MultiAgentVersion::V1);
append_rollout_item_to_path(&original_path, &RolloutItem::SessionMeta(session_meta)).await?;
append_rollout_item_to_path(
&original_path,
&RolloutItem::SessionMeta(Box::new(session_meta)),
)
.await?;
let original_contents = std::fs::read_to_string(&original_path)?;
let mut mcp = TestAppServer::builder()
@@ -1678,8 +1678,11 @@ async fn thread_list_reports_loaded_subagent_direct_input_capability() -> Result
let parent_rollout_path = rollout_path(codex_home.path(), "2025-02-01T09-00-00", &cli_id);
let mut parent_meta = read_session_meta_line(&parent_rollout_path).await?;
parent_meta.meta.multi_agent_version = Some(MultiAgentVersion::V2);
append_rollout_item_to_path(&parent_rollout_path, &RolloutItem::SessionMeta(parent_meta))
.await?;
append_rollout_item_to_path(
&parent_rollout_path,
&RolloutItem::SessionMeta(Box::new(parent_meta)),
)
.await?;
// Legacy children resume before the root restores the V2 registry from persisted spawn edges.
let mut expected = vec![(cli_id.clone(), None, false)];
let mut threads_to_resume = vec![(cli_id.clone(), SessionSource::Cli, Some(true))];
@@ -1736,7 +1739,8 @@ async fn thread_list_reports_loaded_subagent_direct_input_capability() -> Result
let source = SessionSource::from(session_meta.meta.source.clone());
if let Some(version) = version {
session_meta.meta.multi_agent_version = Some(version);
append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(session_meta)).await?;
append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(Box::new(session_meta)))
.await?;
}
if should_resume {
let resume = (thread_id.clone(), source, capability);
@@ -195,7 +195,7 @@ async fn thread_resume_paginated_model_context_preserves_original_metadata() ->
}))?;
append_rollout_item_to_path(
&path,
&RolloutItem::Compacted(CompactedItem {
&RolloutItem::Compacted(Box::new(CompactedItem {
message: "compacted history".to_string(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -208,7 +208,7 @@ async fn thread_resume_paginated_model_context_preserves_original_metadata() ->
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
)
.await?;
append_rollout_item_to_path(
@@ -2158,7 +2158,7 @@ async fn unloaded_thread_goal_mutations_respect_parent_ownership() -> Result<()>
// must take precedence, just as it does when the thread resumes.
let mut meta = read_session_meta_line(&path).await?;
meta.meta.multi_agent_version = version;
append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(meta)).await?;
append_rollout_item_to_path(&path, &RolloutItem::SessionMeta(Box::new(meta))).await?;
for (method, params) in [
(
@@ -6487,8 +6487,11 @@ async fn setup_rollout_fixture(codex_home: &Path, server_uri: &str) -> Result<Ro
let rollout_file_path = rollout_path(codex_home, filename_ts, &conversation_id);
let mut session_meta = read_session_meta_line(&rollout_file_path).await?;
session_meta.meta.multi_agent_version = Some(MultiAgentVersion::V1);
append_rollout_item_to_path(&rollout_file_path, &RolloutItem::SessionMeta(session_meta))
.await?;
append_rollout_item_to_path(
&rollout_file_path,
&RolloutItem::SessionMeta(Box::new(session_meta)),
)
.await?;
set_rollout_mtime(rollout_file_path.as_path(), expected_updated_at_rfc3339)?;
Ok(RolloutFixture {
conversation_id,
+15 -13
View File
@@ -1332,20 +1332,22 @@ mod tests {
let rollout_line = RolloutLine {
timestamp: timestamp.to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(codex_protocol::protocol::SessionMetaLine {
meta: codex_protocol::protocol::SessionMeta {
session_id: parsed_thread_id.into(),
id: parsed_thread_id,
timestamp: timestamp.to_string(),
cwd: self.codex_home.path().to_path_buf(),
originator: "test".to_string(),
cli_version: "test".to_string(),
source: SessionSource::Cli,
model_provider: Some("test-provider".to_string()),
..Default::default()
item: RolloutItem::SessionMeta(Box::new(
codex_protocol::protocol::SessionMetaLine {
meta: codex_protocol::protocol::SessionMeta {
session_id: parsed_thread_id.into(),
id: parsed_thread_id,
timestamp: timestamp.to_string(),
cwd: self.codex_home.path().to_path_buf(),
originator: "test".to_string(),
cli_version: "test".to_string(),
source: SessionSource::Cli,
model_provider: Some("test-provider".to_string()),
..Default::default()
},
git: None,
},
git: None,
}),
)),
};
let contents = serde_json::to_string(&rollout_line).expect("rollout line");
std::fs::write(&path, format!("{contents}\n")).expect("rollout file");
+8 -8
View File
@@ -2695,7 +2695,7 @@ async fn spawn_agent_fork_sanitizes_inherited_compaction_metadata() {
parent_thread
.session
.persist_rollout_items(&[
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(vec![user_message("compacted parent context").into()]),
retained_context: None,
@@ -2708,7 +2708,7 @@ async fn spawn_agent_fork_sanitizes_inherited_compaction_metadata() {
compaction_response_id: None,
latest_token_usage_record: Some(parent_record.clone()),
resume_metadata: Some(parent_resume_metadata.clone()),
}),
})),
RolloutItem::TokenUsageRecord(parent_record),
rollout_response_item(spawn_agent_call(&parent_spawn_call_id)),
])
@@ -3378,7 +3378,7 @@ async fn spawn_agent_fork_strips_parent_usage_hints_from_compacted_history(marke
parent_thread
.session
.persist_rollout_items(&[
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(
replacement_history
@@ -3399,7 +3399,7 @@ async fn spawn_agent_fork_strips_parent_usage_hints_from_compacted_history(marke
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::RetainedContext(answer_event),
RolloutItem::ResponseItem(delivery),
RolloutItem::TurnContext(turn_context.to_turn_context_item()),
@@ -3609,7 +3609,7 @@ async fn spawn_agent_full_fork_restores_instructions_after_compaction_discards_p
phase: None,
internal_chat_message_metadata_passthrough: None,
}),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(
replacement_history.into_iter().map(Into::into).collect(),
@@ -3624,7 +3624,7 @@ async fn spawn_agent_full_fork_restores_instructions_after_compaction_discards_p
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::TurnContext(turn_context.to_turn_context_item()),
rollout_response_item(spawn_agent_call(&parent_spawn_call_id)),
])
@@ -3805,7 +3805,7 @@ async fn spawn_agent_full_fork_legacy_compaction_rebuilds_child_instructions_onc
.await;
let mut rollout_items = vec![
rollout_response_item(parent_user_message),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "legacy compacted summary".to_string(),
replacement_history: None,
retained_context: None,
@@ -3828,7 +3828,7 @@ async fn spawn_agent_full_fork_legacy_compaction_rebuilds_child_instructions_onc
realtime_active: None,
}),
}),
}),
})),
];
if let Some(instructions) = parent_developer_instructions {
rollout_items.push(rollout_response_item(ResponseItem::Message {
@@ -12,7 +12,7 @@ impl Session {
let state = self.state.lock().await;
let history = &state.history;
let window_ids = state.auto_compact_window_ids();
let mut items = vec![RolloutItem::Compacted(CompactedItem {
let mut items = vec![RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(history.annotated_items().to_vec()),
guardian_history: history.guardian_history_checkpoint(),
@@ -25,7 +25,7 @@ impl Session {
compaction_response_id: None,
latest_token_usage_record: state.latest_token_usage_record.clone(),
resume_metadata: None,
})];
}))];
if let Some(world_state) = history.world_state_checkpoint() {
items.push(RolloutItem::WorldState(world_state));
}
+1 -1
View File
@@ -4416,7 +4416,7 @@ impl Session {
}
let world_state_item = WorldStateItem::full(world_state_baseline.into_object());
let rollout_items = [
RolloutItem::Compacted(compacted_item),
RolloutItem::Compacted(Box::new(compacted_item)),
RolloutItem::WorldState(world_state_item),
RolloutItem::TurnContext(reference_context_item),
// The frozen turn context must not override current settings in persisted metadata.
@@ -173,7 +173,7 @@ async fn sender_context_follows_its_delivery_through_checkpoint_and_rollback() {
checkpoint.replacement_history = Some(live.annotated_items().to_vec());
checkpoint.retained_context = Some(live.retained_context().clone());
let mut checkpointed = items.clone();
checkpointed.push(RolloutItem::Compacted(checkpoint));
checkpointed.push(RolloutItem::Compacted(Box::new(checkpoint)));
for (num_turns, expected) in [(1, &snapshots[1]), (2, &snapshots[0])] {
let mut rolled_back = live.clone();
rolled_back.drop_last_n_user_turns(num_turns);
@@ -1304,7 +1304,7 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
..Default::default()
},
)),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -1317,7 +1317,7 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
codex_protocol::protocol::ThreadRolledBackEvent { num_turns: 1 },
)),
@@ -1371,7 +1371,7 @@ async fn record_initial_history_requires_surviving_full_snapshot_without_user_tu
}
MissingContextBaseline::CompactedSnapshot => vec![
RolloutItem::WorldState(WorldStateItem::full(object!({}))),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -1384,7 +1384,7 @@ async fn record_initial_history_requires_surviving_full_snapshot_without_user_tu
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
],
};
rollout_items.push(RolloutItem::TurnContext(
@@ -1409,7 +1409,7 @@ async fn record_initial_history_resumed_does_not_seed_reference_context_item_aft
let previous_context_item = turn_context.to_turn_context_item();
let rollout_items = vec![
RolloutItem::TurnContext(previous_context_item),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -1422,7 +1422,7 @@ async fn record_initial_history_resumed_does_not_seed_reference_context_item_aft
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
session
@@ -1443,7 +1443,7 @@ async fn reconstruct_history_restores_initial_window_from_session_meta() {
let (session, turn_context) = make_session_and_context().await;
let thread_id = ThreadId::default();
let initial_window_id = Uuid::now_v7();
let rollout_items = vec![RolloutItem::SessionMeta(SessionMetaLine {
let rollout_items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1453,7 +1453,7 @@ async fn reconstruct_history_restores_initial_window_from_session_meta() {
..SessionMeta::default()
},
git: None,
})];
}))];
let reconstructed = session
.reconstruct_history_from_rollout(&turn_context, &rollout_items)
@@ -1474,7 +1474,7 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() {
let compacted_previous_window_id = Uuid::now_v7();
let compacted_window_id = Uuid::now_v7();
let rollout_items = vec![
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1484,8 +1484,8 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() {
..SessionMeta::default()
},
git: None,
}),
RolloutItem::Compacted(CompactedItem {
})),
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -1498,7 +1498,7 @@ async fn reconstruct_history_prefers_compacted_window_over_session_meta() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
let reconstructed = session
@@ -1526,7 +1526,7 @@ async fn reconstruct_history_replays_world_state_from_latest_compaction_window()
RolloutItem::WorldState(WorldStateItem::full(object!({
"environment": {"status": "old"}
}))),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -1539,7 +1539,7 @@ async fn reconstruct_history_replays_world_state_from_latest_compaction_window()
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::WorldState(WorldStateItem::full(object!({
"environment": {"status": "starting", "cwd": "/workspace"}
}))),
@@ -1584,7 +1584,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions(
git: None,
};
let initial_context = turn_context.to_turn_context_item();
let mut rollout_items = vec![RolloutItem::SessionMeta(session_meta.clone())];
let mut rollout_items = vec![RolloutItem::SessionMeta(Box::new(session_meta.clone()))];
rollout_items.extend(completed_user_turn_rollout(
initial_context.clone(),
vec![RolloutItem::ResponseItem(
@@ -1603,7 +1603,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions(
let mut wake_items = completed_user_turn_rollout(
context.clone(),
vec![
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(annotated(vec![object!({
"type": "compaction",
@@ -1632,7 +1632,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions(
realtime_active: Some(false),
}),
}),
}),
})),
RolloutItem::WorldState(WorldStateItem::full(object!({
"environment": {"window": window_number, "status": "starting"}
}))),
@@ -1679,7 +1679,7 @@ async fn bounded_replay_matches_full_replay_after_empty_turn_compactions(
});
assert_eq!(cutoff, Some(latest_compaction_index));
let mut bounded_items = scan.finish();
bounded_items.insert(0, RolloutItem::SessionMeta(session_meta));
bounded_items.insert(0, RolloutItem::SessionMeta(Box::new(session_meta)));
let full = session
.reconstruct_history_from_rollout(&turn_context, &rollout_items)
.await;
@@ -1723,7 +1723,7 @@ async fn paginated_compaction_does_not_restore_missing_companions_from_older_his
let rollout_items = vec![
RolloutItem::TurnContext(turn_context.to_turn_context_item()),
RolloutItem::WorldState(WorldStateItem::full(object!({"older": true}))),
RolloutItem::Compacted(compacted),
RolloutItem::Compacted(Box::new(compacted)),
];
let reconstructed = session
@@ -1819,7 +1819,7 @@ async fn reconstruct_attribution_ignores_previous_terminal_after_checkpoint(
.pop()
.expect("previous turn completion");
let mut rollout = vec![
RolloutItem::Compacted(object!({
RolloutItem::Compacted(Box::new(object!({
"message": "summary",
"replacement_history": [user_message("original work")],
"window_number": 1,
@@ -1828,7 +1828,7 @@ async fn reconstruct_attribution_ignores_previous_terminal_after_checkpoint(
"turn_attribution": expected,
"previous_turn_settings": settings
}
})),
}))),
RolloutItem::ResponseItem(user_message("continued work").into()),
RolloutItem::TurnContext(context.clone()),
late_terminal,
@@ -1880,7 +1880,7 @@ async fn completed_turn_suffix_after_compaction_overrides_resume_metadata(
realtime_active: newer_context.realtime_active,
};
let mut rollout_items = vec![
RolloutItem::Compacted(object!({
RolloutItem::Compacted(Box::new(object!({
"message": "summary",
"replacement_history": [user_message("seed"), assistant_message("summary")],
"window_number": 1,
@@ -1892,7 +1892,7 @@ async fn completed_turn_suffix_after_compaction_overrides_resume_metadata(
"comp_hash": "metadata-hash"
}
}
})),
}))),
RolloutItem::WorldState(WorldStateItem::full(object!({}))),
];
// The bounded suffix starts at the compaction, so the turn start and user input are already in
@@ -1959,7 +1959,7 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta
let thread_id = ThreadId::default();
let initial_window_id = Uuid::now_v7();
let rollout_items = vec![
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1969,8 +1969,8 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta
..SessionMeta::default()
},
git: None,
}),
RolloutItem::Compacted(CompactedItem {
})),
RolloutItem::Compacted(Box::new(CompactedItem {
message: "legacy summary".to_string(),
replacement_history: None,
retained_context: None,
@@ -1983,7 +1983,7 @@ async fn reconstruct_history_preserves_legacy_compaction_count_with_session_meta
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
let reconstructed = session
@@ -2028,7 +2028,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_
RolloutItem::ResponseItem(user_message("before compact").into()),
RolloutItem::ResponseItem(assistant_message("assistant reply").into()),
RolloutItem::RetainedContext(answer),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "legacy summary".to_string(),
replacement_history: None,
retained_context: None,
@@ -2041,7 +2041,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_does_
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
let reconstructed = session
@@ -2070,7 +2070,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
.expect("turn context should have turn_id");
let rollout_items = vec![
RolloutItem::ResponseItem(user_message("before compact").into()),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "legacy summary".to_string(),
replacement_history: None,
retained_context: None,
@@ -2083,7 +2083,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_attribution: None,
@@ -2180,7 +2180,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
},
)),
// Compaction clears baseline until a later TurnContextItem re-establishes it.
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -2193,7 +2193,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
RolloutItem::TurnContext(previous_context_item),
RolloutItem::EventMsg(EventMsg::TurnComplete(
codex_protocol::protocol::TurnCompleteEvent {
@@ -2354,7 +2354,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
duration_ms: None,
},
)),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -2367,7 +2367,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
session
@@ -2621,7 +2621,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
..Default::default()
},
)),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -2634,7 +2634,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
];
session
@@ -2807,7 +2807,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
..Default::default()
},
)),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -2820,7 +2820,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
// A newer TurnStarted replaces the incomplete compacted turn without a matching
// completion/abort for the old one.
RolloutItem::EventMsg(EventMsg::TurnStarted(
+17 -17
View File
@@ -2469,7 +2469,7 @@ async fn reconstruct_history_uses_replacement_history_verbatim() {
let first_window_id = Uuid::now_v7();
let previous_window_id = Uuid::now_v7();
let window_id = Uuid::now_v7();
let rollout_items = vec![RolloutItem::Compacted(CompactedItem {
let rollout_items = vec![RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: Some(replacement_history.clone()),
retained_context: None,
@@ -2482,7 +2482,7 @@ async fn reconstruct_history_uses_replacement_history_verbatim() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
})];
}))];
let reconstructed = session
.reconstruct_history_from_rollout(&turn_context, &rollout_items)
@@ -2749,7 +2749,7 @@ async fn inter_agent_communication_waits_for_confirmed_delivery_persistence() {
compacted.retained_context = Some(live.retained_context().clone());
let mut history = resumed.history.as_ref().clone();
history.extend([
RolloutItem::Compacted(compacted),
RolloutItem::Compacted(Box::new(compacted)),
RolloutItem::EventMsg(EventMsg::ThreadRolledBack(
codex_protocol::protocol::ThreadRolledBackEvent { num_turns: 1 },
)),
@@ -3280,7 +3280,7 @@ fn session_meta_item(
thread_id: ThreadId,
multi_agent_version: Option<MultiAgentVersion>,
) -> RolloutItem {
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -3288,7 +3288,7 @@ fn session_meta_item(
..SessionMeta::default()
},
git: None,
})
}))
}
#[tokio::test]
@@ -3435,7 +3435,7 @@ fn latest_token_usage_record_stops_at_compaction_checkpoint() {
thread_token_usage: TokenUsage::default(),
};
let checkpoint = |latest_token_usage_record| {
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::new(),
replacement_history: None,
retained_context: None,
@@ -3448,7 +3448,7 @@ fn latest_token_usage_record_stops_at_compaction_checkpoint() {
compaction_response_id: None,
latest_token_usage_record,
resume_metadata: None,
})
}))
};
assert_eq!(
@@ -7409,7 +7409,7 @@ async fn resumed_subagent_session_restores_persisted_session_id() {
InitialHistory::Resumed(ResumedHistory {
history_revision: None,
conversation_id: thread_id,
history: Arc::new(vec![RolloutItem::SessionMeta(SessionMetaLine {
history: Arc::new(vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: parent_session_id,
id: thread_id,
@@ -7417,7 +7417,7 @@ async fn resumed_subagent_session_restores_persisted_session_id() {
..SessionMeta::default()
},
git: None,
})]),
}))]),
rollout_path: None,
}),
session_source,
@@ -7443,7 +7443,7 @@ async fn resumed_copied_fork_ignores_source_history_base() {
let parent_thread_id = ThreadId::new();
let thread_id = ThreadId::new();
let history = vec![
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
id: thread_id,
session_id: SessionId::from(thread_id),
@@ -7451,8 +7451,8 @@ async fn resumed_copied_fork_ignores_source_history_base() {
..SessionMeta::default()
},
git: None,
}),
RolloutItem::SessionMeta(SessionMetaLine {
})),
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
id: parent_thread_id,
session_id: SessionId::from(parent_thread_id),
@@ -7465,7 +7465,7 @@ async fn resumed_copied_fork_ignores_source_history_base() {
..SessionMeta::default()
},
git: None,
}),
})),
];
let (session, _rx_event) = make_session_with_history_source_and_agent_control_and_rx(
InitialHistory::Resumed(ResumedHistory {
@@ -13279,7 +13279,7 @@ async fn sample_rollout(
let rebuilt1 = compact::build_compacted_history(Vec::new(), &user_messages1, summary1);
live_history.replace_annotated(rebuilt1);
let (window_number, window_ids) = session.advance_auto_compact_window().await;
rollout_items.push(RolloutItem::Compacted(CompactedItem {
rollout_items.push(RolloutItem::Compacted(Box::new(CompactedItem {
message: summary1.to_string(),
replacement_history: None,
retained_context: None,
@@ -13292,7 +13292,7 @@ async fn sample_rollout(
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}));
})));
let user2 = user_message("second user");
live_history.record_items(
@@ -13314,7 +13314,7 @@ async fn sample_rollout(
let rebuilt2 = compact::build_compacted_history(Vec::new(), &user_messages2, summary2);
live_history.replace_annotated(rebuilt2);
let (window_number, window_ids) = session.advance_auto_compact_window().await;
rollout_items.push(RolloutItem::Compacted(CompactedItem {
rollout_items.push(RolloutItem::Compacted(Box::new(CompactedItem {
message: summary2.to_string(),
replacement_history: None,
retained_context: None,
@@ -13327,7 +13327,7 @@ async fn sample_rollout(
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}));
})));
let user3 = user_message("third user");
live_history.record_items(
+4 -4
View File
@@ -2022,7 +2022,7 @@ async fn selected_capability_roots_round_trip_through_fork() {
}];
let inherited = manager
.start_thread(StartThreadOptions {
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new(
SessionMetaLine {
meta: SessionMeta {
selected_capability_roots: selected_roots.clone(),
@@ -2030,7 +2030,7 @@ async fn selected_capability_roots_round_trip_through_fork() {
},
git: None,
},
)]),
))]),
environments: Some(Vec::new()),
..StartThreadOptions::new(config)
})
@@ -2117,7 +2117,7 @@ async fn selected_capability_roots_respect_startup_precedence_and_isolation() {
}
let child = manager
.start_thread(StartThreadOptions {
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new(
SessionMetaLine {
meta: SessionMeta {
selected_capability_roots: vec![root("saved")],
@@ -2125,7 +2125,7 @@ async fn selected_capability_roots_respect_startup_precedence_and_isolation() {
},
git: None,
},
)]),
))]),
inherited_environments: Some(parent_environments.clone()),
thread_extension_init,
..StartThreadOptions::new(config.clone())
@@ -66,7 +66,7 @@ fn restores_cumulative_item_and_compaction_checkpoints() {
};
let history = InitialHistory::Forked(vec![
RolloutItem::ResponseItem(envelope(Some(initial))),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "summary".to_string(),
replacement_history: Some(vec![envelope(Some(cumulative.clone()))]),
guardian_history: None,
@@ -79,7 +79,7 @@ fn restores_cumulative_item_and_compaction_checkpoints() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
]);
assert_eq!(McpAttributionRecorder::new(&history).snapshot(), cumulative);
@@ -135,7 +135,7 @@ fn first_error_reason_survives_checkpoints_and_later_sources() {
compacted.replacement_history = Some(vec![checkpoint.clone()]);
for item in [
RolloutItem::ResponseItem(checkpoint),
RolloutItem::Compacted(compacted),
RolloutItem::Compacted(Box::new(compacted)),
] {
let restored = McpAttributionRecorder::new(&InitialHistory::Forked(vec![item]));
restored.record(source("", "turn_3"));
@@ -967,13 +967,13 @@ fn tool_call_completeness_survives_waits_without_changing_deltas() {
fn paginated_history_allows_fresh_origins_but_rejects_known_ids() {
for origin in ["fresh-exec", "old-exec"] {
let history = InitialHistory::Forked(vec![
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
history_mode: ThreadHistoryMode::Paginated,
..SessionMeta::default()
},
git: None,
}),
})),
RolloutItem::ResponseItem(exec_input("old-exec").into()),
RolloutItem::ResponseItem(exec_output("old-exec").into()),
]);
+6 -6
View File
@@ -673,7 +673,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<(
RolloutLine {
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -686,7 +686,7 @@ async fn synthetic_call_output_id_is_stable_across_resumes() -> anyhow::Result<(
..Default::default()
},
git: None,
}),
})),
},
RolloutLine {
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
@@ -1187,7 +1187,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
RolloutLine {
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1200,7 +1200,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
..Default::default()
},
git: None,
}),
})),
},
RolloutLine {
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
@@ -1331,7 +1331,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
RolloutLine {
timestamp: "2024-01-01T00:00:00.000Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1344,7 +1344,7 @@ async fn resume_replays_image_tool_outputs_with_detail() {
..Default::default()
},
git: None,
}),
})),
},
RolloutLine {
timestamp: "2024-01-01T00:00:01.000Z".to_string(),
+1 -1
View File
@@ -324,7 +324,7 @@ async fn assert_copied_fork_persists_inherited_history(history_mode: ThreadHisto
let source_meta = codex_rollout::read_session_meta_line(source_path.as_path())
.await
.expect("read source session metadata");
let mut supplied_history = vec![RolloutItem::SessionMeta(source_meta)];
let mut supplied_history = vec![RolloutItem::SessionMeta(Box::new(source_meta))];
supplied_history.extend(source_items.iter().cloned());
let NewThread {
thread: forked_thread,
@@ -179,12 +179,14 @@ async fn guardian_revalidates_owning_session_before_allow(
test.codex = super::guardian_checkpoint_migration::resume(
&test,
&test.codex,
vec![RolloutItem::Compacted(serde_json::from_value(json!({
"message": "old checkpoint",
"replacement_history": [{
"type": "compaction", "id": "old", "encrypted_content": "unknown producer"
}]
}))?)],
vec![RolloutItem::Compacted(Box::new(serde_json::from_value(
json!({
"message": "old checkpoint",
"replacement_history": [{
"type": "compaction", "id": "old", "encrypted_content": "unknown producer"
}]
}),
)?))],
)
.await?;
}
@@ -156,12 +156,14 @@ async fn guardian_refreshes_subagent_authorization(change: Change) -> Result<()>
test.codex = super::guardian_checkpoint_migration::resume(
&test,
&test.codex,
vec![RolloutItem::Compacted(serde_json::from_value(json!({
"message": "old checkpoint",
"replacement_history": [{
"type": "compaction", "id": "old", "encrypted_content": "unknown producer"
}]
}))?)],
vec![RolloutItem::Compacted(Box::new(serde_json::from_value(
json!({
"message": "old checkpoint",
"replacement_history": [{
"type": "compaction", "id": "old", "encrypted_content": "unknown producer"
}]
}),
)?))],
)
.await?;
}
@@ -274,7 +274,7 @@ pub(crate) async fn handoff_scenario() -> Result<Vec<ResponsesRequest>> {
"message":"Root checkpoint.", "replacement_history":[], "retained_context":history.retained_context(),
}))?;
test.codex
.append_rollout_items(&[RolloutItem::Compacted(checkpoint)])
.append_rollout_items(&[RolloutItem::Compacted(Box::new(checkpoint))])
.await?;
test.codex.flush_rollout().await?;
let rollout = test
@@ -801,7 +801,7 @@ async fn run_guardian_subagent_review(
test.codex = super::guardian_checkpoint_migration::resume(
&test,
&test.codex,
vec![RolloutItem::Compacted(checkpoint)],
vec![RolloutItem::Compacted(Box::new(checkpoint))],
)
.await?;
assert_eq!(
@@ -1678,7 +1678,7 @@ async fn run_guardian_subagent_review(
));
}
checkpoint.replacement_history = Some(replacement_history);
root.append_rollout_items(&[RolloutItem::Compacted(checkpoint)])
root.append_rollout_items(&[RolloutItem::Compacted(Box::new(checkpoint))])
.await?;
root.shutdown_and_wait().await?;
test.thread_manager.remove_thread(&root_thread_id).await;
@@ -111,7 +111,7 @@ async fn recovery_without_a_snapshot_keeps_each_threads_originator() -> Result<(
let thread = fixture
.thread_manager
.start_thread(StartThreadOptions {
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(
initial_history: InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new(
SessionMetaLine {
meta: SessionMeta {
originator: originator.into(),
@@ -119,7 +119,7 @@ async fn recovery_without_a_snapshot_keeps_each_threads_originator() -> Result<(
},
git: None,
},
)]),
))]),
environments: Some(
fixture
.codex
@@ -48,13 +48,13 @@ async fn selected_capability_roots_survive_environment_reselection(
}];
let mut thread_extension_init = ExtensionDataInit::new();
let initial_history = if from_history {
InitialHistory::Forked(vec![RolloutItem::SessionMeta(SessionMetaLine {
InitialHistory::Forked(vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
selected_capability_roots: roots.clone(),
..SessionMeta::default()
},
git: None,
})])
}))])
} else {
thread_extension_init.insert(roots.clone());
InitialHistory::New
+1 -1
View File
@@ -592,7 +592,7 @@ async fn backfill_scans_existing_rollouts() -> Result<()> {
RolloutLine {
timestamp: "2026-01-27T12:00:00Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(session_meta_line),
item: RolloutItem::SessionMeta(Box::new(session_meta_line)),
},
RolloutLine {
timestamp: "2026-01-27T12:00:01Z".to_string(),
+2 -2
View File
@@ -213,13 +213,13 @@ impl Borrow<ResponseItem> for ResponseItemEnvelope {
/// Persisted rollout item used by core history and rollout storage.
#[derive(Debug, Clone)]
pub enum RolloutItem {
SessionMeta(SessionMetaLine),
SessionMeta(Box<SessionMetaLine>),
ResponseItem(ResponseItemEnvelope),
InterAgentCommunication(InterAgentCommunication),
InterAgentCommunicationMetadata {
trigger_turn: bool,
},
Compacted(CompactedItem),
Compacted(Box<CompactedItem>),
TurnContext(TurnContextItem),
TokenUsageRecord(TokenUsageRecord),
WorldState(WorldStateItem),
+6 -2
View File
@@ -166,7 +166,9 @@ impl<'a> From<&'a RolloutItem> for RolloutItemWire<'a> {
impl From<RolloutItemWire<'_>> for RolloutItem {
fn from(item: RolloutItemWire<'_>) -> Self {
match item {
RolloutItemWire::SessionMeta { payload } => Self::SessionMeta(payload.into_owned()),
RolloutItemWire::SessionMeta { payload } => {
Self::SessionMeta(Box::new(payload.into_owned()))
}
RolloutItemWire::ResponseItem { payload, metadata } => {
if let (
ResponseItem::Message {
@@ -218,7 +220,9 @@ impl From<RolloutItemWire<'_>> for RolloutItem {
trigger_turn: payload.trigger_turn,
}
}
RolloutItemWire::Compacted { payload } => Self::Compacted(payload.into_owned()),
RolloutItemWire::Compacted { payload } => {
Self::Compacted(Box::new(payload.into_owned()))
}
RolloutItemWire::TurnContext { payload } => Self::TurnContext(payload.into_owned()),
RolloutItemWire::TokenUsageRecord { payload } => {
Self::TokenUsageRecord(payload.into_owned())
+8 -7
View File
@@ -682,7 +682,7 @@ fn compacted_metadata_remains_compatible_with_legacy_response_item_readers() ->
])?)?,
crate::GuardianHistoryCheckpoint(vec![response_item.clone().into()]),
);
let compacted_line = serde_json::to_value(RolloutItem::Compacted(CompactedItem {
let compacted_line = serde_json::to_value(RolloutItem::Compacted(Box::new(CompactedItem {
message: "summary".to_string(),
replacement_history: Some(vec![envelope]),
retained_context: None,
@@ -700,7 +700,7 @@ fn compacted_metadata_remains_compatible_with_legacy_response_item_readers() ->
turn_attribution: None,
previous_turn_settings: None,
}),
}))?;
})))?;
let restored: RolloutItem = serde_json::from_value(compacted_line.clone())?;
let RolloutItem::Compacted(restored) = restored else {
@@ -959,7 +959,7 @@ fn compacted_item_migrates_legacy_numeric_window_id() -> Result<()> {
#[test]
fn copied_history_uses_persisted_history_mode() -> Result<()> {
let thread_id = ThreadId::from_string("00000000-0000-0000-0000-000000000001")?;
let session_meta = RolloutItem::SessionMeta(SessionMetaLine {
let session_meta = RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -967,7 +967,7 @@ fn copied_history_uses_persisted_history_mode() -> Result<()> {
..SessionMeta::default()
},
git: None,
});
}));
let history = InitialHistory::Resumed(ResumedHistory {
history_revision: None,
conversation_id: thread_id,
@@ -1025,8 +1025,8 @@ fn multi_agent_version_uses_newest_present_session_meta_value() -> Result<()> {
assert_eq!(
multi_agent_version_from_items(
&[
RolloutItem::SessionMeta(older_meta),
RolloutItem::SessionMeta(newer_meta_without_version),
RolloutItem::SessionMeta(Box::new(older_meta)),
RolloutItem::SessionMeta(Box::new(newer_meta_without_version)),
],
Some(thread_id),
),
@@ -1045,7 +1045,8 @@ fn multi_agent_version_uses_compaction_metadata_without_turn_context() -> Result
}))?;
assert_eq!(
InitialHistory::Forked(vec![RolloutItem::Compacted(compacted)]).get_multi_agent_version(),
InitialHistory::Forked(vec![RolloutItem::Compacted(Box::new(compacted))])
.get_multi_agent_version(),
Some(MultiAgentVersion::V2)
);
Ok(())
+1 -1
View File
@@ -1155,7 +1155,7 @@ fn write_rollout(path: &std::path::Path, thread_id: ThreadId, message: &str) ->
RolloutLine {
timestamp: "2025-01-03T12:00:00Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(session_meta_line),
item: RolloutItem::SessionMeta(Box::new(session_meta_line)),
},
RolloutLine {
timestamp: "2025-01-03T12:00:01Z".to_string(),
+1 -1
View File
@@ -1204,7 +1204,7 @@ pub async fn read_session_meta_line(path: &Path) -> io::Result<SessionMetaLine>
continue;
};
match rollout_line.item {
RolloutItem::SessionMeta(session_meta_line) => return Ok(session_meta_line),
RolloutItem::SessionMeta(session_meta_line) => return Ok(*session_meta_line),
RolloutItem::ResponseItem(_) | RolloutItem::InterAgentCommunication(_) => {
return Err(io::Error::other(MetadataReadError {
reason: "response_before_metadata",
+11 -11
View File
@@ -152,7 +152,7 @@ async fn extract_metadata_from_rollout_uses_session_meta() {
let rollout_line = RolloutLine {
timestamp: "2026-01-27T12:34:56Z".to_string(),
ordinal: Some(0),
item: RolloutItem::SessionMeta(session_meta_line.clone()),
item: RolloutItem::SessionMeta(Box::new(session_meta_line.clone())),
};
let json = serde_json::to_string(&rollout_line).expect("rollout json");
let mut file = File::create(&path).expect("create rollout");
@@ -164,7 +164,7 @@ async fn extract_metadata_from_rollout_uses_session_meta() {
let parent_line = RolloutLine {
timestamp: rollout_line.timestamp.clone(),
ordinal: Some(1),
item: RolloutItem::SessionMeta(parent),
item: RolloutItem::SessionMeta(Box::new(parent)),
};
writeln!(
file,
@@ -206,7 +206,7 @@ async fn extract_metadata_from_rollout_rejects_unknown_history_mode() {
let mut rollout_line = serde_json::to_value(RolloutLine {
timestamp: "2026-01-27T12:34:56Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: id.into(),
id,
@@ -217,7 +217,7 @@ async fn extract_metadata_from_rollout_rejects_unknown_history_mode() {
..SessionMeta::default()
},
git: None,
}),
})),
})
.expect("serialize rollout line");
rollout_line["payload"]["history_mode"] = serde_json::json!("future");
@@ -278,18 +278,18 @@ async fn extract_metadata_from_rollout_returns_latest_memory_mode() {
RolloutLine {
timestamp: "2026-01-27T12:34:56Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: session_meta,
git: None,
}),
})),
},
RolloutLine {
timestamp: "2026-01-27T12:35:00Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: polluted_meta,
git: None,
}),
})),
},
];
let mut file = File::create(&path).expect("create rollout");
@@ -316,7 +316,7 @@ fn builder_from_items_falls_back_to_filename() {
let path = dir
.path()
.join(format!("rollout-2026-01-27T12-34-56-{uuid}.jsonl"));
let items = vec![RolloutItem::Compacted(CompactedItem {
let items = vec![RolloutItem::Compacted(Box::new(CompactedItem {
message: "noop".to_string(),
replacement_history: None,
retained_context: None,
@@ -329,7 +329,7 @@ fn builder_from_items_falls_back_to_filename() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
})];
}))];
let builder = builder_from_items(items.as_slice(), path.as_path()).expect("builder");
let naive = NaiveDateTime::parse_from_str("2026-01-27T12-34-56", "%Y-%m-%dT%H-%M-%S")
@@ -625,7 +625,7 @@ fn write_rollout_in_sessions_with_cwd(
let rollout_line = RolloutLine {
timestamp: event_ts.to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(session_meta_line),
item: RolloutItem::SessionMeta(Box::new(session_meta_line)),
};
let json = serde_json::to_string(&rollout_line).expect("serialize rollout");
let mut file = File::create(&path).expect("create rollout");
+1 -1
View File
@@ -2039,7 +2039,7 @@ async fn write_session_meta(
git: git_info,
};
let rollout_item = RolloutItem::SessionMeta(session_meta_line);
let rollout_item = RolloutItem::SessionMeta(Box::new(session_meta_line));
if let Some(writer) = writer.as_mut() {
let ordinal = ordinal_state.current()?;
writer.write_rollout_item(&rollout_item, ordinal).await?;
+3 -3
View File
@@ -48,7 +48,7 @@ fn test_config(codex_home: &Path) -> RolloutConfig {
}
fn paginated_session_meta_item(thread_id: ThreadId, cwd: &Path) -> RolloutItem {
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -61,7 +61,7 @@ fn paginated_session_meta_item(thread_id: ThreadId, cwd: &Path) -> RolloutItem {
..SessionMeta::default()
},
git: None,
})
}))
}
fn agent_message_item(message: &str) -> RolloutItem {
@@ -248,7 +248,7 @@ async fn state_db_init_backfills_before_returning() -> anyhow::Result<()> {
RolloutLine {
timestamp: "2026-01-27T12:34:56Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(session_meta_line),
item: RolloutItem::SessionMeta(Box::new(session_meta_line)),
},
RolloutLine {
timestamp: "2026-01-27T12:34:57Z".to_string(),
+2 -2
View File
@@ -33,7 +33,7 @@ fn write_rollout_with_source_and_provider(
let line = RolloutLine {
timestamp: timestamp.clone(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -64,7 +64,7 @@ fn write_rollout_with_source_and_provider(
context_window: None,
},
git: None,
}),
})),
};
let body = serde_json::to_string(&line).map_err(std::io::Error::other)?;
std::fs::write(path, format!("{body}\n"))
+2 -2
View File
@@ -323,7 +323,7 @@ fn write_rollout_with_user_message(
RolloutLine {
timestamp: "2026-06-01T14:26:25Z".to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -354,7 +354,7 @@ fn write_rollout_with_user_message(
context_window: None,
},
git: None,
}),
})),
},
RolloutLine {
timestamp: "2026-06-01T14:26:26Z".to_string(),
+2 -2
View File
@@ -1591,7 +1591,7 @@ async fn test_updated_at_uses_file_mtime() -> Result<()> {
let meta_line = RolloutLine {
timestamp: ts.to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -1622,7 +1622,7 @@ async fn test_updated_at_uses_file_mtime() -> Result<()> {
context_window: None,
},
git: None,
}),
})),
};
writeln!(file, "{}", serde_json::to_string(&meta_line)?)?;
+6 -6
View File
@@ -365,7 +365,7 @@ mod tests {
let mut metadata =
ThreadMetadataBuilder::new(thread_id, PathBuf::new(), Utc::now(), source.clone())
.build("test-provider");
let session_meta = RolloutItem::SessionMeta(SessionMetaLine {
let session_meta = RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -373,7 +373,7 @@ mod tests {
..Default::default()
},
git: None,
});
}));
apply_rollout_item(&mut metadata, &session_meta, "test-provider");
let mut expected = metadata.clone();
expected.title = super::GUARDIAN_THREAD_TITLE.to_string();
@@ -525,7 +525,7 @@ mod tests {
apply_rollout_item(
&mut metadata,
&RolloutItem::SessionMeta(SessionMetaLine {
&RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -558,7 +558,7 @@ mod tests {
context_window: None,
},
git: None,
}),
})),
"test-provider",
);
apply_rollout_item(
@@ -775,7 +775,7 @@ mod tests {
apply_rollout_item(
&mut metadata,
&RolloutItem::SessionMeta(SessionMetaLine {
&RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -806,7 +806,7 @@ mod tests {
context_window: None,
},
git: None,
}),
})),
"test-provider",
);
+4 -4
View File
@@ -2806,7 +2806,7 @@ mod tests {
metadata.created_at,
SessionSource::Cli,
);
let items = vec![RolloutItem::SessionMeta(SessionMetaLine {
let items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -2837,7 +2837,7 @@ mod tests {
context_window: None,
},
git: None,
})];
}))];
runtime
.apply_rollout_items(
@@ -2880,7 +2880,7 @@ mod tests {
metadata.created_at,
SessionSource::Cli,
);
let items = vec![RolloutItem::SessionMeta(SessionMetaLine {
let items = vec![RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
creator_user_id: None,
creator_account_id: None,
@@ -2918,7 +2918,7 @@ mod tests {
.expect("valid git remote URL"),
),
}),
})];
}))];
runtime
.apply_rollout_items(
+2 -2
View File
@@ -617,10 +617,10 @@ impl InMemoryThreadStore {
.histories
.entry(params.thread_id)
.or_default()
.push(RolloutItem::SessionMeta(SessionMetaLine {
.push(RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: session_meta,
git: None,
}));
})));
state.created_threads.insert(params.thread_id, params);
Ok(())
}
@@ -185,7 +185,7 @@ async fn metadata_updates_share_ownership_and_resume_compressed_rollouts() -> Te
expected.git = None;
assert_eq!(
json!(items.last()),
json!(Some(RolloutItem::SessionMeta(expected.clone())))
json!(Some(RolloutItem::SessionMeta(Box::new(expected.clone()))))
);
age(&path)?;
@@ -214,7 +214,7 @@ async fn metadata_updates_share_ownership_and_resume_compressed_rollouts() -> Te
let (items, _, _) = RolloutRecorder::load_rollout_items(&path).await?;
assert_eq!(
json!(items.last()),
json!(Some(RolloutItem::SessionMeta(expected)))
json!(Some(RolloutItem::SessionMeta(Box::new(expected))))
);
Ok(())
}
@@ -155,7 +155,7 @@ pub(super) async fn load_for_fork(
let lineage = lineage.truncate_at(history_base).await?;
scan_model_context_from_lineage(lineage, session_meta).await
}
None => Ok(vec![RolloutItem::SessionMeta(session_meta)]),
None => Ok(vec![RolloutItem::SessionMeta(Box::new(session_meta))]),
}
}
@@ -212,6 +212,6 @@ fn scan_model_context_from_lineage_blocking(
}
let mut items = scan.finish();
items.insert(0, RolloutItem::SessionMeta(session_meta));
items.insert(0, RolloutItem::SessionMeta(Box::new(session_meta)));
Ok(items)
}
@@ -69,7 +69,7 @@ async fn stops_at_newest_usable_compaction_and_keeps_companions() {
assert_eq!(
serde_json::to_value(context.items).expect("serialize context"),
serde_json::to_value(vec![
RolloutItem::SessionMeta(session_meta),
RolloutItem::SessionMeta(Box::new(session_meta)),
compacted("latest compaction", Some(Vec::new())),
world_state,
turn_context,
@@ -129,7 +129,7 @@ async fn loads_recent_context_after_many_empty_wake_turns() {
})
.await
.expect("load model context");
expected_suffix.insert(0, RolloutItem::SessionMeta(session_meta));
expected_suffix.insert(0, RolloutItem::SessionMeta(Box::new(session_meta)));
assert_eq!(
serde_json::to_value(context.items).expect("serialize context"),
@@ -165,7 +165,7 @@ async fn fork_context_excludes_items_after_frozen_cutoff() {
.expect("load frozen fork context");
let expected = vec![
RolloutItem::SessionMeta(session_meta),
RolloutItem::SessionMeta(Box::new(session_meta)),
turn_started("frozen-turn"),
user_message("frozen message"),
];
@@ -201,7 +201,7 @@ async fn fork_version_stops_before_older_segments_once_resolved() {
let head = RolloutLine {
timestamp: "2025-01-03T13:02:01Z".to_string(),
ordinal: Some(0),
item: RolloutItem::SessionMeta(source_meta.clone()),
item: RolloutItem::SessionMeta(Box::new(source_meta.clone())),
};
std::fs::write(
&child_path,
@@ -243,7 +243,7 @@ async fn fork_version_stops_before_older_segments_once_resolved() {
source_meta.meta.multi_agent_version = stored_version.or(Some(MultiAgentVersion::V2));
assert_eq!(
serde_json::to_value(context).expect("serialize fork context"),
serde_json::to_value(vec![RolloutItem::SessionMeta(source_meta)])
serde_json::to_value(vec![RolloutItem::SessionMeta(Box::new(source_meta))])
.expect("serialize expected context")
);
}
@@ -296,7 +296,7 @@ async fn fork_version_respects_inherited_segment_cutoffs() {
source_meta.meta.multi_agent_version = Some(MultiAgentVersion::V2);
assert_eq!(
serde_json::to_value(context).expect("serialize fork context"),
serde_json::to_value(vec![RolloutItem::SessionMeta(source_meta)])
serde_json::to_value(vec![RolloutItem::SessionMeta(Box::new(source_meta))])
.expect("serialize expected context")
);
}
@@ -444,7 +444,7 @@ async fn replays_nested_archived_lineage_from_frozen_prefix() {
.await
.expect("read child metadata");
let expected = vec![
RolloutItem::SessionMeta(child_meta),
RolloutItem::SessionMeta(Box::new(child_meta)),
compacted("root checkpoint", Some(Vec::new())),
turn_started("middle-turn"),
user_message("middle inherited"),
@@ -703,7 +703,7 @@ fn turn_context(root: &Path, turn_id: &str) -> RolloutItem {
}
fn compacted(message: &str, replacement_history: Option<Vec<ResponseItem>>) -> RolloutItem {
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: message.to_string(),
replacement_history: replacement_history
.map(|items| items.into_iter().map(Into::into).collect()),
@@ -717,5 +717,5 @@ fn compacted(message: &str, replacement_history: Option<Vec<ResponseItem>>) -> R
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
})
}))
}
@@ -34,7 +34,7 @@ async fn empty_archived_reads_without_sqlite_preserve_source_and_file_time()
let line = RolloutLine {
timestamp: timestamp.to_string(),
ordinal: None,
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
id: thread_id,
session_id: thread_id.into(),
@@ -43,7 +43,7 @@ async fn empty_archived_reads_without_sqlite_preserve_source_and_file_time()
..SessionMeta::default()
},
git: None,
}),
})),
};
fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?;
fs::OpenOptions::new()
@@ -277,7 +277,7 @@ fn write_rollout_under(
let initial_ordinal = history_base.map_or(0, |base| base.end_ordinal_exclusive);
let mut lines = vec![rollout_line(
initial_ordinal,
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -286,7 +286,7 @@ fn write_rollout_under(
..SessionMeta::default()
},
git: None,
}),
})),
)];
for offset in 1..next_ordinal {
let ordinal = initial_ordinal
@@ -86,7 +86,7 @@ impl RollbackPlan {
// A rolled-back turn can still own the empty checkpoint that keeps cold resume from
// replaying older history.
if let Some(compacted) = self.compacted_items.get(&record_index) {
line.item = RolloutItem::Compacted(compacted.clone());
line.item = RolloutItem::Compacted(Box::new(compacted.clone()));
return Ok(Some(line));
}
if boundary.is_some_and(|boundary| !self.boundary_alive[boundary]) {
@@ -262,7 +262,7 @@ impl RollbackPlanner {
record_index: index,
boundary_depth: self.boundary_stack.len(),
owner,
item: item.clone(),
item: item.as_ref().clone(),
});
}
RolloutItem::TurnContext(_) => {
@@ -47,10 +47,10 @@ fn write_rollout(home: &Path, thread_id: ThreadId, history_mode: ThreadHistoryMo
..SessionMeta::default()
};
for (ordinal, item) in [
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: metadata,
git: None,
}),
})),
RolloutItem::EventMsg(EventMsg::UserMessage(UserMessageEvent {
message: "question".to_string(),
..UserMessageEvent::default()
@@ -119,10 +119,10 @@ fn write_rollout_with_fork(
model_provider: Some("test-provider".to_string()),
..SessionMeta::default()
};
let items = std::iter::once(RolloutItem::SessionMeta(SessionMetaLine {
let items = std::iter::once(RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: metadata,
git: None,
}))
})))
.chain(items);
for item in items {
let line = RolloutLine {
@@ -245,7 +245,7 @@ fn started(turn_id: &str) -> RolloutItem {
}
fn compacted(replacement_history: Vec<ResponseItem>) -> RolloutItem {
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "checkpoint".to_string(),
replacement_history: Some(replacement_history.into_iter().map(Into::into).collect()),
retained_context: None,
@@ -258,7 +258,7 @@ fn compacted(replacement_history: Vec<ResponseItem>) -> RolloutItem {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
})
}))
}
fn completed(turn_id: &str) -> RolloutItem {
@@ -2077,10 +2077,10 @@ async fn migration_drops_copied_user_fork_metadata_without_creating_a_history_ba
SessionSource::Cli,
Some(parent_id),
vec![
RolloutItem::SessionMeta(SessionMetaLine {
RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: copied_metadata,
git: None,
}),
})),
copied_response,
user_message("child question"),
agent_message("child answer"),
@@ -2142,7 +2142,7 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() {
thread_id,
SessionSource::SubAgent(SubAgentSource::Other("test".to_string())),
vec![
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "superseded checkpoint".repeat(1024),
replacement_history: Some(Vec::new()),
retained_context: None,
@@ -2155,8 +2155,8 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
RolloutItem::Compacted(CompactedItem {
})),
RolloutItem::Compacted(Box::new(CompactedItem {
message: "latest checkpoint".to_string(),
replacement_history: Some(vec![
ResponseItem::Message {
@@ -2182,7 +2182,7 @@ async fn migration_compacts_subagent_prefix_and_does_not_project_it() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
started("child-turn"),
RolloutItem::TurnContext(TurnContextItem {
turn_id: Some("child-turn".to_string()),
@@ -1569,7 +1569,7 @@ fn write_rollout_with_end(
let mut lines = vec![RolloutLine {
timestamp: "2026-07-16T00:00:00.000Z".to_string(),
ordinal: Some(initial_ordinal),
item: RolloutItem::SessionMeta(SessionMetaLine {
item: RolloutItem::SessionMeta(Box::new(SessionMetaLine {
meta: SessionMeta {
session_id: thread_id.into(),
id: thread_id,
@@ -1578,7 +1578,7 @@ fn write_rollout_with_end(
..SessionMeta::default()
},
git: None,
}),
})),
}];
for offset in 1..next_ordinal {
let ordinal = initial_ordinal
@@ -921,7 +921,7 @@ async fn update_rollout_metadata(
};
patch(&mut metadata);
recorder
.record_canonical_items(&[RolloutItem::SessionMeta(metadata)])
.record_canonical_items(&[RolloutItem::SessionMeta(Box::new(metadata))])
.await
.map_err(io_error)?;
recorder.flush().await.map_err(io_error)?;
@@ -1314,7 +1314,7 @@ mod tests {
let (mut expected, _, _) = RolloutRecorder::load_rollout_items(&path).await?;
let mut metadata = read_session_meta_line(&path).await?;
metadata.meta.memory_mode = Some("disabled".into());
expected.push(RolloutItem::SessionMeta(metadata));
expected.push(RolloutItem::SessionMeta(Box::new(metadata)));
let mut shutdown = Box::pin(store.shutdown_thread(thread_id));
update_rollout_metadata(&store, thread_id, &path, &writer_lock, |meta| {
@@ -563,7 +563,7 @@ mod tests {
let mut sync = resume_sync(
thread_id,
vec![
RolloutItem::SessionMeta(session_meta(thread_id)),
RolloutItem::SessionMeta(Box::new(session_meta(thread_id))),
RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))),
],
);
@@ -672,7 +672,7 @@ mod tests {
fn metadata_irrelevant_items_coalesce_updated_at_touches() {
let thread_id = ThreadId::new();
let mut sync = resume_sync(thread_id, Vec::new());
let item = RolloutItem::Compacted(CompactedItem {
let item = RolloutItem::Compacted(Box::new(CompactedItem {
message: "compacted".to_string(),
replacement_history: None,
retained_context: None,
@@ -685,7 +685,7 @@ mod tests {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
});
}));
let first = sync
.observe_appended_items(std::slice::from_ref(&item))
@@ -804,7 +804,7 @@ mod tests {
let mut sync = resume_sync(
thread_id,
vec![
RolloutItem::SessionMeta(session_meta(thread_id)),
RolloutItem::SessionMeta(Box::new(session_meta(thread_id))),
RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))),
],
);
@@ -836,7 +836,7 @@ mod tests {
let sync = resume_sync(
thread_id,
vec![
RolloutItem::SessionMeta(meta),
RolloutItem::SessionMeta(Box::new(meta)),
RolloutItem::EventMsg(EventMsg::UserMessage(user_message("hello metadata"))),
],
);
+2 -2
View File
@@ -1143,12 +1143,12 @@ mod tests {
}
fn session_meta(history_mode: ThreadHistoryMode) -> RolloutItem {
RolloutItem::SessionMeta(codex_protocol::protocol::SessionMetaLine {
RolloutItem::SessionMeta(Box::new(codex_protocol::protocol::SessionMetaLine {
meta: codex_protocol::protocol::SessionMeta {
history_mode,
..Default::default()
},
git: None,
})
}))
}
}
@@ -73,7 +73,7 @@ fn legacy_transcript_preview_scans_tail_across_compaction() {
vec![
rollout_user_message("older user"),
rollout_agent_message("older assistant"),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: String::from("summary that is not transcript text"),
replacement_history: None,
retained_context: None,
@@ -86,7 +86,7 @@ fn legacy_transcript_preview_scans_tail_across_compaction() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
rollout_user_message("recent user"),
rollout_agent_message("commentary one\ncommentary two"),
rollout_agent_message("final one\n\n final two "),
@@ -209,7 +209,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() {
&path,
vec![
rollout_user_message("older user"),
RolloutItem::Compacted(CompactedItem {
RolloutItem::Compacted(Box::new(CompactedItem {
message: "x".repeat(MAX_LEGACY_TRANSCRIPT_PREVIEW_SCAN_BYTES),
replacement_history: None,
retained_context: None,
@@ -222,7 +222,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
}),
})),
rollout_agent_message("recent assistant"),
],
);
@@ -241,7 +241,7 @@ fn legacy_transcript_preview_falls_back_for_oversized_hidden_record() {
fn legacy_transcript_preview_falls_back_when_scan_budget_is_exhausted() {
let temp_dir = tempdir().expect("tempdir");
let path = temp_dir.path().join("rollout.jsonl");
let compacted = RolloutItem::Compacted(CompactedItem {
let compacted = RolloutItem::Compacted(Box::new(CompactedItem {
message: "x".repeat(MAX_LEGACY_TRANSCRIPT_PREVIEW_SCAN_BYTES / 8),
replacement_history: None,
retained_context: None,
@@ -254,7 +254,7 @@ fn legacy_transcript_preview_falls_back_when_scan_budget_is_exhausted() {
compaction_response_id: None,
latest_token_usage_record: None,
resume_metadata: None,
});
}));
let mut items = vec![rollout_user_message("older user")];
items.extend(std::iter::repeat_n(compacted, 9));
items.push(rollout_agent_message("recent assistant"));