Route rollout reads through the canonical JSON decoder (#42378)

## Why

Directly deserializing the flattened `RolloutLine` envelope can reject nested
decimal values, preventing affected paginated sessions from resuming.

## What changed

- Add canonical string, byte, and reverse-scanner helpers that decode rollout
  records through `serde_json::Value` before decoding the flattened item.
- Route rollout readers across session discovery, history, migration, search,
  thread storage, and transcript previews through those helpers.
- Remove `Deserialize` from `RolloutLine` so new readers cannot bypass the
  canonical persistence decoder.

## Testing

Add coverage that resumes a paginated rollout after a token-count record with
a decimal rate-limit value and verifies that ordinal sequencing continues.

GitOrigin-RevId: 49abac1e0751c073daa5a93a840d8a483fd2d013
This commit is contained in:
Owen Lin
2026-09-02 22:45:19 +00:00
committed by copyberry
parent e1d0ef995f
commit 69cebb5d15
49 changed files with 184 additions and 114 deletions
+7 -7
View File
@@ -5,7 +5,6 @@ use super::Config;
use super::DoctorCheck;
use super::DoctorIssue;
use codex_history::RolloutItem;
use codex_history::RolloutLine;
use codex_protocol::protocol::InternalSessionSource;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
@@ -543,7 +542,7 @@ async fn thread_id_from_rollout(path: &Path) -> RolloutThreadId {
Err(_) => continue,
};
if item_type == "session_meta" {
return match serde_json::from_str::<RolloutLine>(line.trim()) {
return match codex_rollout::parse_rollout_line(line.trim()) {
Ok(line) => match line.item {
RolloutItem::SessionMeta(session_meta) => {
RolloutThreadId::Id(session_meta.meta.id.to_string())
@@ -560,7 +559,7 @@ async fn thread_id_from_rollout(path: &Path) -> RolloutThreadId {
};
}
if !has_legacy_item {
has_legacy_item = serde_json::from_str::<RolloutLine>(line.trim()).is_ok();
has_legacy_item = codex_rollout::parse_rollout_line(line.trim()).is_ok();
}
}
@@ -745,6 +744,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use codex_history::RolloutLine;
use codex_protocol::ThreadId;
use codex_utils_absolute_path::test_support::PathExt;
use pretty_assertions::assert_eq;
@@ -862,7 +862,7 @@ mod tests {
fixture.write_rollout(/*archived*/ false, "2025-01-02T10-00-00", filename_id);
let contents = std::fs::read_to_string(&path).expect("rollout file");
let mut rollout_line =
serde_json::from_str::<RolloutLine>(contents.trim()).expect("rollout line");
codex_rollout::parse_rollout_line(contents.trim()).expect("rollout line");
let RolloutItem::SessionMeta(session_meta) = &mut rollout_line.item else {
panic!("expected session metadata");
};
@@ -981,7 +981,7 @@ mod tests {
fixture.write_rollout(/*archived*/ false, "2025-01-02T10-00-00", filename_id);
let contents = std::fs::read_to_string(&metadata_path).expect("rollout file");
let mut rollout_line =
serde_json::from_str::<RolloutLine>(contents.trim()).expect("rollout line");
codex_rollout::parse_rollout_line(contents.trim()).expect("rollout line");
let RolloutItem::SessionMeta(session_meta) = &mut rollout_line.item else {
panic!("expected session metadata");
};
@@ -1114,7 +1114,7 @@ mod tests {
fixture.write_rollout(/*archived*/ false, "2025-01-02T10-00-00", filename_id);
let contents = std::fs::read_to_string(&path).expect("rollout file");
let mut rollout_line =
serde_json::from_str::<RolloutLine>(contents.trim()).expect("rollout line");
codex_rollout::parse_rollout_line(contents.trim()).expect("rollout line");
let RolloutItem::SessionMeta(session_meta) = &mut rollout_line.item else {
panic!("expected session metadata");
};
@@ -1148,7 +1148,7 @@ mod tests {
fixture.write_rollout(/*archived*/ false, "2025-01-02T10-00-00", filename_id);
let contents = std::fs::read_to_string(&path).expect("rollout file");
let mut rollout_line =
serde_json::from_str::<RolloutLine>(contents.trim()).expect("rollout line");
codex_rollout::parse_rollout_line(contents.trim()).expect("rollout line");
let RolloutItem::SessionMeta(session_meta) = &mut rollout_line.item else {
panic!("expected session metadata");
};