Preserve floating-point values when decoding rollout lines (#38399)

## Why

Serde's generic buffering for flattened and internally tagged fields is incompatible with `serde_json`'s `arbitrary_precision` representation. As a result, persisted rollout items containing nested floating-point values can fail to decode.

## What changed

- Decode the rollout envelope at the JSON persistence boundary before deserializing the item payload.
- Use the shared decoder for both session resume and thread-history projection.
- Cover token-count floats, response-item metadata, field ordering, and ignored metadata in the decoder compatibility test.

GitOrigin-RevId: 59c7f6fbcf83162b5ed6980a69381fe45fc20a0a
This commit is contained in:
Tamir Duberstein
2026-08-13 16:03:20 +00:00
committed by copyberry
parent 053dda6b89
commit 2bd8727a0c
4 changed files with 60 additions and 4 deletions
@@ -5,7 +5,6 @@ use chrono::DateTime;
use codex_app_server_protocol::ThreadHistoryChangeSet;
use codex_app_server_protocol::project_rollout_line;
use codex_protocol::ThreadId;
use codex_rollout::RolloutLine;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncSeekExt;
use tracing::warn;
@@ -150,7 +149,7 @@ async fn read_projection_steps(
}
};
let value_ordinal = value.get("ordinal").and_then(serde_json::Value::as_u64);
let line = match serde_json::from_value::<RolloutLine>(value) {
let line = match codex_rollout::decode_rollout_line(value) {
Ok(line) => Some(line),
Err(err) => {
warn!(