You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(ghosts): Codex text ghosts are never superseded (response id vs rollout turn id) #1231
Found in the #1227 review (reviewer A, finding 1).
Codex ghosts are minted with turnId = the proxy response id (resp_…). Committed entries carry codexTurnId = the rollout's turn_context.turn_id (a UUID, providers/codex/renderer/transcript/rollout.ts:242). The two never match, and text blocks have no tool id to fall back on, so reconcileUpstream cannot supersede any Codex text ghost. Every one orphans 30 s later.
Live panes: these ghosts stay hidden only by render rule 3 (the turn is in semantic history) or rule 4.
Scope note after #1227 closed (the on-disk ghost log is being removed): this issue still matters for LIVE Codex ghosts, which reconcile can never supersede. Only the restore half is moot.
Restore: ghosts are now in-memory only (no on-disk log), so restored panes carry no ghosts. The "388 visible rows on restore" no longer applies.
Live panes: unsuperseded Codex text ghosts are still hidden only by render rules 3 and 4. That makes this a latent identity weakness, not a visible bug today, so it is lowered to P3.
Two identity routes, both verified on a real rollout (rollout-2026-09-25T05-55-26-…):
Response to turn map: every token_usage_record carries {turn_id, response_id} (33 in that rollout). A response's output items (reasoning, message, tool call) precede its usage record, and the tool output follows it. The mapper can't stamp items at ingest (no lookahead), but on a usage record the ingest sites (useIpcSubscriptions, initialHistory, reconstructSlices) can supersede ghosts whose turnId === response_id. This needs MappedTranscriptEntry to carry that fact.
Item ids: every rollout response_item carries its id (msg_, rs_, ctc_), and the proxy SSE sees the same ids. Semantic blocks don't record them yet (a codex-headless package change), but they would give an exact per-block match.
C8 hunt (2026-09-25): still reachable. Codex text ghosts carry the live response id (resp_…) as turnId, while committed entries carry the rollout turn UUID in codexTurnId, and nothing stamps the response id onto mapped entries. So Codex ghosts are never superseded; they orphan after 30 s and are hidden only by selectMergedEntries rules 3-4 (ghosts.ts:405-436).
Activity
fix(workspace): restore holds only ghosts the committed tail has not …
Juliusolsson05 commentedon Sep 25, 2026
Scope note after #1227 closed (the on-disk ghost log is being removed): this issue still matters for LIVE Codex ghosts, which reconcile can never supersede. Only the restore half is moot.
Juliusolsson05 commentedon Sep 25, 2026
Re-audit after #1235 (quality loop, 2026-09-25):
Two identity routes, both verified on a real rollout (
rollout-2026-09-25T05-55-26-…):token_usage_recordcarries{turn_id, response_id}(33 in that rollout). A response's output items (reasoning, message, tool call) precede its usage record, and the tool output follows it. The mapper can't stamp items at ingest (no lookahead), but on a usage record the ingest sites (useIpcSubscriptions,initialHistory,reconstructSlices) can supersede ghosts whoseturnId === response_id. This needsMappedTranscriptEntryto carry that fact.response_itemcarries its id (msg_,rs_,ctc_), and the proxy SSE sees the same ids. Semantic blocks don't record them yet (a codex-headless package change), but they would give an exact per-block match.Route 2 is the more precise one.
Juliusolsson05 commentedon Sep 25, 2026
C8 hunt (2026-09-25): still reachable. Codex text ghosts carry the live response id (
resp_…) as turnId, while committed entries carry the rollout turn UUID incodexTurnId, and nothing stamps the response id onto mapped entries. So Codex ghosts are never superseded; they orphan after 30 s and are hidden only by selectMergedEntries rules 3-4 (ghosts.ts:405-436).docs(ghosts): correct three comments that still described the turn-id…
test(ghosts): drive the production mapper; say reasoning ghosts are n…