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 authored and copyberry committed 2026-09-02 22:45:19 +00:00
1 parent e1d0ef995f
commit 69cebb5d15
49 files changed
+184 -114

No files matched your search

+2 -3
View File
@@ -22,7 +22,6 @@ use codex_extension_api::empty_extension_registry;
use codex_features::Feature;
use codex_history::CompactedItem;
use codex_history::RolloutItem;
use codex_history::RolloutLine;
use codex_login::AuthManager;
use codex_login::CodexAuth;
use codex_protocol::AgentPath;
@@ -1262,7 +1261,7 @@ async fn spawn_agent_fork_from_paginated_parent_uses_model_context_prefix() {
let lines = std::fs::read_to_string(&rollout_path)
.expect("read child rollout")
.lines()
.map(|line| serde_json::from_str::<RolloutLine>(line).expect("parse rollout line"))
.map(|line| codex_rollout::parse_rollout_line(line).expect("parse rollout line"))
.collect::<Vec<_>>();
let RolloutItem::SessionMeta(meta_line) = &lines[0].item else {
panic!("child rollout should start with session metadata");
@@ -1466,7 +1465,7 @@ async fn spawn_agent_fork_drops_inherited_token_usage_state() {
let lines = std::fs::read_to_string(&rollout_path)
.expect("read child rollout")
.lines()
.map(|line| serde_json::from_str::<RolloutLine>(line).expect("parse rollout line"))
.map(|line| codex_rollout::parse_rollout_line(line).expect("parse rollout line"))
.collect::<Vec<_>>();
assert!(
!lines.iter().any(|line| {