fix(flow-chat): drain stuck bottom whitespace after subagent card collapses - #2159
Open
YodonTan wants to merge 3 commits into
Open
fix(flow-chat): drain stuck bottom whitespace after subagent card collapses#2159YodonTan wants to merge 3 commits into
YodonTan wants to merge 3 commits into
Conversation
added 3 commits
August 7, 2026 00:41
…hitespace Add gated flow_chat_diagnostics probes that make a growing bottom blank attributable to its reservation owner: - Periodic bottom-reservation ledger sampling (collapse/pin px+floor, intent state, owner kind, coordinator mode, follow/streaming flags, scroller geometry) while the logging setting is enabled - Collapse-intent finalize retry counting plus a trace when the drain target is not renderable - Auto-follow suspension duration probe (fires once after 2s) - Subagent/task card ResizeObserver height-change correlation probes - Anchor-restore bottom-range additions tracked per source in the viewport coordinator - footer dataset.reservationPx so DevTools shows the synthetic tail space at a glance - flowChatDiagnostics.subscribe() so sampling can start/stop when the setting toggles at runtime
Long unbroken tokens (file paths, model names, URLs) inside the subagent projection text and task card headers could stretch the min-content width of the card and change the layout height. Add overflow-wrap:anywhere and min-width:0 so wrapping happens inside the card instead of widening the layout.
Subagent card collapses pre-compensate the footer with provisional tail space. At the physical bottom every settle variant recomputes exactly the current reservation as its geometric minimum (the synthetic footer holds scrollTop high), so collapse compensation could only drain through content growth or repeated up/down scrub cycles - the reported growing bottom whitespace that occasionally cleared on scroll. Introduce convergeBottomReservationsToContentBottom: when the scroller sits at the physical bottom with no preserving/pinned viewport owner and no active collapse intent, clear collapse + pin reservations in one synchronous footer update and fall scrollTop to the new content bottom. Wire it into retained quiet settlement, collapse-intent finalization (non-pinned strategies), the idle reservation audit, the scroll handler (any scroll event at the physical bottom is bottom intent), the collapse-intent accumulation guard (a new provisional estimate no longer stacks on a settled bottom reservation), and the input-stack-shrink drain. The idle audit only releases a preserved element anchor for bottom users; mid-list readers keep their reading anchor. Also bound collapse-intent finalize retries (20 max) so a virtualized sticky pin target cannot keep the intent (and auto-follow suspension) alive forever, and cap intent-window growth consumption at the measured protection line. Tests cover growth protection, convergence positive/negative cases, force settle at mid-list, and the stale-pin audit path.
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.
Fixes #2154
Problem
After a subagent (Task) card collapses, the chat viewport keeps a large block of blank space below the last message. The blank area grows with each subagent card event and only drains after manually scrubbing the scroll wheel (each round trip consumes only the upward-scroll distance). The scrollbar thumb sits at the physical bottom while hundreds of pixels of empty background separate the content from the input bar.
Root cause
Collapse-intent pre-compensation adds provisional footer space (
collapse.px) before the card shrinks. When the user is at the physical bottom, every settlement path dead-locks:settleCollapseReservationForViewport/ retained quiet settlement compute the geometric minimum for the currentscrollTop, but the synthetic footer itself holdsscrollTopat the physical bottom, so the minimum recomputes exactly the current reservation (e.g. 786px stays 786px).scrollDeltais 0 (scrollTop is capped by the footer).Multiple collapse intents (e.g. several parallel subagent failures) stack provisional estimates on the unsettled reservation (
base = current total compensation), which is why the whitespace grows monotonically during the session. Repeated up/down scrub cycles only consumed the upward-scroll distance per round trip.Changes
convergeBottomReservationsToContentBottom: when the scroller sits at the physical bottom (within 2px) with nopreserving-element/pinned-itemviewport owner and no active collapse intent, clear collapse + pin reservations in one synchronous footer update and fallscrollTopto the new content bottom (the delayed browser clamp that compensation was hiding). Wired into:settleRetainedCollapseRange)overflow-wrap: anywhere+min-width: 0on subagent projection text and task card headers so long unbroken tokens wrap inside the card instead of widening the layout.Tests
New component tests in
VirtualMessageList.session-boundary.test.tsx:data-reservation-pxfooter diagnosticsAll flow_chat modern + tool-cards tests pass (376),
type-check:weband ESLint are clean.Manual verification
Verified with a real streaming session: long-title subagent failures collapse without leaving bottom whitespace, repeated failures no longer accumulate blank space, and the viewport settles to the content bottom without scrub-wheel workarounds.