LearnNewsExamplesServices
Frontmatter
id19543
titleFilm journey scene: one drag crosses every window boundary
stateClosed
labels
enhancementaitestingdashboard
assigneesneo-fable
createdAtOct 10, 2026, 2:59 PM
updatedAtOct 10, 2026, 4:11 PM
githubUrlhttps://github.com/neomjs/neo/issues/19543
authorneo-fable
commentsCount0
parentIssue15252
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 10, 2026, 4:11 PM

Film journey scene: one drag crosses every window boundary

Closed v13.2.0/archive-v13-2-0-chunk-24 enhancementaitestingdashboard
neo-fable
neo-fable commented on Oct 10, 2026, 2:59 PM

Parent: #15252 (the film epic; design record A3-M-06 6091324649 + the dialogue fold A3-M-06a 6091334597). Not blocked: #19533's fix landed on dev at 5698517f19 (PR #19539).

Context

The operator's challenge on the film (2026-10-10 01:1xZ): the screenplay never shows the gesture's freedom. film-tear-out, film-morph, film-second-window and film-reintegration are four scenes of one hop each; the thing the engine does best — one drag that crosses every boundary as often as the hand likes while the pane keeps living — is never on screen. The journey scene is designed on the epic. Its hops 4–5 are #19533's B shape, shipped by PR #19539: inside a window of the group the drag is that window's tab-header proxy, outside every window it is a vessel; a claim retires the vessel riding the hand, leaving re-opens one (ADR 0029 §2.8.6). This ticket builds the runnable cue; the recorded take is the epic's AC-1 step (6092305993).

