Fix Live Tape Scroll Stability
Completed on 2026-05-17 at 03:31 America/New_York for Beads issue
islandflow-9dg.
Summary
The live tape now keeps the visible scrolled segment stable while new prints arrive. When the user is away from the top, the view freezes both the hot live head and the displayed history segment, only allowing genuinely older history to append below the current tail.
Changes Made
- Added
mergeHeldTapeHistoryto filter held history updates by the visible tail. - Updated
usePausableTapeViewto keep a displayed history ref while scroll-held. - Resynced displayed history automatically when the user jumps back to the top or otherwise resumes.
- Increased tape virtualizer overscan for options, equities, flow, alerts, classifier, and dark panes.
- Added a fixed row-lane table background so fast scrolling shows a stable substrate instead of blank holes.
Context
Live session history receives both ClickHouse history and hot-window overflow from new live prints. Before this change, the pausable view froze live rows during scroll hold but still composed against the mutating history array, so newer overflow rows could insert above the user's current viewport.
Important Implementation Details
The stable merge compares incoming history with the current displayed history tail. Rows newer than that tail are withheld during hold, duplicates from the frozen live head are removed, and older lazy-loaded rows remain eligible to append.
const next = mergeHeldTapeHistory(displayedHistoryRef.current, historyItems, projected.items);
When hold ends, displayedHistoryRef is replaced with the latest live session
history, so buffered overflow catches up cleanly on jump-to-top.
Expected Impact for End-Users
Users can scroll into older options or equities prints without the rows shifting under them
as new live prints arrive. The +N new counter can continue accumulating until
they jump back to the top, where the tape catches up.
Validation
bun test apps/web/app/terminal.test.ts services/api/tests/live.test.ts: passed, 90 tests.bun --cwd=apps/web run build: passed.curl -I http://localhost:3000/tapeagainst the local dev server: returned 200 OK.
Issues, Limitations, and Mitigations
This change preserves row stability in the frontend view model. It does not alter backend history pagination or wire protocols. The fixed table substrate mitigates visual blanking during fast scrolls, while actual row rendering remains virtualized. Browser automation was attempted, but the local Node automation runtime did not have Playwright installed, so the handoff relies on unit tests, production build, and the local HTTP smoke check.
Follow-up Work
No follow-up Beads issues were needed for this turn.