LearnNewsExamplesServices
Frontmatter
id19533
titleA pane dragged into another window parks its vessel at the display's top-left corner for the whole drag
stateClosed
labels
bugaiarchitecturedashboard
assigneesneo-fable
createdAtOct 9, 2026, 11:05 PM
updatedAtOct 10, 2026, 4:23 AM
githubUrlhttps://github.com/neomjs/neo/issues/19533
authorneo-fable
commentsCount21
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 10, 2026, 4:23 AM
milestonev13.2

A pane dragged into another window parks its vessel at the display's top-left corner for the whole drag

Closed v13.2.0/archive-v13-2-0-chunk-24 bugaiarchitecturedashboard
neo-fable
neo-fable commented on Oct 9, 2026, 11:05 PM

Context

The operator, watching the stage display live during tonight's film takes (2026-10-09 ≈21:00Z): "suddenly a 2nd popup spawns and sticks at the top left … we can not release v13.2 with that regression." Then: "we NEVER EVER want additional visible windows (popups). OFF SCREEN or not at all." And on a proposed redesign that would stop re-creating the window: "no half-baked, half-hearted tradeoffs. get it right, or no release."

Measured on the recordings (4096×2304 at 60 fps; the top-left 1000×500 px at 3 fps, 5–15 s), the same on every head of the day — dev 5b69fc1dac (the gating take 19:49Z, the hold-take 20:24Z) and ada/19531-vessel-paint-nudge e437103c5b (20:55Z, 20:59Z):

take s what the display shows
≈6.1 Metrics leaves the main window mid-drag and becomes a window riding the pointer — the hero gesture, correct
≈9.3 Commits leaves the main window toward the first window's dock zones; its conversion vessel is born and jumps to the top-left corner of the display (the work area's availLeft/availTop), showing the Commits strip, CHANGE STREAM, +42
9.3 → 12.7 it sits there for the whole second drag (≈3.4 s) while the pane's proxy rides inside the first window
≈12.7 the drop composes A and B in the first window; the parked vessel closes

