From 099ed802b20852148bf14f9d85ed77eb3ba8601b Mon Sep 17 00:00:00 2001 From: guinness-oai Date: Tue, 10 Feb 2026 10:32:11 -0800 Subject: [PATCH] Treat first rollout session_meta as canonical thread identity (#11241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During thread/fork, the new rollout includes the fork’s own session_meta plus copied history that can contain older session_meta entries from the source thread. thread/list was overwriting metadata on later session_meta lines, so a fork could be reported with the source thread’s thread_id. This fix only uses the first session_meta, so the fork keeps its own ID. --- codex-rs/core/src/rollout/list.rs | 40 ++++++++++++++++-------------- codex-rs/core/src/rollout/tests.rs | 1 + 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/codex-rs/core/src/rollout/list.rs b/codex-rs/core/src/rollout/list.rs index 940402902..af9223119 100644 --- a/codex-rs/core/src/rollout/list.rs +++ b/codex-rs/core/src/rollout/list.rs @@ -1015,25 +1015,27 @@ async fn read_head_summary(path: &Path, head_limit: usize) -> io::Result { - summary.source = Some(session_meta_line.meta.source.clone()); - summary.model_provider = session_meta_line.meta.model_provider.clone(); - summary.thread_id = Some(session_meta_line.meta.id); - summary.cwd = Some(session_meta_line.meta.cwd.clone()); - summary.git_branch = session_meta_line - .git - .as_ref() - .and_then(|git| git.branch.clone()); - summary.git_sha = session_meta_line - .git - .as_ref() - .and_then(|git| git.commit_hash.clone()); - summary.git_origin_url = session_meta_line - .git - .as_ref() - .and_then(|git| git.repository_url.clone()); - summary.cli_version = Some(session_meta_line.meta.cli_version); - summary.created_at = Some(session_meta_line.meta.timestamp.clone()); - summary.saw_session_meta = true; + if !summary.saw_session_meta { + summary.source = Some(session_meta_line.meta.source.clone()); + summary.model_provider = session_meta_line.meta.model_provider.clone(); + summary.thread_id = Some(session_meta_line.meta.id); + summary.cwd = Some(session_meta_line.meta.cwd.clone()); + summary.git_branch = session_meta_line + .git + .as_ref() + .and_then(|git| git.branch.clone()); + summary.git_sha = session_meta_line + .git + .as_ref() + .and_then(|git| git.commit_hash.clone()); + summary.git_origin_url = session_meta_line + .git + .as_ref() + .and_then(|git| git.repository_url.clone()); + summary.cli_version = Some(session_meta_line.meta.cli_version); + summary.created_at = Some(session_meta_line.meta.timestamp.clone()); + summary.saw_session_meta = true; + } } RolloutItem::ResponseItem(_) => { summary.created_at = summary diff --git a/codex-rs/core/src/rollout/tests.rs b/codex-rs/core/src/rollout/tests.rs index a4bd72433..a2e54d43f 100644 --- a/codex-rs/core/src/rollout/tests.rs +++ b/codex-rs/core/src/rollout/tests.rs @@ -881,6 +881,7 @@ async fn test_list_threads_scans_past_head_for_user_event() { .unwrap(); assert_eq!(page.items.len(), 1); + assert_eq!(page.items[0].thread_id, Some(thread_id_from_uuid(uuid))); } #[tokio::test]