Skip to content

bug(ui): transcript scroll geometry lost its warm-up, and the scrollbar drifts again on long sessions #5184

Description

@Astro-Han

What happened

On a long session the scrollbar thumb compresses and repositions while the reader scrolls up, and scrollHeight keeps changing without any content arriving. This is the symptom #828 fixed in July: never-rendered content occupies an estimated height until Chromium gets around to laying it out, so each upward step inflates the document and scroll anchoring compensates — the top keeps receding.

Since #5170 the Renderer also decides from this geometry when to fill an edge and what to trim (packages/ui/src/use-chat-scroll.ts, the two-screen fill and six-screen trim bands). Estimated heights that later grow make those bands fire early or late. That is a performance problem now, not a correctness one — the anchored window refuses anything it cannot splice — but it is the same root cause.

The chain

PR What it did to the guard
#828 8a47301a5 Added turn-size-warmup.ts: a chunked, bottom-up idle walk that forces each Turn through one rendering opportunity so the browser records its size. Measured: a 24-Turn session mounted at scrollHeight 14640 vs 31872 real, 51 anchor-corrected steps to reach the top; after warm-up, exact geometry and monotonic scrollTop.
#2462 2f5c75be0 Deleted turn-size-warmup.test.ts (8 cases) and e2e/scroll-geometry.spec.ts (565 lines) as "low-value" — the only tests that would have failed on the steps below.
#2975 6b8e3db26 Deleted turn-size-warmup.ts and turn-size-index.ts, replaced by a row virtualizer with spacers. Geometry was now the virtualizer's estimate.
#4206 c33617fd8 Deleted the virtualizer, height index, spacers and compensation state. Did not restore the warm-up.
#4259 d2d9f9060 Bounded rendering within oversized Turns with content-visibility line-block chunks (packages/ui/src/styles.css:744). The estimate is now per chunk inside a Turn, with nothing walking chunks to measure them.

Result: the browser's remembered-size mechanism is once again the only thing turning estimates into measurements, and it only runs for what scrolls into view — exactly the situation #828 measured.

How to reproduce

  1. A session with 20+ Turns of mixed length, at least a few long enough to be chunked by perf(desktop): bound rendering within oversized turns #4259.
  2. Open it at the tail, then scroll to the top with the wheel or the scrollbar.
  3. Watch scrollHeight (or the thumb): it grows step by step during the ascent; the top recedes.

The deleted e2e/scroll-geometry.spec.ts (git show 2f5c75be0^:apps/desktop/e2e/scroll-geometry.spec.ts) asserted constant height and monotonic scrollTop for this gesture. Restoring it is the regression; it should fail on main today.

Expected

Geometry that does not change under the reader when no content changed. Either bring the idle warm-up back for whatever now carries the estimate (line-block chunks after #4259), or seed chunk heights from measurement the way #2224 proposed for Turns. The regression that guards it must come back with the fix; #2462 deleting it is how the next three PRs got through.

Not in scope

The Renderer-owned window and its fill/trim bands (#5163 / #5170). They consume this geometry; they do not produce it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingeffort/LUnder 1000 readable lines

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions