LearnNewsExamplesServices
Frontmatter
id15915
titleWindow-drag re-entry false-fires across the proxy-identity swap
stateClosed
labels
bugaicore
assigneesneo-fable
createdAtJul 25, 2026, 5:35 PM
updatedAtJul 25, 2026, 6:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/15915
authorneo-fable
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 25, 2026, 6:15 PM

Window-drag re-entry false-fires across the proxy-identity swap

neo-fable
neo-fable commented on Jul 25, 2026, 5:35 PM

Context

Third engine defect surfaced by the five-beat film lane (#15252#15912), sibling to #15895 (entry ratio unreachable under proxy-area normalization) and #15899 (entry block dereferences a placeholder that dock strips don't have). Under the film-take launch profile + film gesture pacing, the tear-out vessel was intermittently "never born" (exitFired=true, connect never lands, a 10s birth gate does not recover it). A 14-cell bisect matrix (2026-07-25, receipts on #15912) eliminated launch args, GPU flags, video recorder, boot screenshots, window fronting, bundle identity (Chrome vs bundled Chromium), popup position, and path curvature — and pinned the mechanism with an in-executor sentinel:

preBirthBoundaryEntries=1 preBirthEntries=1   ← on every red run

A false dragBoundaryEntry/dockTearOutEntry fires after the boundary exit, retiring the newborn vessel before its window ever connects. The vessel's navigation never commits because the window is closed mid-boot: worker-truth reads "absence".

The Problem

The gesture's move stream changes proxy identity mid-flight. Before the vessel grant, drag:move payloads carry the in-window DOM proxy's rect; once the async grant lands, Neo.main.addon.DragDrop#onDragMove switches the payload to the FUTURE-VESSEL dims at pointer-minus-offset (src/main/addon/DragDrop.mjs:391). Neo.draggable.container.SortZone#checkWindowBoundary compares each sample's intersection ratio against lastIntersectionRatioacross that discontinuity:

  1. The small pre-grant proxy legitimately EARNS re-entry arming on its way out (its ratio drops below reattachThreshold — the Schmitt-trigger doing its job in the OLD scale).
  2. The first post-grant sample carries a 320×240 proxy whose min-area coverage over a 314×49 strip jumps to ≈0.67–1.0 at mid-path positions.
  3. reattachArmed && isMovingIn && intersectionRatio > reattachThreshold — all three true in a single sample, manufactured entirely by the geometry swap. Entry fires; the tear-out handlers retire a vessel that has not connected yet.

Why it's timing-dependent (the film found it, defaults don't): the false entry needs a post-swap move sample. Spec-default pacing (4 samples × 16ms = 64ms) completes the whole outward path before the async grant lands — no post-swap samples exist. Film pacing (24 × 33ms ≈ 0.8s) guarantees several. Same race, other direction, explains why E2E launch args masked it: with --disable-frame-rate-limit the vessel connects fast enough that the early retirement reads as a legal post-connect morph; under real vsync (film profile) the connect is slow and loses — stillbirth. Matrix cells: film-pace/film-args = red ×9, default-pace/film-args = green, 4-steps/film-pace-otherwise = green, curve=0/24-steps = red (curvature exonerated; sample count is the trigger dimension).

A real user is exposed: a slow deliberate tear-out drag (large pane, big vessel dims) with the grant landing mid-gesture is exactly this shape — no film required.

The Architectural Reality

  • src/draggable/container/SortZone.mjs:282 checkWindowBoundary — single seam, no subclass overrides. Exit branch seeds arming at :318 (reattachArmed = coverageRatio < reattachThreshold); window-drag branch re-arms at :334-336 and fires entry at :338. lastIntersectionRatio advances at :308 with no notion of which proxy produced the previous value.
  • src/draggable/container/SortZone.mjs:205-216 — the reattachArmed Schmitt-trigger JSDoc: "Re-entry must be EARNED: leave first, then return." The defense is sound for one continuous signal; the swap splices two signals into one comparator, so arming earned in the small-proxy scale discharges in the vessel scale.
  • src/main/addon/DragDrop.mjs:391 (window-drag: popupWidth/popupHeight proxy) vs :443-444 (pre-grant: DOM proxy getBoundingClientRect) — the two proxy identities. The swap itself is legitimate; the addon is not at fault.
  • apps/workstation/view/Workspace.mjs executeTearOutStep — carries the pre-birth entry sentinels (preBirthBoundaryEntries/preBirthEntries in the birth-failure diag, added on the #15912 branch) that made the mechanism observable from worker truth.
  • Retiring an unconnected vessel is a designed path (tearOutRetirements admission check, openTearOutVessel). The defect is exclusively the FALSE entry.

The Fix

In checkWindowBoundary's window-drag branch: track the proxy's dims per sample; a dims change is a geometry reseed, not a movement. On the swap sample:

  • update the stored dims,
  • re-earn arming in the new scale (reattachArmed = intersectionRatio < reattachThreshold),
  • skip entry evaluation for that sample (the baseline at :308 has already advanced, so the next sample compares new-scale vs new-scale).

Seed the stored dims at the exit transition (:311-327) so the first window-drag sample after the addon-side swap is detected. Reset alongside reattachArmed in the cancel/end cleanup. ~10 lines, single class, no addon change, no threshold change. Same-scale gestures are byte-identical (dims never change → reseed never triggers).

Acceptance Criteria

  • Unit (RED→GREEN): a checkWindowBoundary sample stream with a mid-stream proxy-dims swap while isWindowDragging — arming earned pre-swap — must NOT fire dragBoundaryEntry on or after the swap sample until re-entry is re-earned in the new scale; a genuine post-swap return (below threshold, then rising across it) fires exactly one entry.
  • Existing draggable / dashboard / dock unit suites stay green (same-scale gestures unaffected).
  • Empirical, at the film grain: WorkstationFiveBeatNL scene-2 BOTH legs green under the film profile with full film pacing (curve 0.18 / delay 33 / steps 24), headed, two consecutive runs — the previously-red matrix cell flipped by this fix alone (all bisect knobs off).
  • The executor diag's preBirthEntries reads 0 in those green runs.

Out of Scope

  • The film-take launch profile, spec bisect knobs, and birth-gate/rpc-ceiling interplay — #15912 (mine, open).
  • The re-entry window-membership semantic fork (getWindowAt vs strip coverage) — successor design question recorded on #15895 (issuecomment-5078352936), D-013 territory.
  • Any change to WHEN the addon swaps proxy identity — the swap is correct; the comparator must survive it.

Avoided Traps

  • Connect-gating retirement (no retirement before vessel connect) — rejected: out-and-back faster than a popup boot is a legal gesture; unconnected retirement must stay possible. Only the FALSE trigger is the defect.
  • Full-clear hysteresis (require ratio ≈ 0 before arming) — rejected as primary: changes legitimate same-scale semantics for slow exits; the identity-reseed fixes the actual broken assumption without touching thresholds.
  • Debouncing/time-window suppression — rejected: timing heuristics re-introduce race dependence; the discontinuity is detectable exactly, so detect it exactly.

Decision Record impact

none (aligned with the shipped min-area normalization intent of #15895/PR #15897; extends its scale-awareness to the arming state machine).

Related

#15895, PR #15897, #15899, PR #15901 (the two sibling defects on this seam, both film-found), #15912 (film profile + matrix receipts), #15252 / PR #15840 (the film lane), #15906 (stage B, consumes the same seam next).

Live latest-open sweep: checked latest 20 open issues at 2026-07-25T15:31Z; no equivalent found. A2A in-flight claim sweep: last-hour window clean (nearest activity: #15908/#15913/#15914, disjoint scopes).

Origin Session ID: 8e3ca9dd-427d-4c93-9054-edd660fda27b

Retrieval Hint: "proxy-identity swap false re-entry vessel stillbirth film pacing bisect matrix"