From f2368b7de61c6a5adadec7cba3597097f1e8e520 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Mon, 18 May 2026 14:54:36 -0700 Subject: [PATCH] [codex] Trim unused TurnContextItem fields (#22709) ## Why `TurnContextItem` is the durable baseline used to reconstruct context diffs across resume/fork. Most of the old persisted-only fields on it are no longer read, so keeping them in rollout snapshots adds schema surface and state that can drift without affecting reconstruction. `summary` is the exception: older Codex versions require it to deserialize `turn_context` records, so keep writing a default compatibility value until that schema surface can be removed safely. ## What changed - Removed the unused persisted fields from `TurnContextItem`: trace ids, user/developer instructions, output schema, and truncation policy. - Kept `summary` with a compatibility comment and made `TurnContext::to_turn_context_item` write `ReasoningSummary::Auto` instead of live turn state. - Updated rollout/context reconstruction fixtures for the retained summary field. ## Verification - `cargo test -p codex-protocol --lib turn_context_item` - `cargo test -p codex-rollout resume_candidate_matches_cwd_reads_latest_turn_context` - `cargo test -p codex-state turn_context` - `cargo test -p codex-core --lib new_default_turn_captures_current_span_trace_id` - `cargo test -p codex-core --lib record_initial_history_resumed_turn_context_after_compaction_reestablishes_reference_context_item` - `cargo test -p codex-core --test all emits_warning_when_resumed_model_differs` - `git diff --check` --- .../core/src/context_manager/history_tests.rs | 8 +-- .../session/rollout_reconstruction_tests.rs | 56 +++---------------- codex-rs/core/src/session/tests.rs | 16 ++---- codex-rs/core/src/session/turn_context.rs | 7 +-- codex-rs/core/tests/suite/resume_warning.rs | 5 -- codex-rs/protocol/src/protocol.rs | 21 ++----- codex-rs/rollout/src/recorder_tests.rs | 8 +-- codex-rs/state/src/extract.rs | 22 +------- 8 files changed, 24 insertions(+), 119 deletions(-) diff --git a/codex-rs/core/src/context_manager/history_tests.rs b/codex-rs/core/src/context_manager/history_tests.rs index 74f4d29bfb..8ba5d56e32 100644 --- a/codex-rs/core/src/context_manager/history_tests.rs +++ b/codex-rs/core/src/context_manager/history_tests.rs @@ -2,7 +2,6 @@ use super::*; use base64::Engine; use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use codex_protocol::AgentPath; -use codex_protocol::config_types::ReasoningSummary; use codex_protocol::models::BaseInstructions; use codex_protocol::models::ContentItem; use codex_protocol::models::DEFAULT_IMAGE_DETAIL; @@ -121,7 +120,6 @@ fn developer_msg_with_fragments(texts: &[&str]) -> ResponseItem { fn reference_context_item() -> TurnContextItem { TurnContextItem { turn_id: Some("reference-turn".to_string()), - trace_id: None, cwd: PathBuf::from("/tmp/reference-cwd"), current_date: Some("2026-03-23".to_string()), timezone: Some("America/Los_Angeles".to_string()), @@ -135,11 +133,7 @@ fn reference_context_item() -> TurnContextItem { collaboration_mode: None, realtime_active: Some(false), effort: None, - summary: ReasoningSummary::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(codex_protocol::protocol::TruncationPolicy::Tokens(10_000)), + summary: codex_protocol::config_types::ReasoningSummary::Auto, } } diff --git a/codex-rs/core/src/session/rollout_reconstruction_tests.rs b/codex-rs/core/src/session/rollout_reconstruction_tests.rs index aa403316e0..fc2811710a 100644 --- a/codex-rs/core/src/session/rollout_reconstruction_tests.rs +++ b/codex-rs/core/src/session/rollout_reconstruction_tests.rs @@ -59,7 +59,6 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ let previous_model = "previous-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -74,11 +73,7 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let rollout_items = vec![RolloutItem::TurnContext(previous_context_item)]; @@ -101,7 +96,6 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif let previous_model = "previous-rollout-model"; let mut previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -116,11 +110,7 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let turn_id = previous_context_item .turn_id @@ -925,7 +915,6 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis let previous_model = "previous-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -940,11 +929,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item .turn_id @@ -1005,7 +990,6 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis .expect("serialize seeded reference context item"), serde_json::to_value(Some(TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -1020,11 +1004,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, })) .expect("serialize expected reference context item") ); @@ -1037,7 +1017,6 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu let previous_model = "previous-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -1052,11 +1031,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item .turn_id @@ -1155,7 +1130,6 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo let unmatched_abort_turn_id = "other-turn".to_string(); let current_context_item = TurnContextItem { turn_id: Some(current_turn_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -1170,11 +1144,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let rollout_items = vec![ @@ -1272,7 +1242,6 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea let previous_model = "previous-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -1287,11 +1256,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item .turn_id @@ -1428,7 +1393,6 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear let previous_model = "previous-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -1443,11 +1407,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item .turn_id diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index dbdc8aa8dd..e3f038eff7 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -2317,7 +2317,6 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() { let previous_model = "forked-rollout-model"; let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), - trace_id: turn_context.trace_id.clone(), #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), @@ -2332,11 +2331,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() { collaboration_mode: Some(turn_context.collaboration_mode.clone()), realtime_active: Some(turn_context.realtime_active), effort: turn_context.reasoning_effort, - summary: turn_context.reasoning_summary, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: Some(turn_context.truncation_policy), + summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let turn_id = previous_context_item .turn_id @@ -5125,7 +5120,7 @@ async fn new_default_turn_captures_current_span_trace_id() { &request_parent )); - let turn_context_item = async { + let turn_trace_id = async { let expected_trace_id = Span::current() .context() .span() @@ -5133,15 +5128,14 @@ async fn new_default_turn_captures_current_span_trace_id() { .trace_id() .to_string(); let turn_context = session.new_default_turn().await; - let turn_context_item = turn_context.to_turn_context_item(); - assert_eq!(turn_context_item.trace_id, Some(expected_trace_id)); - turn_context_item + assert_eq!(turn_context.trace_id, Some(expected_trace_id)); + turn_context.trace_id.clone() } .instrument(request_span) .await; assert_eq!( - turn_context_item.trace_id.as_deref(), + turn_trace_id.as_deref(), Some("00000000000000000000000000000011") ); } diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index 8f0ce2d5fd..b14999d2cc 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -368,7 +368,6 @@ impl TurnContext { pub(crate) fn to_turn_context_item(&self) -> TurnContextItem { TurnContextItem { turn_id: Some(self.sub_id.clone()), - trace_id: self.trace_id.clone(), #[allow(deprecated)] cwd: self.cwd.to_path_buf(), current_date: self.current_date.clone(), @@ -383,11 +382,7 @@ impl TurnContext { collaboration_mode: Some(self.collaboration_mode.clone()), realtime_active: Some(self.realtime_active), effort: self.reasoning_effort, - summary: self.reasoning_summary, - user_instructions: self.user_instructions.clone(), - developer_instructions: self.developer_instructions.clone(), - final_output_json_schema: self.final_output_json_schema.clone(), - truncation_policy: Some(self.truncation_policy), + summary: ReasoningSummaryConfig::Auto, } } diff --git a/codex-rs/core/tests/suite/resume_warning.rs b/codex-rs/core/tests/suite/resume_warning.rs index ac916ba66d..d2bdcd1d32 100644 --- a/codex-rs/core/tests/suite/resume_warning.rs +++ b/codex-rs/core/tests/suite/resume_warning.rs @@ -27,7 +27,6 @@ fn resume_history( let turn_id = "resume-warning-seed-turn".to_string(); let turn_ctx = TurnContextItem { turn_id: Some(turn_id.clone()), - trace_id: None, cwd: config.cwd.to_path_buf(), current_date: None, timezone: None, @@ -44,10 +43,6 @@ fn resume_history( summary: config .model_reasoning_summary .unwrap_or(ReasoningSummary::Auto), - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, }; InitialHistory::Resumed(ResumedHistory { diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 98635ee30a..ec780d60c3 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -2824,8 +2824,6 @@ pub struct TurnContextNetworkItem { pub struct TurnContextItem { #[serde(default, skip_serializing_if = "Option::is_none")] pub turn_id: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub trace_id: Option, pub cwd: PathBuf, #[serde(default, skip_serializing_if = "Option::is_none")] pub current_date: Option, @@ -2848,15 +2846,11 @@ pub struct TurnContextItem { pub realtime_active: Option, #[serde(skip_serializing_if = "Option::is_none")] pub effort: Option, + // Compatibility-only field written with a default value so older Codex + // versions can deserialize turn-context rollout items. It is no longer + // read by context reconstruction and should be removed in a future schema + // cleanup. pub summary: ReasoningSummaryConfig, - #[serde(skip_serializing_if = "Option::is_none")] - pub user_instructions: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub developer_instructions: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub final_output_json_schema: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub truncation_policy: Option, } impl TurnContextItem { @@ -5246,7 +5240,6 @@ mod tests { "summary": "auto", }))?; - assert_eq!(item.trace_id, None); assert_eq!(item.network, None); assert_eq!(item.file_system_sandbox_policy, None); Ok(()) @@ -5256,7 +5249,6 @@ mod tests { fn turn_context_item_serializes_network_when_present() -> Result<()> { let item = TurnContextItem { turn_id: None, - trace_id: None, cwd: test_path_buf("/tmp"), current_date: None, timezone: None, @@ -5281,10 +5273,6 @@ mod tests { realtime_active: None, effort: None, summary: ReasoningSummaryConfig::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, }; let value = serde_json::to_value(item)?; @@ -5308,6 +5296,7 @@ mod tests { }] }) ); + assert_eq!(value["summary"], json!("auto")); Ok(()) } diff --git a/codex-rs/rollout/src/recorder_tests.rs b/codex-rs/rollout/src/recorder_tests.rs index 8199f290d8..90fe15c312 100644 --- a/codex-rs/rollout/src/recorder_tests.rs +++ b/codex-rs/rollout/src/recorder_tests.rs @@ -4,7 +4,6 @@ use super::*; use crate::config::RolloutConfig; use chrono::TimeZone; use codex_protocol::ThreadId; -use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig; use codex_protocol::models::ResponseItem; use codex_protocol::protocol::AgentMessageEvent; use codex_protocol::protocol::AskForApproval; @@ -1127,7 +1126,6 @@ async fn resume_candidate_matches_cwd_reads_latest_turn_context() -> std::io::Re timestamp: "2025-01-03T13:00:01Z".to_string(), item: RolloutItem::TurnContext(TurnContextItem { turn_id: Some("turn-1".to_string()), - trace_id: None, cwd: latest_cwd.clone(), current_date: None, timezone: None, @@ -1141,11 +1139,7 @@ async fn resume_candidate_matches_cwd_reads_latest_turn_context() -> std::io::Re collaboration_mode: None, realtime_active: None, effort: None, - summary: ReasoningSummaryConfig::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, + summary: codex_protocol::config_types::ReasoningSummary::Auto, }), }; writeln!(file, "{}", serde_json::to_string(&turn_context)?)?; diff --git a/codex-rs/state/src/extract.rs b/codex-rs/state/src/extract.rs index 886d267e4f..2369addf23 100644 --- a/codex-rs/state/src/extract.rs +++ b/codex-rs/state/src/extract.rs @@ -156,7 +156,6 @@ mod tests { use chrono::DateTime; use chrono::Utc; use codex_protocol::ThreadId; - use codex_protocol::config_types::ReasoningSummary; use codex_protocol::models::ContentItem; use codex_protocol::models::ResponseItem; use codex_protocol::openai_models::ReasoningEffort; @@ -339,7 +338,6 @@ mod tests { &mut metadata, &RolloutItem::TurnContext(TurnContextItem { turn_id: Some("turn-1".to_string()), - trace_id: None, cwd: PathBuf::from("/parent/workspace"), current_date: None, timezone: None, @@ -353,11 +351,7 @@ mod tests { collaboration_mode: None, realtime_active: None, effort: None, - summary: ReasoningSummary::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, + summary: codex_protocol::config_types::ReasoningSummary::Auto, }), "test-provider", ); @@ -379,7 +373,6 @@ mod tests { &mut metadata, &RolloutItem::TurnContext(TurnContextItem { turn_id: Some("turn-1".to_string()), - trace_id: None, cwd: PathBuf::from("/fallback/workspace"), current_date: None, timezone: None, @@ -393,11 +386,7 @@ mod tests { collaboration_mode: None, realtime_active: None, effort: Some(ReasoningEffort::High), - summary: ReasoningSummary::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, + summary: codex_protocol::config_types::ReasoningSummary::Auto, }), "test-provider", ); @@ -413,7 +402,6 @@ mod tests { &mut metadata, &RolloutItem::TurnContext(TurnContextItem { turn_id: Some("turn-1".to_string()), - trace_id: None, cwd: PathBuf::from("/fallback/workspace"), current_date: None, timezone: None, @@ -427,11 +415,7 @@ mod tests { collaboration_mode: None, realtime_active: None, effort: Some(ReasoningEffort::High), - summary: ReasoningSummary::Auto, - user_instructions: None, - developer_instructions: None, - final_output_json_schema: None, - truncation_policy: None, + summary: codex_protocol::config_types::ReasoningSummary::Auto, }), "test-provider", );