mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
The mid-history correction's momentum-skip gate keyed on the raw `scrollTop` delta since baseline. On WebKit, momentum is coalesced into `scrollTop` on the compositor's own async clock, so a frame that PAINTED still can read a large raw delta and wrongly skip a genuine above-anchor reflow — the reversal survivor bin (the 204px-class lurch of #1662). Rekey the gate onto the RENDERED scroll — the painted wheel motion this frame — `renderedScroll = aboveShift - ΔtopOffset`: the anchor's painted on-screen move with the reflow's own push removed, both terms read from the painted DOM (getBoundingClientRect), not the possibly-ahead `scrollTop`. A rendered-still frame now reads ~0 and the reflow is corrected instead of dropped. Because the gate now needs `aboveShift` to decide, the band walk runs before the gate. To keep "under-correcting is invisible; the next quiet frame catches up," `sumAboveAnchorShift` no longer refreshes the height cache inline — it STAGES the refresh and returns `{ aboveShift, commit }`. The caller applies `commit()` only past the gate, so a momentum skip leaves the cache for the next frame; a kept correction refreshes it as one indivisible pass (the "second observer no-ops" invariant is intact). Arbiter contract, fresh w4a-gate-1 build, both engines: - raf-correction HARD gate: Chromium 0 reversals, rAF fires 0 / RO 21 (RO sole writer); WebKit 2 reversals max 14.5px (<=34 quantum floor), rAF fires 24 / RO no-op (residual 0.0). Ratified invariants hold. - slow-scroll: 0 reversals both engines (felt low-velocity regime clean). - fast-classify DECOMPOSITION self-test (WebKit): pure-reflow attempts median |signedShift|=18.5 but median |renderedScroll|=0.0 — the reflow does NOT leak into the gated quantity, and 19/28 fire. Pure-scroll |renderedScroll| runs up to 28. The decomposition is proven, not asserted. Guarded WebKit-only: on Chromium the rAF is the passive loser observer (RO corrects first), so renderedScroll there tracks signedShift by construction — characterized, not asserted. KNOWN RESIDUAL (surfaced, not hidden): 2 WebKit survivors remain, but they are a DIFFERENT class — signedShift=0.0 (the band walk sees no above-anchor reflow) while the row still lurches 14.5px. The momentum-gate survivors the rekey targeted are gone; these are cross-check/null-target skips where the reflow is invisible to the band walk. Separate diagnosis. Diagnostic-only `renderedScroll` is threaded through the shared result type + emitted on the rAF probe so the fixture can prove the decomposition; stripped/gated before merge per the file-size exit condition. Raises the useAnchoredScroll.ts size exception 1180->1210 to cover the arm (biome reflows the 4-prop returns); flagged in the override comment for Eva as heavy-for-a-diagnostic. Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Signed-off-by: Tyler Longwell <tlongwell@block.xyz>