fix(ui): hear the reader when resize lands before scroll - #4809
Draft
Astro-Han wants to merge 1 commit into
Draft
Conversation
ResizeObserver wrote the tail whenever the pin was still on. A reader who had already moved scrollTop — with the scroll event still in flight — was yanked back. That is the Storybook smoke flake on ReaderScrolledUpIsNotPulledBack, and a real path: uncovering estimated Turns is itself a layout pass. The classifier that already distinguishes content from the reader on scroll events now runs on resize too. It is not the write-echo check: growth under a pin leaves scrollTop on lastWrittenTop until the follow write happens. Generated-by: Cursor Grok 4.6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Main's Storybook smoke has been red on about half the runs that actually execute it since #4766 landed. Two AppShell stories take turns failing; the product defect underneath is in
TranscriptScrollAuthority, not in those play functions.ResizeObserver wrote
scrollTopto the tail whenever the pin was still on. Pin is only updated onscrollevents. The two deliveries are unordered. A reader who has already moved the offset — typical whencontent-visibility: autoresolves estimated Turns they just uncovered — gets yanked back if the layout callback wins. That is a normal user path, not a test-only race, and it is alsoReaderScrolledUpIsNotPulledBackassigningscrollTopthen waiting six frames.The classifier that already distinguishes "content moved the offset" from "the reader did" on scroll events now runs on resize too. It is not the write-echo check: growth under a pin leaves
scrollToponlastWrittenTopuntil the follow write happens, so treating that as an echo would stop following.This PR does not rewrite the AppShell stories and does not change the
distance ≤ 4tail bound. Those stories still drive the scroller by assigningscrollTopand by injecting a raw box; that belongs with the coming transcript-scroll restructure.TailFollowsGrowthOutsideTurnsmay still flake if a scroll event mis-classifies acontent-visibilitycorrection before resize runs — that is a different, remaining hole.Refs #4766
Verification
npx tsx --test src/__tests__/transcript-scroll-authority.test.tsinpackages/ui: 14 passed, including the new case that failed before the change (Expected 2400 !== 1900when resize yanked the reader back).npm run formatandnpm run lint: clean.@maka/uitest:dist(workspacetsccurrently fails on unrelated locale typing), Storybook smoke, Desktop e2e.AI use
Tool(s) and scope: Cursor Grok 4.6 diagnosed the main CI flake, wrote the failing unit test, and applied the classifier to the ResizeObserver path. Commits carry
Generated-by: Cursor Grok 4.6.Checklist
Does this PR entail a change in behavior?
A reader who has left the tail is no longer pulled back when a layout pass arrives before the corresponding scroll event. Pinned following is unchanged: content growth still writes the tail.