Files
buzz/desktop
e729784935 fix(desktop): gate WebKit upscroll fallback on prev-rAF anchor agreement
The prior fallback fired `scrollTo(currentScrollTop + aboveShift)` whenever
the baseline-relative position diff read 0 and `|aboveShift| > 0.5`. On WebKit
that condition is not specific to a real reflow: the per-rAF baseline is
captured post-realization, so `baseline` and `current` straddle the SAME side
of the reflow (dTop=dScroll=0) on EVERY frame, and `aboveShift` — summed from
the RO entries — can be nonzero on a frame where the anchor never moved,
because a row straddling the anchor boundary is miscounted. The fallback then
fabricated a downward shove: the "Shape B" slow-trackpad lurch
(`e=0, rowMove=+35..41px, dScroll=0`) — firing the correction WAS the visible
jump.

Add a second, baseline-timing-independent signal and fire only when the two
instruments agree. Carry the anchor snapshot from the PREVIOUS rAF tick
(`prevReadingAnchorRef`), which — unlike the same-frame baseline — was captured
before this frame's realization and so spans the reflow. Its document-position
shift `observedShift = (scrollTop+topOffset) − prev(scrollTop+topOffset)` is
scroll-invariant (user scroll moves scrollTop and topOffset equal-and-opposite),
so it isolates the reflow alone (Eva's probe `e`, from one coherent snapshot;
Quinn's scroll-isolated `R_obs`). Fire only when `prev.id === baseline.id` AND
`|aboveShift − observedShift| ≤ 0.5`, and correct by `observedShift` (never raw
screen motion — that would refold the user's scroll into the pin).

Agreement is the classifier boundary. Two-population split of fallback frames
on the WebKit slow-trackpad probe:

  population         | aboveShift vs observedShift | old writer   | gated writer
  -------------------|-----------------------------|--------------|-------------
  real reflow        | agree (Δ ≤ 0.5px)           | corrects OK  | corrects OK
  straddler miscount | disagree (Δ = row height)   | fabricates   | suppressed
                     |                             | +35..41 shove|  (no write)

Suppressing the miscount branch removes the fabricated shoves without touching
the frames where the RO sum is genuine.

Validated (each run x2, stable):
- Shape-B fabricated `e=0` shoves: eliminated (was the dominant felt defect)
- Chromium slow-trackpad: 0 escapes, sync 0.00, felt 0.00 (no regression)
- WebKit felt/wheel gate: 0.91px peak (<< 2px threshold), was 0.00 pre-gate —
  the 0.91 is the frame-late CV-realization flash the miscount was masking
- WebKit slow-trackpad escapes: 67 -> 54
- 2167/2167 unit tests, tsc, biome clean

Residual (54 escapes) is a different phenomenon with a different owner: ~15
self-correcting frame-late flashes + ~12 multi-frame-blind under-corrections,
both rooted in WebKit delivering the CV-realization RO callback one frame after
the realization paints (documented in
RESEARCH/WEBKIT_RO_REALIZATION_FRAME_LATE_W1.md; overturns W4a doc lines 96-98,
which assumed the RO write is same-frame-visible on WebKit). That is a W4a
architecture item (Quinn owns direction; Max's W2 pre-realization band is the
A/B candidate), not a W1 branch-logic defect.

Co-authored-by: Dawn <dawn@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
2026-07-08 19:57:00 -04:00
..
2026-06-11 15:06:24 +00:00

Buzz

Desktop chat shell with:

  • Tauri + React + TypeScript + Vite
  • Tailwind CSS
  • shadcn/ui-ready shared components
  • Biome (lint/format/check)
  • Feature-driven frontend structure

Scripts

  • pnpm dev - run the web frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm format - Biome format (write)
  • pnpm check - Biome check

Structure

  • src/shared - reusable app-wide code (ui, lib, styles)
  • src/features - feature modules (vertical slices)
  • src/app - top-level app composition