Repository navigation
Unified scrollback to the start of history: one disk-paged surface with the live turn, on by default #3856
Description
Part of #3868 (follow-ups to #854). This is #854 ask 1: trim scrollback to what is needed in memory, and let the user scroll back through the whole session, loaded from disk.
Problem
Today scrollback stops early. With the disk pager off (the default after #3852), the transcript is the in-memory fallback list, capped at 400 items or 4 MiB (DEFAULT_HISTORY_MAX_ITEMS, DEFAULT_HISTORY_MAX_BYTES, same as main). Older items are dropped and cannot be scrolled back to.
#854 added a file-driven scrollback pager (ui.scrollbackPagerEnabled). It pages the alternate-buffer transcript from the session journal through ProjectedJournalCursor, with a window bounded by viewport and eviction, and shows compression points as summary rows. It is off because it cannot render an interactive turn the way the in-memory transcript does; with it on, the Interactive UI (tmux) suite fails (approval dialogs, always-allow, long output, the issue 2208 and memory-profile scenarios).
What is missing:
- No live tail.
ScrollbackPagerStore.setLiveTailandcommitPendingRowhave no production callers. Streaming text, tool groups and confirmation dialogs are never fed to the pager. - No journal tailing. The pager reads the journal once in
resumeFromJournaland does not extend on appends. A draft subscribes toSessionRecordingService.onCommitWatermarkand callsProjectedJournalCursor.extend. - Journal rows are not display rows. The journal records tool response content, not the tool's
resultDisplay, and has no UI-only items (info and error messages, slash-command output). A journal-projected tool row shows raw response JSON instead of the display string. - Bootstrap race.
useScrollbackBootstrapcan render "scrollback unavailable: no journal" before the journal path is known, then rebind.
Options for item 3: record resultDisplay and UI-only rows in the journal as display-only records that the model-history fold ignores; or overlay committed tool-group items by call id, limited to the window.
Acceptance
- One scroll surface: committed rows come from the journal, the live turn sits at the bottom, with no seam between them.
- The user can scroll back to the session's first row, across compressions and resumes. No item-count cap.
- Pager memory stays bounded by the window, the live tail and mutation events. Large old tool output is rendered within the visible-window budget (see Budget message component rendering to the visible window: diff and markdown process full buffers before clipping #3431).
- With the pager on,
LLXPRT_E2E_TMUX=1 bun test scripts/tests/interactive-ui.test.tspasses every scenario twice in a row. - Ink render tests cover the live tail, committed rows after append, the tool result after approval, and deterministic bootstrap.
- The pager is on by default, and the fallback ledger's cap no longer limits scrollback.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
github-actions commentedon Oct 11, 2026
LLxprt Issue Planner — infrastructure failure
The autonomous planner failed with exit code 1. Please inspect the workflow logs (Run planner agent section) and re-run once resolved.
[-]Scrollback pager cannot render live turns: journal rows lack tool resultDisplay and UI-only items[/-][+]Unified scrollback to the start of history: one disk-paged surface with the live turn, on by default[/+]