Context
Live operator QA on 2026-07-29 reproduced a one-gesture failure: drag a Workstation tab out until a real popup is created, keep the pointer down, move back into the main window, and continue moving. The popup visibly converts back to an in-app proxy, but that proxy freezes instead of following the still-active drag.
This is a new temporal-motion successor to #15895 / PR #15897 (re-entry reachability) and #15915 / PR #15917 (proxy-identity reseed). Both predecessors remain closed: the current gesture now reaches the re-entry transition, then fails after it.
The Problem
The Workstation DockTearOut entry path restores only the worker-side sort-zone state:
onDockTearOutEntry() calls sortZone.endWindowDrag();
DockTabSortZone#endWindowDrag() makes the DOM proxy visible and sets sortZone.isWindowDragging = false;
- the vessel is then retired with zero model mutation.
The main-thread Neo.main.addon.DragDrop owns a separate isWindowDragging flag. This entry path does not clear it. On the next pointer move, the addon therefore remains in its native-window branch, attempts to move the retired popup, sends the window-sized payload, and returns before the DOM-proxy movement branch. The visible proxy has resumed in the worker but the main thread still believes the gesture is embodied as an OS window.
The generic dashboard Container#onDragBoundaryEntry() already demonstrates the missing symmetry by clearing both the sort-zone flag and the main-addon config. The Workstation composition lacks an equivalent end-to-end transition.
Existing morph receipts prove vessel birth, re-entry, popup retirement, unchanged document, same pane identity, and heartbeat continuity. They do not move the pointer to two positions after the morph and compare proxy rectangles, so the freeze is invisible to them.
The Architectural Reality
One continuous gesture crosses two threads and two embodiments. Re-entry is complete only when worker sort state, main-thread movement mode, proxy identity, and vessel lifecycle settle to the same generation. Making the proxy visible is not enough.
This ticket owns source-window re-entry after a tear-out. It is distinct from popup-over-popup target conversion (#16117) and from dragging a previously committed popup by its native title bar.
The Fix
- Add a real-pointer headed regression that tears out, re-enters the source main window, then moves through at least two additional positions before release.
- Make the entry transition atomically end native-window movement in the main addon and resume the existing DOM proxy for the same drag generation.
- Preserve the exact source pointer offset so the proxy resumes under the live pointer without a jump or reacquisition.
- Retire the popup exact-once while keeping the same live pane/store instance and zero model mutation until the eventual drop.
- Pin cancel, re-exit, ordinary in-window drop, and stale async native-move settlement.
Contract Ledger
| Surface |
Authority |
Required behavior |
Failure fallback |
Evidence |
| Worker sort zone |
DockTabSortZone |
isWindowDragging=false, proxy visible, base sort resumes |
Preserve the last valid embodiment |
Worker state + proxy identity |
| Main movement mode |
Neo.main.addon.DragDrop |
Leaves native-window branch for the same generation before the next move |
Fail closed without moving a retired popup |
Addon state/generation + move-route receipt |
| Native vessel |
DockTearOut lifecycle |
Retires exact-once after re-entry with zero document mutation |
Same vessel remains recoverable until disposition settles |
Window identity/topology receipt |
| Resumed proxy |
Existing body-mounted drag proxy |
Follows every subsequent pointer move with the preserved offset |
No frozen or reacquired proxy |
Two-plus post-entry rect samples bound to pointer samples |
| Live pane |
Worker-owned component/store |
Same instance and heartbeat throughout |
No clone/recreate |
Identity + liveness receipt |
Acceptance Criteria
Out of Scope
Re-entry threshold geometry already resolved by #15895 · proxy-identity reseed already resolved by #15915 · popup-over-popup target conversion (#16117) · native-titlebar drag of an already-committed popup · proxy visual skin (#16120).
Avoided Traps
- Do not reopen #15895 or #15915.
- Do not add synthetic jitter or a second pointer event solely to wake a frozen state.
- Do not recreate the proxy/pane; resume the existing gesture embodiment.
- Do not clear only the worker flag; the bug is split-brain movement ownership.
- Do not prove only that the popup closed or proxy appeared—continued motion is the contract.
Decision Record impact
aligned-with ADR 0029's DETACHED_MOVING → in-window nonterminal transition and park/re-show lifecycle; no amendment expected.
Related
Successor to #15895 / PR #15897 and #15915 / PR #15917 · #15396 / PR #15573 park lifecycle · #15906 / PR #16035 Workstation composition · parent #15239 · QT-parity epic #13158.
Freshness evidence: live all-state searches for re-entry/freeze/morph/tear-out; exact predecessor bodies and merged paths; current DockTearOut, DockTabSortZone, main DragDrop, generic Container precedent, and current e2e assertion census; latest 20 open issues and latest 30 all-state A2A messages checked immediately before creation on 2026-07-29. No equivalent open defect or competing claim found.
Retrieval Hint: Workstation tear out reenter main same gesture proxy visible freezes main addon isWindowDragging
Context
Live operator QA on 2026-07-29 reproduced a one-gesture failure: drag a Workstation tab out until a real popup is created, keep the pointer down, move back into the main window, and continue moving. The popup visibly converts back to an in-app proxy, but that proxy freezes instead of following the still-active drag.
This is a new temporal-motion successor to #15895 / PR #15897 (re-entry reachability) and #15915 / PR #15917 (proxy-identity reseed). Both predecessors remain closed: the current gesture now reaches the re-entry transition, then fails after it.
The Problem
The Workstation
DockTearOutentry path restores only the worker-side sort-zone state:onDockTearOutEntry()callssortZone.endWindowDrag();DockTabSortZone#endWindowDrag()makes the DOM proxy visible and setssortZone.isWindowDragging = false;The main-thread
Neo.main.addon.DragDropowns a separateisWindowDraggingflag. This entry path does not clear it. On the next pointer move, the addon therefore remains in its native-window branch, attempts to move the retired popup, sends the window-sized payload, and returns before the DOM-proxy movement branch. The visible proxy has resumed in the worker but the main thread still believes the gesture is embodied as an OS window.The generic dashboard
Container#onDragBoundaryEntry()already demonstrates the missing symmetry by clearing both the sort-zone flag and the main-addon config. The Workstation composition lacks an equivalent end-to-end transition.Existing morph receipts prove vessel birth, re-entry, popup retirement, unchanged document, same pane identity, and heartbeat continuity. They do not move the pointer to two positions after the morph and compare proxy rectangles, so the freeze is invisible to them.
The Architectural Reality
One continuous gesture crosses two threads and two embodiments. Re-entry is complete only when worker sort state, main-thread movement mode, proxy identity, and vessel lifecycle settle to the same generation. Making the proxy visible is not enough.
This ticket owns source-window re-entry after a tear-out. It is distinct from popup-over-popup target conversion (#16117) and from dragging a previously committed popup by its native title bar.
The Fix
Contract Ledger
DockTabSortZoneisWindowDragging=false, proxy visible, base sort resumesNeo.main.addon.DragDropDockTearOutlifecycleAcceptance Criteria
devheaded real-pointer witness reproduces: popup retires and proxy becomes visible, but two later pointer positions do not produce corresponding proxy movement.sortZone.isWindowDraggingand main-addonisWindowDraggingtransition out of native mode for the same gesture generation before the first post-entry move is processed.Out of Scope
Re-entry threshold geometry already resolved by #15895 · proxy-identity reseed already resolved by #15915 · popup-over-popup target conversion (#16117) · native-titlebar drag of an already-committed popup · proxy visual skin (#16120).
Avoided Traps
Decision Record impact
aligned-with ADR 0029's
DETACHED_MOVING → in-windownonterminal transition and park/re-show lifecycle; no amendment expected.Related
Successor to #15895 / PR #15897 and #15915 / PR #15917 · #15396 / PR #15573 park lifecycle · #15906 / PR #16035 Workstation composition · parent #15239 · QT-parity epic #13158.
Freshness evidence: live all-state searches for re-entry/freeze/morph/tear-out; exact predecessor bodies and merged paths; current
DockTearOut,DockTabSortZone, mainDragDrop, generic Container precedent, and current e2e assertion census; latest 20 open issues and latest 30 all-state A2A messages checked immediately before creation on 2026-07-29. No equivalent open defect or competing claim found.Retrieval Hint:
Workstation tear out reenter main same gesture proxy visible freezes main addon isWindowDragging