Live latest-open sweep: the latest 20 open issues at 12:57Z, no equivalent (#19537, #19538, #19540, #19541 are the dock cleanups; none touches the screenplay). A2A claim sweep: my own [lane-claim] of 12:51Z is the only claim on the film's cue. Memory sweep: the A3-M-06 design turn (session d6e132f0-fc2a-4d90-a3b5-5046668076e1); no earlier journey cue. Own-assignment sweep: #15252 (the parent) and #19382 (unrelated).

The Problem

apps/workstation/tour/fiveBeatFilm.mjs is the narrative authority the in-app Start film tour, the whitebox replay and the recorded take all consume. Its window scenes are single hops: scene 3 film-second-window (the convert-while-dragging cue: Commits out → into Metrics' window → drop) and scene 7 film-morph (a tear-out cue with reenter: true: Metrics out → back → cancel). No cue walks the pointer through main, the desktop and a foreign window under one pointer-down, so the picture cannot show B.

The Architectural Reality

  • Screenplay: fiveBeatFilm.mjs — ten scenes summing to 97 s inside the 90–150 s envelope; filmCueTypes is the exact cue set the film uses; film-second-window (lines 162–187), film-morph (256–288).
  • Cue vocabulary and dispatch: apps/workstation/tour/cueVocabulary.mjs (WORKSTATION_CUE_TYPES); apps/workstation/view/TourController.mjs#executeCue has one case per type, unknown → false.
  • Executors: apps/workstation/tour/NativeGestureDriver.mjs — executeTearOutStep (arm, the progressive boundary exit, waitForTearOutVessel, the born hold, the reenter walk back to a point 35 % into the boundary rect, waitForTearOutVesselRetired) and executeCrossWindowDockStep (the client point frozen outside the boundary while the screen point travels, readCrossWindowGestureSnapshot(...).ready as the pre-release gate, waitForCrossWindowTransfer). The pointer is synthetic (simulateEvent with client and screen coordinates); the engine's claim geometry reads the screen point, so "desktop" is a screen point outside every window of the group (Demo B's driveCrossWindowDesktopLeg uses "below the source viewport" for the same reason).
  • Readiness contract: apps/workstation/view/CrossWindowGestureSnapshot.mjs#readCrossWindowGestureSnapshot — with draggedItemId, ready requires the vessel gone (!sourceVesselConnected) and the target's proxy settled and visible in that window.
  • Witnesses: test/playwright/unit/apps/workstation/tour/fiveBeatFilm.spec.mjs pins the scene list, the 97 s sum, births = 3, gates = 3, the reenter flags [false, true] and one born hold; test/playwright/e2e/workstation/WorkstationFilmTourNL.spec.mjs pins totalBeats, three continued gates, ≥ 3 popups born, the convert-while-dragging and re-entry receipts. apps/workstation/README.md:59 still says "eight scenes".

The Fix

  1. A journey cue — {type: 'journey', itemId: 'commits', sourceNodeId: 'right-bottom-tabs', targetItemId: 'metrics', hops: ['desktop', 'main', 'desktop', 'target', 'desktop', 'target'], options: {...filmPace, birthDwellMs: 1500, dwellDelay: 1000}} — added to WORKSTATION_CUE_TYPES, dispatched by TourController#executeCue, executed by NativeGestureDriver#executeJourneyStep. Hops are data. desktop: a screen point outside every window rect of the group (computed from the Window manager, never a fixed offset); a fresh vessel must be born (waitForTearOutVessel, a window id different from the previous generation), then the born hold. main: the 35 % interior point; the vessel retires (dockTearOutEntry seen + waitForTearOutVesselRetired) and the committed document is byte-identical to the one before the gesture. target: the target vessel's centre in screen space until the snapshot is ready (vessel retired, the proxy in that window), then the dwell. The last hop is the drop: mouseup → waitForCrossWindowTransfer → the A+B adoption ([metrics, commits]), settled as executeCrossWindowDockStep settles it. Receipt: {applied, errors, hops: [{kind, born|retired|claimed, windowId, …}], proof: {vesselWindowIds, documentsUnchangedAfterReturn, identityPreserved, sourceDocument, targetDocument, transfer}}. A failed hop cancels the gesture (cancelTearOutGesture) and names itself in errors.
  2. The screenplay: film-second-window → film-journey (the journey cue behind its gate, the captions of A3-M-06, targetSeconds 18); film-morph retired — its byte-identity pin is the journey's main hop. Nine scenes; the sum re-pinned (91 s, inside the band); the header's show-order prose and filmCueTypes follow (convert-while-dragging leaves the film's set; its executor stays for the five-beat witness).
  3. Witnesses re-pinned: unit (scene list, sum, births = 2, gates = 2, reenter [false], the hold on the journey); e2e (filmCues, two gates, ≥ 4 popups born and all closed by the signature, the journey receipt's hops and three distinct vessel ids replacing the convert and reentry blocks). README: nine scenes.

Contract Ledger

Target surface Source of authority Proposed behaviour Fallback Docs Evidence
journey cue (WORKSTATION_CUE_TYPES, TourController#executeCue) ADR 0029 §2.8.6; #15252 A3-M-06 walks hops under one pointer-down; the last target hop drops a failed hop cancels and names itself in errors; the document stays unchanged the screenplay header + the cue's JSDoc unit + e2e film witnesses
NativeGestureDriver#executeJourneyStep same The Fix 1 same JSDoc WorkstationFilmTourNL receipt pins
fiveBeatFilm.mjs scene list #15252 A3-M-06 / A3-M-06a film-journey replaces film-second-window and film-morph — header prose fiveBeatFilm.spec.mjs

Decision Record impact: aligned-with ADR 0029 §2.8.6; no amendment.

Acceptance Criteria

  • AC-1 fiveBeatFilm.mjs has nine scenes; film-journey sits where film-second-window was; film-morph is gone; the pacing sum is re-pinned inside the envelope; filmCueTypes names journey and no longer convert-while-dragging.
  • AC-2 executeJourneyStep walks the six hops under one pointer-down; its receipt records three distinct vessel window ids, the retirement at the main hop with the committed document byte-identical, the two target claims with the proxy inside Metrics' window, the final A+B adoption, and the same live pane across every hop.
  • AC-3 WorkstationFilmTourNL.spec.mjs green headless in both arms (viewer gates and autoGates): two gates, ≥ 4 windows born and all closed by the signature, the journey receipt pinned.
  • AC-4 fiveBeatFilm.spec.mjs green; the document tier still runs twice with identical logs.
  • AC-5 executeCrossWindowDockStep and the five-beat witness's scene 3 are untouched.
  • AC-6 The README's scene count and the screenplay header prose match the new order.
  • Post-merge (the epic's, not this ticket's): the first headed take at this head after the operator's real-mouse check (#15252 AC-1).

Out of Scope

The recorded take and Emmy's clips (#15252); the dialogue text (lives on the epic); the interactive tour's popup-permission prologue and the refused-open explanation (#19537, Emmy's); the dense tour; any engine change (#19538 / #19541 are Ada's deletions; nothing here depends on them).

Avoided Traps

  • A second copy of the tear-out executor: the hops reuse the existing waits (waitForTearOutVessel, waitForTearOutVesselRetired, readCrossWindowGestureSnapshot, waitForCrossWindowTransfer, cancelTearOutGesture); the executor is a hop walker over them.
  • Driving the hops from the e2e with page.mouse (as WorkstationHumanPopupOverlapNL does for B's acceptance arm): the film plays from the app's own button, so the cue drives itself and the e2e witnesses the receipt.
  • Keeping film-morph beside the journey: the journey's second hop is the morph; two scenes would show one hop twice.
  • "Desktop" as a fixed offset past main's boundary corner: after scene 2, Metrics' committed vessel sits there.

Related

#15252 (parent) · #19533 / PR #19539 (B) · #19542 (Ada's deletion, independent) · #16498 (the discriminator rides the take, not this cue) · #19537 (Emmy).

Origin Session ID: 424b0f57-6941-4f77-9b2a-4d083b50cecf Retrieval Hint: "film journey cue executeJourneyStep hops desktop main target"

tobiu referenced in commit f3ec47b - "feat(workstation): the film's journey scene walks one drag across every window boundary (#19543) (#19546) on Oct 10, 2026, 4:11 PM
tobiu closed this issue on Oct 10, 2026, 4:11 PM