69fd61b0ef
Switching to a long tool-heavy session still painted the tail, then jumped a full viewport when the first backfill step committed, on current main. Root cause: anchorBeforePrepend() skipped while the load was unsettled, but the settle loop hands a bottom-pinned load back at the FIRST-PAINT height, before the backfill transition commits. Every backfill step therefore ran unanchored; the prepend grew scrollHeight by thousands of px with scrollTop untouched and the view sat near the top until use-stick-to-bottom's ResizeObserver re-pinned it frames later (measured CLS 0.6-1.0 per switch, layout-shift entries of 0.61). Fix: - anchor a bottom-pinned load even while unsettled (shouldAnchorBeforePrepend); an unsettled offset restore still never anchors, the settle loop owns it - record the anchor's scrollHeight and consume it only on a taller tree, so a commit that does not grow content (transcript arriving under the first-paint budget, a store-window refresh) cannot spend the anchor as a no-op - clear any anchor on a cold switch, not only on a key change: the stale rows shown under the new key are collapsed by the swap and the anchor with them - do not arm the backfill while the transcript is empty or nothing is hidden Live A/B (isolated Desktop, Xvfb, CDP layout-shift capture, 3 rounds x 2 long sessions): main CLS 0.19-0.65 with one-frame 3-4k px scroll jumps every switch; fixed CLS 0 on every warm switch and no scroll jump (cold first open of a session keeps only the sub-0.1 first-paint shifts). Show-earlier and remembered offset restore controls unchanged.