TUI prepends paginated history before fork lineage on resumed forked threads
Open 💬 1 comment Opened Aug 9, 2026 by 92645417d9e5c763259dbebc306e3e
What version of Codex CLI is running?
rust-v0.148.0-alpha.1
What subscription do you have?
- ChatGPT Pro 20x
Which model were you using?
gpt-5.6-sol
What terminal emulator and version are you using (if applicable)?
- Alacritty with Codex running inside tmux
What issue are you seeing?
- Resuming a forked thread initially renders
Thread forked from ...before the child transcript, but loading an older paginated history page inserts those messages before the lineage marker. - The marker then appears inside the child transcript instead of remaining its ancestry boundary, even though the persisted parent metadata is intact.
- This makes older child messages look as if they precede the fork relationship and obscures where the resumed thread came from.
What steps can reproduce the bug?
- Create a fork from a thread with enough inherited or child history to require more than one history page.
- Resume the forked thread in the TUI and confirm that
Thread forked from ...appears before the initially loaded messages. - Scroll to the beginning or otherwise trigger loading the preceding history page.
- Observe that the newly loaded messages are inserted before
Thread forked from ....
What is the expected behavior?
- The fork lineage marker should remain before every transcript item belonging to the child thread as older pages are prepended.
- Initial resume and later pagination should preserve the order
fork lineage,older child history,newer child history.
Additional information
- Fork lineage is currently emitted before the initial history replay buffer begins and is represented as an ordinary transcript cell.
- The non-overlay pagination path chooses an insertion point only after the last session-info cell, defaulting to index zero when that cell is absent.
- The lineage cell is therefore not recognized as a structural insertion boundary.
- This issue report was written with assistance from Codex CLI.
1 Comment
Structural cause, from the TUI side: the
Thread forked from …marker is an ordinary history cell emitted once at resume time (emit_thread_forked_event, https://github.com/openai/codex/blob/1f41cc5d92/codex-rs/tui/src/chatwidget/session_flow.rs#L218-L233) — it's just whatever happens to be first intranscript_cellswhen the initial page renders. Older-page loads then prepend fetched entries at the absolute top of the transcript, with no concept of a pinned ancestry boundary, so eachnext_older_cursorbatch lands above the marker and the lineage line migrates into the middle of the child history, exactly as you observed. The persisted metadata is fine; only the insertion anchor is wrong.Two fix shapes: (1) make the marker a pinned prologue — track its cell index (or give lineage cells a kind flag) and have the older-page prepend insert after any leading lineage cells; or (2) stop emitting it at resume and instead render it as part of whichever page contains the thread's true beginning (i.e., only when
next_older_cursoris exhausted), which also fixes the subtler cousin: on a multi-page child, the marker currently implies "everything below is post-fork" even before pagination rearranges it. Option 2 is more honest about what the marker means; option 1 is the smaller diff.