What changed, and when (V-B-A on the source history)

  • The far-corner park is #19278 → PR #19289 (Ada, merged 2026-09-27, 9fcc3668d2): NativeVesselTransaction.resolveClearPark — "the corner of the work area whose parked frame overlaps the target's content least, the farthest one among equals" — replaced the target-cover binding of ADR 0029 §2.8.6 (#15396 / #16117): focus the exact target route first → move the source frame onto the target's origin, behind it → refocus; "z-order hides the parked vessel"; a focus refusal leaves the source untouched and moving. The amendment's reason: under a real OS mouse drag focus() raised nothing, so the vessel stayed in front of the target's zones (the operator's recording, #19186).
  • No commit since 09-27 changed the park position. git log on src/dashboard/dock/window, apps/workstation/view/VesselWorkspace.mjs, src/manager/DragCoordinator.mjs: #19325 (shared return/replay), #19351/#19352 (participation; dispose receipt), #19374 (Vega, 10-03: the terminal re-show lands on the frame it was parked from), #19458 (Sophie, merged 10-07 23:50Z: "keep converted popups under the pointer" — the conversion-OUT re-show rect only, one title bar's correction; the park position is untouched). Nothing in 10-08/10-09's dev touches this path (#19514, #19521, #19522 are projection/shell fixes).
  • Why it was "fine" before: in the tour (synthetic pointer, the gate click's fresh activation) the target-cover focus() was admitted, so the parked vessel sat behind the target — invisible. Today's takes are the first film takes since 09-27; the corner park was exercised in every one of them (my 16:03Z read on #15252 called it design, which it is — the design is what is wrong). For a human hand drag, the pre-09-27 binding failed the other way (#19186: the vessel in front of the zones). Neither binding ever satisfied the operator's bar; 13.2 would be the first release carrying either.
  • 13.1.0 (2026-07-03) has no NativeVesselTransaction: the pointer-path cross-window conversion is new 13.2 behavior; the baseline is the pre-#19289 mechanism (Emmy's check).

The Problem

A window that teleports to the far corner during a drag reads as a bug to any viewer; a window that covers the target's drop zones (the pre-09-27 hand-drag case) is the bug the operator filed as #19186. The product rule is now explicit: no additional visible window at any moment of the gesture — the vessel is either invisible or it does not exist — and nothing the user had is lost.

The Architectural Reality (what bounds the shapes)

  • The engine's own contract forbids close-and-reopen (VesselPark.mjs header): "popup acquisition consumes WHATWG transient user activation … A popup→proxy→popup round-trip within ONE continuous gesture therefore cannot count on re-acquisition … Close-and-reopen is a one-way door — the user drags over a target, changes their mind, drags out, and their window is unrecoverable without a fresh gesture. The park contract removes the door." The HTML spec confirms the door has no back: an activation-triggering input event is keydown, mousedown, pointerdown (mouse), pointerup only for non-mouse pointer types, touchend — a mouse release grants nothing, so a window closed on entering the target cannot be re-created on a re-exit nor at the drop. A design that closes the vessel on target entry ships exactly the loss the contract names.
  • Off-screen is clamped: "the macOS/Chrome headed falsifier clamped a requested far-negative position back onto the visible desktop" (ADR §2.8.6); the whole frame stays inside the work area.
  • Behind the target needs a raise: focus() on the target by its owner (the opener-minted route) is admitted under a synthetic/tour drag with fresh activation and refused under a real OS mouse drag (#19186, as recorded — whether it is refused always or only once the pointerdown's transient activation has expired is unmeasured; the recording was a long drag).
  • The native-titlebar path (dragging the vessel WINDOW by its OS title bar onto a target) is unaffected: it parks only after the OS released the drag, with focus granted, behind the target.

Design authority: ADR 0029 §2.8.6; the operator's rule above is the product input; the shape is the dock planners' (Ada with Vega).

The Fix — shapes that meet the bar, each with its falsifier; the ones that do not, named

Decision (the operator, 2026-10-10 ≈00:2xZ, with Emmy's and Mnemosyne's agreement): close on entry, "option B". The pop-up permission is the multi-window application's one-time setup, so the one-way door above does not apply to it: a re-exit opens a fresh vessel, exactly as the return over main always has ("we do exactly that when tear-out and drag back over main app"). One rule for every window of the group: inside a window the drag is that window's tab-header proxy, outside every window it is a vessel, and nothing parks. A site without the permission degrades: the exit fails closed and the drag stays in-window. Keeping the vessel as the drag over another window was the alternative, declined for the one rule. (Added by @neo-opus-ada; the shapes below are kept as the record of what was weighed.)

Meets the bar:

  1. The vessel never leaves the hand; the target's zones are mirrored into it. No park at all: the dragged vessel keeps following the pointer at its grab offset (as it does over empty desktop), and while the pointer claims a target, the target's zone preview is rendered inside the vessel's own window at the translated screen rects (the coordinator already computes the zones from the claim; the vessel is a Neo window with its own Main), clipped to the vessel; the target still renders the uncovered part of its zones. One window, nothing parked, nothing lost, re-exit needs no re-show. Falsifiers: the mirrored zone rects equal the target's within 1 px in a unit arm; a headed real-mouse witness shows coherent zones across both windows and the drop composing; the #19278 e2e arm is rewritten to the new contract.
  2. Target-cover restored, with the raise made to work for hand drags. Park behind the target (the pre-09-27 chain) and establish, by measurement on real chrome under a real OS drag, whether the owner's focus() on the target is admitted within the pointerdown's transient activation (a hand drag of a few seconds). If it is, the chain holds for the common case and the ADR records the activation bound; if focus() is refused regardless (the #19186 reading), this shape is dead and only shape 1 remains. Falsifier: the real-mouse measurement itself (a short drag and a long drag; the park receipt's focused).

Does not meet the bar (do not implement):

  • Close the vessel on target entry ("merge into the target's tab proxy, not at all") — the one-way door above: a re-exit onto the desktop loses the window, and the drop cannot re-create it (no activation on a mouse release). The operator's words apply. (Superseded by the decision above: with the pop-up permission, this is the chosen shape.)
  • Park at the far corner (today), park adjacent, park as a strip — visible extra windows, all three.

Release fallback if neither shape lands in the 13.2 window: the pointer path does not propose conversion-in over a target at all — the vessel keeps following the hand across other windows like any OS window; the user drops it where it is and composes by the native-titlebar drag (unaffected). No park, no loss, no new window; the cross-window pointer compose returns with shape 1. The operator decides between this and the delay.

Acceptance Criteria

  • During a pointer-path cross-window drag no window other than the dragged vessel and the existing windows is ever visible (a recorded headed take of the film tour at the fix head: the display's top-left corner and every work-area corner stay black through the second pane's drag; the vessel-region strip as the receipt).
  • A re-exit onto empty desktop after a target claim opens a fresh vessel under the pointer in the same gesture, and a release there detaches the item into it; without the pop-up permission the exit fails closed and the drag stays in-window. (Amended 2026-10-10 for the decision; was: the same OS window re-shown.)
  • The target's drop zones are reachable and visible to the hand while the pointer claims the target, with nothing covering them because the vessel retired on the claim (the foreign-popup arms of WorkstationHumanPopupOverlapNL; a real OS mouse drag on the operator's display as post-merge validation). (Amended 2026-10-10 for the decision.)
  • ADR 0029 §2.8.6 is amended to the chosen shape with the operator's rule as its first sentence.

Contract Ledger (applied by the author, 2026-10-10 02:5xZ — PR #19539 RA-2)

Bounded changes to consumer-facing contracts; no new API. The park-era surfaces that remain (VesselConversion, VesselPark, the host park seams, resolveClearPark, parkedItemId in the retired matrix) are dormant and owned by #19538.

Surface Before After Consumers
Neo.dashboard.dock.interaction.TabSortZone#resolveRemoteDragTransition (opt-in via enableVesselConversion) ({draggedItem, logicalSourceRect, now, pointerInTarget, replayAfterTransition, targetId, targetRect}) → {commitEligible, engage, preview?, retain, proxyRect?} or null; the size-pair sensor proposed conversion, the park admitted it, convert-out re-showed the same window ({draggedItem, pointerInTarget}) → on a claimed frame {commitEligible: true, engage: true, proxyRect, retain: false}; null for a claim-free frame or a source that did not opt in. On the first claimed frame a vessel riding the hand retires through dragBoundaryEntry (the re-entry contract: zero model mutation, the pane home). checkWindowBoundary treats a claimed frame as no boundary crossing and re-arms the sampler as inside, so leaving the claiming window for the desktop is an ordinary exit → openVessel (a fresh generation; fails closed without the site's pop-up permission, the drag staying in-window). An exit while the previous generation's retirement or admission is still pending waits for it, and stands down once the drag is back inside a window (DockTearOut.spec › "an exit while the previous admission is pending…"). DragCoordinator (caller), projection/LayoutAdapter (threads the opt-in), apps/workstation/view/VesselWorkspace, examples/dashboard/crossWindow/DemoBWorkspace, DockTabSortZone.spec, DockTearOut.spec
apps/workstation/view/CrossWindowGestureSnapshot#readCrossWindowGestureSnapshot ({nativeWindowId, parkedItemId, sourceZone, sourceZoneId, targetWorkspaceId}) → snapshot with converted, parkedItemId, parkReceipt; with parkedItemId readiness required a parked, connected source vessel and targetProxy.sourceWindowId === sourceVesselWindowId ({draggedItemId, nativeWindowId, sourceZone, sourceZoneId, targetWorkspaceId}) → snapshot without converted / parkedItemId; with draggedItemId readiness requires no connected source vessel, the item's header proxy in the target (header, settled, visible, targetWindowId === target.windowId) and ≥ 5 visible indicator candidates apps/workstation/tour/NativeGestureDriver (the film runner), WorkstationFiveBeatNL, WorkstationNativePopupOverPopupNL, WorkstationHumanPopupOverlapNL, GestureDriver.spec, the film take runner
DemoBWorkspace#executeCrossWindowStep(step, options) (demo harness) {cancelAtTarget, parkObservationMs, roundTrip}; round trip = park → same-vessel re-show → detach; commit proof vesselMountDelta === 1, mountDelta === 2 {cancelAtTarget, roundTrip, viaDesktop = roundTrip}; a desktop leg births a vessel, the claim retires it (readCrossWindowClaimSettlement: vessel null, slot clear, pane home), round trip = a fresh generation on leaving → detach; commit proof keyed on vesselBorn (direct: mountDelta 1; via desktop: 3) DemoBCrossWindowDragNL, DemoBPerspectivesNL (through the tour), DemoBWorkspace.spec; DemoBVesselConversionNL deleted with its matrix row

Surviving acceptance after merge (L4, the operator's display; recording hold until #19539 lands): AC-1's recorded headed take and AC-3's real-mouse drag are owned by the film epic #15252 (its first take at merged dev is AC-1's receipt; the operator's hand drag is that take's precondition) and gated for the release on #14800. Nothing else of this ticket stays open after the merge.

Out of Scope

The compose paint gap (#16498 / #19531); the vessel's size at birth (#19450); the hero tear-out, which is correct; the native-titlebar path.

Related

#19278 / PR #19289 (the corner park), #15396 / #16117 (the target-cover binding), #19186 (the operator's recording), #19372 / #19374 / #19373 / #19458 (the park's restore and re-show rects), ADR 0029 §2.8.6, #15252 (the film), #14800 (the v13.2 cut list), #19538 (retiring the dormant pointer-path conversion after this), #19537 (explaining a refused popup).

handoff: @neo-opus-ada (the design's author) with @neo-opus-vega — the operator's rule is the input, the shape is theirs; the film's next take waits on it.

Live latest-open sweep: checked the latest 20 open issues at 2026-10-09T21:03Z; no equivalent (nothing names the park). Tracker search "park vessel conversion" open: none; #19278, #19372, #19374 closed. A2A claim sweep: no lane-claim on the park before this ticket; Ada's claim at 21:19Z and her withdrawal at 21:22Z are on this ticket's thread. MC sweep: my 16:03Z read on #15252 is the prior art; no prior decision to reopen the park's position.

Origin Session ID: 882aedde-7578-4231-9183-8160f948db6a Retrieval Hint: "converting vessel parks at the display's top-left corner during a cross-window drag resolveClearPark farthest corner 13.2 target-cover one-way door"

tobiu referenced in commit 5698517 - "fix(dock): a drag shows only the windows the user owns: a claimed window carries it, leaving reopens the vessel (#19533) (#19539) on Oct 10, 2026, 4:23 AM
tobiu closed this issue on Oct 10, 2026, 4:23 AM