Skip to content

perf(flowchat): Improve long-session scrolling and history paging - #3198

Merged
wsp1911 merged 8 commits into
GCWing:mainfrom
wsp1911:dev-omen
Sep 22, 2026
Merged

wsp1911 merged 8 commits into
GCWing:mainfrom
wsp1911:dev-omen

Conversation

@wsp1911

@wsp1911 wsp1911 commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Defer Markdown parsing and mounting for collapsed thinking cards. Stop hidden typewriter playback after the collapse transition and skip summary-preview work for ordinary reasoning.
  • Synchronize virtualizer offsets after measurement compensation and capture prepend geometry immediately before DOM mutation.
  • Narrow CSS sibling invalidation in Markdown and shared UI components, and batch OverflowText measurements per window and animation frame.
  • Replace history paging latches with a controller that coordinates requests, committed layout, and reader demand. Add regression coverage and update frontend performance and paging guidance.

Type and Areas

Type: Performance improvement / bug fix / refactor

Areas: Web UI, FlowChat, Markdown rendering, shared design system, docs

Motivation / Impact

Long conversations containing large thinking and tool cards could show substantial temporary blank regions during fast scrolling. Hidden Markdown work, broad CSS invalidation, and stale virtualizer offsets contributed to the cost of changing the visible window.

These changes reduce unnecessary rendering and style work while preserving collapse transitions, Markdown spacing, and viewport ownership. Manual retesting showed substantially fewer temporary blank regions. Matched DOM trace samples also showed lower individual style-recalculation costs; these are individual measurements, not a general speedup guarantee.

A separate paging defect prevented loading more history after the first successful page. Window changes cleared boundary-arrival history while leaving paging disarmed. The new controller supports continued prefetch without requiring physical boundary arrival, preserves demand during loading, and prevents layout compensation from generating additional requests. The user confirmed that the original paging failure is resolved.

Verification

Recorded during implementation and probe cleanup; tests were not rerun solely to prepare this PR description.

  • Web UI TypeScript: passed.

    pnpm --dir src/web-ui exec tsc --noEmit
  • Focused paging, viewport, and prepend regression tests: 94 passed.

    pnpm --dir src/web-ui exec vitest run \
      src/flow_chat/components/modern/flowChatHistoryPager.test.ts \
      src/flow_chat/components/modern/flowChatHistoryBoundary.test.ts \
      src/flow_chat/components/modern/VirtualMessageList.session-boundary.test.tsx \
      src/flow_chat/components/modern/useFlowChatViewportOwner.test.tsx \
      src/flow_chat/components/modern/ModernFlowChatContainer.history-state.test.tsx \
      src/flow_chat/components/modern/FlowChatPrependSnapshot.test.tsx
  • Earlier implementation checks passed for thinking-card lifecycle/typewriter behavior, Markdown rendering, OverflowText scheduling, and delayed virtualizer scroll events. The thinking/typewriter change passed 39 focused tests.

  • Focused ESLint, SCSS compilation, and theme color audits passed during the relevant changes.

  • Combined diff whitespace check: passed.

    git diff HEAD~7 HEAD --check

Manual evidence:

  • Repeated long-session scrolling showed substantially fewer temporary blank regions.
  • Performance traces supported targeted CSS invalidation improvements.
  • The user confirmed the consecutive history paging fix.

Limitations:

  • The earlier full pnpm run check:web attempt was blocked by existing mobile typography violations.
  • Full builds, packaging, remote scenarios, and the broader keyboard/touch/scrollbar matrix were not verified.

Reviewer Notes

  • Temporary probes and collection code have been removed.
  • OverflowText indicators and tooltips may update on the next animation frame. Its batching change and the prepend snapshot change do not claim an independently measured overall scrolling speedup.
  • CSS changes preserve spacing, border behavior, and selector specificity. Some narrowed selectors have invalidation evidence without a separately confirmed end-to-end improvement.
  • Expanded streaming Markdown still parses updated content; this PR does not introduce an incremental Markdown parser.
  • No persisted-data or transport-protocol changes are included.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

Avoid parsing and mounting hidden Markdown when collapsed thinking cards
enter the virtual window. Mount content on expansion and release it
after the collapse transition settles, preserving rapid reopen behavior
and existing typewriter reveal semantics.

Cover collapsed content updates, forced expansion, transition completion,
cancellation, and reopening with focused tests. Document the lifecycle.
Publish the actual viewport offset after accepted row measurement
compensation so window selection uses the updated position. This avoids
unmounting measured rows and mounting them again on delayed scroll events.

Cover delayed scroll and scroll-end delivery with the real virtualizer.
Narrow Markdown, usage metadata, dispatch checks, and NumberInput
sibling selectors to avoid invalidating unrelated transcript elements
when virtual rows change. Preserve spacing and border behavior, and
add renderer coverage plus frontend CSS invalidation guidance.

Matched DOM samples support style-time reductions for usage metadata
and dispatch checks. NumberInput and remaining Markdown rules have
invalidation evidence, but no confirmed overall scrolling speedup.

Validation: focused component tests, TypeScript, SCSS compilation,
and theme color audits passed. The full Web UI check remains blocked
by existing mobile typography violations.
Capture scroll height immediately before DOM mutation when history
moves the old head, rather than reusing a previous commit's height.
Keep compensation bounds and viewport ownership unchanged.

Cover intervening geometry changes, consecutive prepends, and
suspended viewport recovery. Browser performance and remote behavior
remain separate validation requirements.
Coalesce label geometry reads before publishing overflow state through
a per-window frame queue. Preserve reentrant requests, cancel stale
results, and isolate callback failures while reporting their errors.

Document the deferred overflow indicator and tooltip timing. Cover
batch ordering, cancellation, reentrancy, and window isolation without
claiming an overall scrolling speedup.
Only compute summary previews for summary cards. Once a thinking card
finishes collapsing, cancel typewriter playback, catch up to the latest
content, and release its reveal gate. Preserve playback while closing
and resume new text normally after reopening.

Cover ordinary and legacy reasoning, summary kind changes, collapse
transitions, hidden updates, reopening, and finishing backlogs.
Validation: 39 focused tests, TypeScript, and diff checks passed.
Browser and remote validation remain pending.
The first page could clear boundary arrival history while leaving the
request disarmed, preventing further paging when the reader returned to
the top.

Replace the independent latches with a paging controller that tracks
request completion, committed layout, and coalesced reader demand. Keep
prefetch independent of physical boundary arrival and prevent viewport
corrections from triggering additional pages. Ignore stale request results
and protect newer requests during session changes.

Add regression coverage and update the paging contract. Remove temporary
instrumentation after the user confirmed the original issue is resolved.

Validation: 94 focused tests, Web UI type checking, and focused ESLint pass.
Remote transports and the broader input-device matrix remain unverified.
Enable visual JSDOM windows for components using frame-based overflow
measurement, and close windows and restore globals after each test.

Load JSDOM outside the timeout indicator setup hook. Reuse the ESLint
Node API and real file-selected config instead of starting a new CLI
process for each adapter-fence probe. Preserve rule assertions without
increasing global timeouts or changing production behavior.

Validation: pnpm --dir src/web-ui run test:run passes all 858 files and
9293 tests. Focused ESLint and git diff --check also pass.
@wsp1911
wsp1911 merged commit 05dc08b into GCWing:main Sep 22, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant