Context
The Workstation film tour (WorkstationFilmTourNL, both arms) has been quarantined since 2026-10-12 as "hosted only: the tour stops at journey hop 3 because no fresh vessel is born" (accountable: me). A read-only diagnosis of the hop-level [film-probe] logs (runs 38258413156, 38260376912, 38271163182, 38276837825, 38291757581; 12 arm attempts) found two failure modes. This ticket is mode A (5 arms, 4 of them autoGates):
journey hop 3 (desktop): no fresh vessel was born — isWindowDragging=false reattachArmed=true lastRatio=0 vesselOpen={…"stage":"granted"} connects=false … activeVessel=false. No popup is created for the hop at all.
Every leg between main and the desktop point crosses Metrics' window. That window claims the drag, the vessel retires, and leaving reopens it, so a journey births 6 popups, 3 of them short-lived. In all 5 mode-A arms, hop 1's reopened vessel closed 0.41–0.47 s after creation. Every arm that closed it within 0.38 s went on to birth hop 3's vessel.
The Problem (inferred, ~60–70 %)
acquire returns null at reserve (src/manager/transaction/NativeLifecycle.mjs ~197–198), which refuses a slot with a live binder (src/manager/Transaction.mjs ~852). Every generation uses the same per-item key (apps/workstation/view/VesselWorkspace.mjs ~58–68). The binder can stay live past the window's death:
App#registerApp binds the slot before it sends registerAppName (src/worker/App.mjs ~897–898);
DomEvents#onBeforeUnload sends disconnect only for Manager.appNames (src/main/DomEvents.mjs ~485–486).
A popup closed between those two steps never disconnects, and nothing retries: the exit fires only while the pointer is moving out (src/draggable/container/SortZone.mjs ~388–400). For a user, a vessel closed quickly can leave that item unable to tear out again in the session.
The Fix
- First, confirm. Add the key's binding
windowId and its port liveness to the gesture driver's diag() (apps/workstation/tour/NativeGestureDriver.mjs ~1414), and run hosted once with reporter output kept, or locally under 6× CPU throttling. A null binding at failure falsifies this cause.
DomEvents#onBeforeUnload: when appNames is empty, send a window-scoped disconnect that worker/Base#onDisconnect (~559) accepts.
App#registerApp: skip Transaction.admit when the window's port is already gone (importApp is async, so registration can follow the disconnect).
Acceptance Criteria
Out of Scope
Mode B (hop 4 target never settles; the viewer arm) is a separate ticket.
Related
Parent #19655.
Sweeps at 11:00Z: live latest-20 open issues, A2A claims (none).
Origin Session ID: 1cc54e4a-b230-43bc-ac83-7519d425f6e7
Context
The Workstation film tour (
WorkstationFilmTourNL, both arms) has been quarantined since 2026-10-12 as "hosted only: the tour stops at journey hop 3 because no fresh vessel is born" (accountable: me). A read-only diagnosis of the hop-level[film-probe]logs (runs38258413156,38260376912,38271163182,38276837825,38291757581; 12 arm attempts) found two failure modes. This ticket is mode A (5 arms, 4 of them autoGates):journey hop 3 (desktop): no fresh vessel was born — isWindowDragging=false reattachArmed=true lastRatio=0 vesselOpen={…"stage":"granted"} connects=false … activeVessel=false. No popup is created for the hop at all.Every leg between main and the desktop point crosses Metrics' window. That window claims the drag, the vessel retires, and leaving reopens it, so a journey births 6 popups, 3 of them short-lived. In all 5 mode-A arms, hop 1's reopened vessel closed 0.41–0.47 s after creation. Every arm that closed it within 0.38 s went on to birth hop 3's vessel.
The Problem (inferred, ~60–70 %)
acquirereturns null atreserve(src/manager/transaction/NativeLifecycle.mjs~197–198), which refuses a slot with a live binder (src/manager/Transaction.mjs~852). Every generation uses the same per-item key (apps/workstation/view/VesselWorkspace.mjs~58–68). The binder can stay live past the window's death:App#registerAppbinds the slot before it sendsregisterAppName(src/worker/App.mjs~897–898);DomEvents#onBeforeUnloadsendsdisconnectonly forManager.appNames(src/main/DomEvents.mjs~485–486).A popup closed between those two steps never disconnects, and nothing retries: the exit fires only while the pointer is moving out (
src/draggable/container/SortZone.mjs~388–400). For a user, a vessel closed quickly can leave that item unable to tear out again in the session.The Fix
windowIdand its port liveness to the gesture driver'sdiag()(apps/workstation/tour/NativeGestureDriver.mjs~1414), and run hosted once with reporter output kept, or locally under 6× CPU throttling. A null binding at failure falsifies this cause.DomEvents#onBeforeUnload: whenappNamesis empty, send a window-scopeddisconnectthatworker/Base#onDisconnect(~559) accepts.App#registerApp: skipTransaction.admitwhen the window's port is already gone (importAppis async, so registration can follow the disconnect).Acceptance Criteria
registerAppandregisterAppNameleaves its slot free: a unit or e2e arm, red before and green after.binder=null themeFileLoads=0, a third cause, and timed out its shard; the film arms stay quarantined until #19919 lands.Out of Scope
Mode B (hop 4 target never settles; the viewer arm) is a separate ticket.
Related
Parent #19655.
Sweeps at 11:00Z: live latest-20 open issues, A2A claims (none).
Origin Session ID: 1cc54e4a-b230-43bc-ac83-7519d425f6e7