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

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

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.