You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Re-examine the click-to-focus test (tests/e2e/matrix.spec.ts, "click-to-focus fixes the node, animates the camera, and reset restores the view") in light of #55, which proved that a stray node capture at a hard-coded screen coordinate — not browser/rasterizer nondeterminism — was the real mechanism behind a long-standing "flake".
This issue is not a claim that #34 is unfixed. #34 received a genuine root-cause fix (65a1ad7, 2026-07-20): the library resolves hover only in the render loop's throttled raycast and defers onClick a frame past pointerup, so under software WebGL a bare click could resolve against a not-yet-committed hover; settleHoverThenClick forces a committed hover raycast before pointerdown. That mechanism is documented in tests/e2e/pointer.ts and is not in question here.
Motivation
#55's finding. The Firefox background-drag flake was blamed for years on "synthetic-input-delivery nondeterminism". Instrumentation refuted that (12/12 pointermoves delivered in every failure) and proved H1 stray node capture: the hard-coded drag start (150, 450) intermittently landed on a node whose screen projection had grown after the wheel-zoom, DragControls grabbed it, and the Trackball was disabled. Rasterizer-independent (CPU-side three.js raycast → survived on RTX 3080), per-run-random (random layout seed), Firefox-dominant (zooms ~18–22% closer → bigger projections).
The link to this test. This test contains its own unexplained stray-node problem, and it is structured around a hard-coded screen coordinate in a moving scene — the exact anti-pattern #55 fixed. From matrix.spec.ts:
// Wheel from a corner: while zooming through the rotating cloud, nodes sweep
// under the pointer, and the hover pipeline can otherwise register a stray
// node click that stops rotation and fixes a node prematurely.
await page.mouse.move(60, 540);
and, immediately after:
// The wheel path itself occasionally registers a stray node interaction
// (observed in both engines) that fixes a node and stops rotation. [...]
// on a stray, restart from a fresh page instead of aiming into a corrupted state.
That is a static pointer, moving scene variant of #55's static coordinate, changed scene. The parked corner (60, 540) is asserted-empty by nothing; the loop then wheels the camera 60 bursts closer, growing every node's projection, while the cloud auto-rotates. Nodes sweeping under a parked pointer is precisely how a hover-pipeline stray click would arise. The current handling is a recovery loop (detect fixedNodeCount !== 0, full page reload, retry, up to 2×) — i.e. we detect and recover from the symptom without having proven the cause.
Why now.#55 left behind exactly the tooling to settle this, deliberately retained for future background-point triage:
nodeOccupancyAtPoint / __graphNodeOccupancyAtPoint in tests/e2e/graph-handle.ts — the DragControls-mirroring hit test that was the H1 discriminator.
pickBackgroundDragPoint — max-edge-clearance point selection with a pixel-margin floor.
The out-of-tree amplified-reproduction harness under tests/diagnostics/55-drag/ (own playwright.diag.config.ts), a re-runnable template for this investigation.
If confirmed: replace the parked corner with a probe-verified clearance point maintained across the zoom (reuse/extend pickBackgroundDragPoint; the point must stay clear as projections grow, so re-probing between bursts may be needed). The recovery-reload loop then becomes dead code and can be retired.
If refuted: document the actual mechanism and keep the recovery loop, with the refutation recorded so the next reader does not re-open this.
Phase C — Re-qualify the residual scaffolding (secondary, gated on B).
Only after A/B settle, audit each item on evidence — retire what no longer earns its keep, keep and justify the rest:
test.setTimeout(240_000) — the suite's only 240 s override.
The 60-burst adaptive zoom loop with 600 ms / 2 500 ms stall pauses.
.github/workflows/validation.yml byte-for-byte unchanged; the absolute CI → workers: 1 guard stays intact. Any change to CI retries is a config-line change with recorded evidence, nothing more.
Goal
Re-examine the click-to-focus test (
tests/e2e/matrix.spec.ts, "click-to-focus fixes the node, animates the camera, and reset restores the view") in light of #55, which proved that a stray node capture at a hard-coded screen coordinate — not browser/rasterizer nondeterminism — was the real mechanism behind a long-standing "flake".Two questions, in order:
This issue is not a claim that #34 is unfixed. #34 received a genuine root-cause fix (
65a1ad7, 2026-07-20): the library resolves hover only in the render loop's throttled raycast and defersonClicka frame pastpointerup, so under software WebGL a bare click could resolve against a not-yet-committed hover;settleHoverThenClickforces a committed hover raycast before pointerdown. That mechanism is documented intests/e2e/pointer.tsand is not in question here.Motivation
#55's finding. The Firefox background-drag flake was blamed for years on "synthetic-input-delivery nondeterminism". Instrumentation refuted that (12/12 pointermoves delivered in every failure) and proved H1 stray node capture: the hard-coded drag start
(150, 450)intermittently landed on a node whose screen projection had grown after the wheel-zoom,DragControlsgrabbed it, and the Trackball was disabled. Rasterizer-independent (CPU-side three.js raycast → survived on RTX 3080), per-run-random (random layout seed), Firefox-dominant (zooms ~18–22% closer → bigger projections).The link to this test. This test contains its own unexplained stray-node problem, and it is structured around a hard-coded screen coordinate in a moving scene — the exact anti-pattern #55 fixed. From
matrix.spec.ts:and, immediately after:
That is a static pointer, moving scene variant of #55's static coordinate, changed scene. The parked corner
(60, 540)is asserted-empty by nothing; the loop then wheels the camera 60 bursts closer, growing every node's projection, while the cloud auto-rotates. Nodes sweeping under a parked pointer is precisely how a hover-pipeline stray click would arise. The current handling is a recovery loop (detectfixedNodeCount !== 0, full page reload, retry, up to 2×) — i.e. we detect and recover from the symptom without having proven the cause.Why now. #55 left behind exactly the tooling to settle this, deliberately retained for future background-point triage:
nodeOccupancyAtPoint/__graphNodeOccupancyAtPointintests/e2e/graph-handle.ts— the DragControls-mirroring hit test that was the H1 discriminator.pickBackgroundDragPoint— max-edge-clearance point selection with a pixel-margin floor.tests/diagnostics/55-drag/(ownplaywright.diag.config.ts), a re-runnable template for this investigation.Scope
Phase A — Instrument the stray (primary).
nodeOccupancyAtPoint(60, 540)across thezoomIntoClickRangeburst loop and correlate occupancy hits withfixedNodeCount0→1 transitions, using Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55's instrument-first method (out-of-tree diagnostic harness; canonical suite untouched during investigation).Phase B — Fix or justify (conditional on A).
pickBackgroundDragPoint; the point must stay clear as projections grow, so re-probing between bursts may be needed). The recovery-reload loop then becomes dead code and can be retired.Phase C — Re-qualify the residual scaffolding (secondary, gated on B).
Only after A/B settle, audit each item on evidence — retire what no longer earns its keep, keep and justify the rest:
test.setTimeout(240_000)— the suite's only 240 s override.retries: 2(playwright.config.ts:132) — landed as Flaky CI e2e: click-to-focus (matrix.spec.ts:235) intermittently fails on SwiftShader (~50% observed 2026-07-20) #34's mitigation before the root-cause fix existed. Measure the current flaky-marked rate in merged Playwright reports first; do not remove it on vibes.Constraints and invariants
MOTION_FLOOR, localretries: 0, and the real synthetic gesture path stay as strict as they are. Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55 fixed the cause rather than relaxing the test; same bar here..github/workflows/validation.ymlbyte-for-byte unchanged; the absoluteCI → workers: 1guard stays intact. Any change to CIretriesis a config-line change with recorded evidence, nothing more.tests/diagnostics/(the FR2 pattern from Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55); the committedtests/e2e/delta should be the fix plus any cheap probe.npm run validateremains the green gate.Definition of Done
zoomIntoClickRangeconfirmed or refuted with instrumented, verbatim evidence (occupancy ⟺fixedNodeCount0→1 correlation table, in Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55's format).retries: 0— Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55's bar.65a1ad7, and recorded.npm run validategreen on a clean detached-HEAD worktree with realnpm ci(lessons-critical clean-checkout rule).retries: 2remains warranted.Non-goals
DEFAULT_LOCAL_WORKERSdefault (blocked on deterministic Chromium SwiftShader parallel contention; see Make the native-GPU e2e lane default to parallel workers (SwiftShader gate stays serial) #56 and Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55's follow-ups).References
pickBackgroundDragPoint,nodeOccupancyAtPoint,tests/diagnostics/55-drag/.codev/reviews/55-firefox-background-drag-flake.md.retries: 2mitigation; hover-first fix65a1ad7.tests/e2e/pointer.ts).tests/e2e/matrix.spec.ts(click-to-focus test),tests/e2e/pointer.ts,tests/e2e/graph-handle.ts,playwright.config.ts:116-132.codev/resources/lessons-learned.md, added by Firefox e2e flake: "background drag" rotation (matrix.spec.ts:224) — synthetic-input-delivery nondeterminism (survives on hardware) #55): a hard-coded "background"/empty screen coordinate in an interaction test is not guaranteed to stay empty when the scene changes.