Repository navigation
fix(codex): same-millisecond rollout items are no longer dropped (#1288) - #1298
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…items are not dropped (#1288) The entry uuid, the renderer marker and main's marker were three copies of ts:id|call_id|type. A call and its output in one millisecond shared a uuid, as did id-less items (message), and admission dropped the second for good. One shared codexRolloutIdentity now keeps ids as-is, suffixes call outputs, and disambiguates type-only items by a content hash (a re-read still dedupes). A missing timestamp no longer mints a new identity per read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
…ithful fixture, marker parity pinned - A: one call can record two different outputs in the same millisecond (a real rollout: session_id 88325 then 39977); outputs now carry a content hash too, so both are admitted while a re-read still dedupes. - B: the call/output fixture had its exec wrapper 'redacted' away, which changed what the mapper does. It is now the recorded kept pair (an Edit call and its error output), plus the recorded two-output pair. - B: nothing pinned main's marker to the renderer's; a re-inlined old rule passed CI. A parity test now compares them on every recorded shape. - The exec-wrapper predicate's comment said 'only the wrapper'; it drops any wrapped output because exec_command_end carries the result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Final disposition (pre-merge), head 1739a92. Three independent reviewers:
Every commit after 7b2fb1a is a merge from main, and none of them touches this PR's files.
Findings and dispositions: Round 1 (majors fixed in 7b2fb1a)
Round 2
Round 1, reviewer C (final head; all minor)
Residuals:
Merges through batch PR #1318 once every member passes its gate. 🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1288.
Found by the Stage 3 C8 hunt. Plan:
docs/plans/2026-09-25-codex-rollout-identity.md(first commit).Why
Codex rollout lines have no uuid. The renderer's entry uuid, the renderer's marker and main's history marker were three copies of
${timestamp}:${id ?? call_id ?? type}. That rule is not unique:ts:call_id.message) in the same millisecond sharets:message.Committed-record admission dedupes by uuid, so the second item was dropped on every path (live, initial history, older pages, remote client, rendering replay), permanently and silently. The result is a tool card with no result, or a message that never rendered. A third reviewer's recount of the owner's corpus under the old rule found 4,976 dropped items in 1,300 of 2,231 rollouts; 4,767 of them had content that differed from the item kept.
What merges
One shared
src/shared/codex/rolloutIdentity.ts, used by all three sites:idstaysts:id.ts:call_id, and its*_outputbecomests:call_id:output:<fnv1a(payload)>, so two different outputs of one call differ.ts:type:<fnv1a(payload)>, so different items differ and a re-read still dedupes.'', notDate.now().Main's
extractCodexHistoryMarkeris exported so a test can hold it equal to the renderer'scodexHistoryMarker.The
isCodexExecWrapperOutputcomment inentries.tsis corrected. The predicate matches any exec-wrapped output, not "only the wrapper". The predicate itself is unchanged.Markers aren't persisted, and older pages anchor by byte offset, so no migration is needed.
Tests
rolloutIdentity.test.tshas 6 tests. They drive recorded rollout lines (testing/fixtures/codex-identity/same-millisecond-2026-04.json) through the real mapper andadmitMappedEntries. Only paths, strings and ids are redacted. The recorded lines are:<tool_use_error>output in the same millisecond;custom_tool_call_outputrecords of one call in the same millisecond;The tests also cover stable identity on re-read and without a timestamp, and marker parity between main and the renderer on every fixture line.
npx tsc -bis clean.Residual
isCodexExecWrapperOutputstill drops exec-wrappedfunction_call_outputresults. In the owner's corpus noexec_command_endevent replaces them, soexec_commandcards (including Codex transcript silently drops a tool result or message that shares a millisecond with its sibling #1288'sdf -hexample) can still show no result. That is a separate, older cause, and it needs its own issue.'live'mode.historyLoader.test.tsstill uses the old marker rule as its oracle.🤖 Generated with Claude Code