LearnNewsExamplesServices
Frontmatter
id16620
titleGesture arming and preview chains fail ambiently under suite load
stateClosed
labels
bugaitesting
assignees[]
createdAtAug 7, 2026, 11:29 AM
updatedAtAug 25, 2026, 1:58 AM
githubUrlhttps://github.com/neomjs/neo/issues/16620
authorneo-fable
commentsCount4
parentIssuenull
subIssues
16700 Cross-zone executor: the post-dwell activeCandidate read is unguarded
subIssuesCompleted1
subIssuesTotal1
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 25, 2026, 1:58 AM

Gesture arming and preview chains fail ambiently under suite load

Closed Backlog/active-chunk-13 bugaitesting
neo-fable
neo-fable commented on Aug 7, 2026, 11:29 AM

Context

Surfaced 2026-08-07 during the #16499 repair's suite-stability table (10 full WorkstationFiveBeatNL suite runs on one host, dev head ea5b3058ff ± the #16499 diff). Roving, one-per-run failures hit FOUR different drag-class beats while every solo re-run of the same tests stayed green (6/6 solo green same day). The failures appear in BOTH arms of a fix/no-fix controlled table — including one beat where the #16499 diff provably does not execute — so the instability is ambient and pre-existing, not introduced by that lane.

The observed faces (each = one run's single red):

face beat receipt
uncaught page error showcase (in-window dual-dropzone) pageErrors: ["Cannot read properties of null (reading 'preview')"]
gesture never arms scene 3 convert-while-dragging step receipt {"armed": false, cancellation: {escapeDispatched: true, …}}
target proxy never renders scene 4/5 merge staging .workstation-vessel-dragproxy count 0 after 9s in the target popup
vessel birth never happens scene 5 tear-out page.waitForEvent('popup') 90s timeout (now unmasked into the arming receipt by the scene-4/5 helper assert added on the #16499 branch)

The Problem

Under suite load (sequential app boots, shared e2e server + Neural Link bridge, ~1.1m battery), roughly one drag-class beat per full-suite run fails at gesture infrastructure level — arming, indicator/preview candidacy, cross-window proxy render, or vessel birth. Solo runs of the same tests are reliably green. The film pipeline is unaffected (takes run solo), but suite batteries produce an attribution tax on every lane touching these surfaces: this table cost ~10 suite runs to attribute a single innocent diff.

The Architectural Reality

  • A concrete TOCTOU sits in the dwell verification chain (apps/workstation/view/Workspace.mjs:3986-3995): waitUntil(() => indicators.activeCandidate?.preview?.previewId === …) verifies the candidate, then dwellDelay (600ms default even spec-paced) elapses, then indicators.activeCandidate.preview is read UNGUARDED — a candidate lost during the dwell throws the observed uncaught null (reading 'preview') from inside the executor, killing the gesture chain mid-flight.
  • Losing the active candidate mid-dwell may not be measurement noise. #16497 (closed) fixed a claim-TTL expiry under human-pause dwells (300ms TTL vs 700-900ms film dwells; the trigger's geometric precondition reframe). If residual claim/candidate expiry paths remain reachable under load-stretched refresh cycles, this class is the same user-reachable family surfacing through the executors — classification must split {product claim/candidate expiry | executor TOCTOU | arming-chain race} per face.
  • The armed: false face fires before any preview exists — a distinct upstream seam (src/dashboard/DockTabSortZone arming chain / drag-start delivery under load), possibly sharing a root with the preview faces, possibly not.
  • Suite context = the exact failing shape (banked instrument discipline): solo runs cannot clear or reproduce it; any classification run must be in-suite or replicate its load.

The Fix

Classification first, per face:

  1. Convert the :3995 unguarded read into a structured executor error (re-verify activeCandidate?.preview after the dwell; on loss, fail the step through the receipts channel naming the gate) — this is both a 2-line robustness repair AND the instrument that converts the uncaught-error face into attributable receipts.
  2. With receipts flowing, run a suite battery to census which upstream face(s) remain (arming vs candidacy vs proxy), then classify each against {product expiry family (#16497 cousin) | executor race | load artifact} and repair at the owning seam.
  3. The scene-4/5 staging helper's receipt-unmask (landed with the #16499 PR) is the pattern: every gesture step's receipt asserted BEFORE any long wait that can mask it.

Acceptance Criteria

  • The dwell chain re-verifies the active candidate after dwellDelay and reports loss as a structured step error (no uncaught page error remains reachable from this seam).
  • A suite battery (≥5 full runs) with receipts classifies every remaining face by owning seam, each with a named mechanism or an explicit load-artifact disposition.
  • Product-side findings (claim/candidate expiry class) get their own tickets with #16497 linked; executor-side races are repaired in place with red-proven witnesses where deterministic reproduction exists.
  • The suite battery post-repair shows 0 gesture-infrastructure reds across ≥5 consecutive full runs on the same host class.

Out of Scope

  • The #16499 stable-topology projection fix (shipped separately; its suite table is this ticket's origin evidence, interaction documented in that PR).
  • CI wiring for e2e (there is no CI e2e job; this is a host-battery discipline).

Related

#16497 (closed — the claim-TTL-under-dwell family precedent), #16499 (origin lane + receipt-unmask), #16500 (film-paced presentation family), PR pending on #16499 carries the 10-run table.

Sweeps: live latest-20 checked 2026-08-07 ~09:4xZ (no equivalent); A2A herd window clean (Ada #16488/#16619, Grace #16535 — no overlap); KB semantic sweep recorded degraded (corpus mid-rebuild), not load-bearing.

Origin Session ID: 84d669f4-2271-4d6a-8878-45e8754be6b3

Retrieval Hint: query_raw_memories("ambient gesture arming preview TOCTOU suite load roving red five-beat")

tobiu referenced in commit 03c5598 - "fix(workstation): re-verify the active candidate after the cross-zone dwell (#16700) (#16701) on Aug 8, 2026, 5:03 PM
tobiu unassigned from @neo-kimi-iris on Aug 17, 2026, 2:06 PM