Context
Found while fixing #19990 (Workstation; headless Chrome through the Neural Link fixture). Pop Metrics out (popup workstation-vessel:metrics), move Audit into it, then drag Metrics out of the popup over empty desktop.
The Problem
Nothing tears out. No vessel is admitted (tearOutHandlers.activeVessel stays null), no window opens, and the release leaves Metrics in the popup. Audit, in the same popup, tears out every time (#19990's e2e). So #19990's AC-3, "tears it out into a new popup every time", holds for every tab except the one its popup was opened for.
Inferred from the same derivation, not run: main refuses too, for an item dragged back into main while its old popup keeps other tabs and then torn out of main again.
The Architectural Reality
A vessel opened for metrics is identified by metrics in three places (intake, comment 6346317829):
- Its Group key.
Workstation.view.VesselWorkspace.vesselWorkspaceId(itemId) gives workstation-vessel:<itemId>, which tearOutWorkspaceKey hands the native reservation. Neo.manager.Transaction#reserve returns null for a key whose binding has a windowId, so NativeLifecycle#acquire refuses and the gesture degrades in-window (ADR 0029 §2.8.3). This is the wall a drag hits today.
- The native registry.
NativeLifecycle keys admissions, connections and owners by item id, and the popup holding Audit keeps its records under metrics.
- Its window name,
tearout-<itemId>. Main#windowOpen reuses a live window of that name, so a second vessel would navigate the popup that holds Audit.
Item-to-vessel lookups re-derive the key throughout VesselWorkspace (registerVesselWorkspaceTarget, retireVesselWorkspaceTarget, the park's disposeVessel, onTearOutDocumentChange) and in the tour's NativeGestureDriver.
Design authority: ADR 0029 §2.8.6 (amended 2026-10-09): "outside every window it is a vessel." The refusal contradicts it.
The Fix
Decided: option A. Euclid disposed it on his NativeLifecycle surface (#18314), 2026-10-22. A vessel is identified by its Group key, minted at admission:
- Mint and reserve in one synchronous, Group-owned step.
- The first choice is the derived key
workstation-vessel:<itemId>. When it is taken, the vessel gets the first free workstation-vessel:<itemId>:<n>.
- "Taken" includes pending and reconnecting reservations and retained logical slots.
Transaction#reserve replaces a binding whose windowId is null, so having no live window does not make a key free.
- An intentional rebind stays a separate path, and a retry within one gesture is idempotent.
- The native registry keys its records by that key. Each record keeps the opening item as provenance. Loops that take the item from a map key (bind, release, expiry, destruction) read it from the record instead, and the retirement fences around awaited preparation stay.
- Close and retire use the supplied key and generation, never the opening item resolved again.
NativeVesselTransaction#closeVessel prefers item-derived records today, so a late close of the old popup could hit the successor vessel.
- The window name follows the key.
- Keys persist verbatim. Nothing parses an item out of a key, renames a live participant, or recomputes a suffix on restore. An item's current home comes from the document that holds it.
Acceptance Criteria
Out of Scope
- #20004 (drags inside a popup that lies over main).
Related
#19990 (found there) · #20004 · #19533 · #18314
Live latest-open sweep: checked latest 20 open issues at 2026-10-22T14:43:03Z and the latest 6 again at 14:45:16Z, plus gh search issues for "vessel key origin tab tear out own popup"; no equivalent found.
A2A claim sweep: latest 30 messages at 2026-10-22T14:44Z; no overlapping lane-claim.
MC sweep: "tearing the first tab out of its own popup does nothing, the vessel slot is still bound to that popup", 6 results; no prior decision found.
Own-assignment sweep: 6 open, none overlapping.
Origin Session ID: cdb5023d-349c-443c-b1ad-d8c57688c97c
Retrieval Hint: "tab cannot tear out of the popup opened for it, vessel key derived from the item id is still bound"
Context
Found while fixing #19990 (Workstation; headless Chrome through the Neural Link fixture). Pop Metrics out (popup
workstation-vessel:metrics), move Audit into it, then drag Metrics out of the popup over empty desktop.The Problem
Nothing tears out. No vessel is admitted (
tearOutHandlers.activeVesselstaysnull), no window opens, and the release leaves Metrics in the popup. Audit, in the same popup, tears out every time (#19990's e2e). So #19990's AC-3, "tears it out into a new popup every time", holds for every tab except the one its popup was opened for.Inferred from the same derivation, not run: main refuses too, for an item dragged back into main while its old popup keeps other tabs and then torn out of main again.
The Architectural Reality
A vessel opened for
metricsis identified bymetricsin three places (intake, comment 6346317829):Workstation.view.VesselWorkspace.vesselWorkspaceId(itemId)givesworkstation-vessel:<itemId>, whichtearOutWorkspaceKeyhands the native reservation.Neo.manager.Transaction#reservereturnsnullfor a key whose binding has awindowId, soNativeLifecycle#acquirerefuses and the gesture degrades in-window (ADR 0029 §2.8.3). This is the wall a drag hits today.NativeLifecyclekeys admissions, connections and owners by item id, and the popup holding Audit keeps its records undermetrics.tearout-<itemId>.Main#windowOpenreuses a live window of that name, so a second vessel would navigate the popup that holds Audit.Item-to-vessel lookups re-derive the key throughout
VesselWorkspace(registerVesselWorkspaceTarget,retireVesselWorkspaceTarget, the park'sdisposeVessel,onTearOutDocumentChange) and in the tour'sNativeGestureDriver.Design authority: ADR 0029 §2.8.6 (amended 2026-10-09): "outside every window it is a vessel." The refusal contradicts it.
The Fix
Decided: option A. Euclid disposed it on his
NativeLifecyclesurface (#18314), 2026-10-22. A vessel is identified by its Group key, minted at admission:workstation-vessel:<itemId>. When it is taken, the vessel gets the first freeworkstation-vessel:<itemId>:<n>.Transaction#reservereplaces a binding whosewindowIdisnull, so having no live window does not make a key free.NativeVesselTransaction#closeVesselprefers item-derived records today, so a late close of the old popup could hit the successor vessel.Acceptance Criteria
WorkstationPopupTabDragNL.spec.mjstearing out the popup's own tab, red before the fix.Out of Scope
Related
#19990 (found there) · #20004 · #19533 · #18314
Live latest-open sweep: checked latest 20 open issues at 2026-10-22T14:43:03Z and the latest 6 again at 14:45:16Z, plus
gh search issuesfor "vessel key origin tab tear out own popup"; no equivalent found. A2A claim sweep: latest 30 messages at 2026-10-22T14:44Z; no overlapping lane-claim. MC sweep: "tearing the first tab out of its own popup does nothing, the vessel slot is still bound to that popup", 6 results; no prior decision found. Own-assignment sweep: 6 open, none overlapping.Origin Session ID: cdb5023d-349c-443c-b1ad-d8c57688c97c Retrieval Hint: "tab cannot tear out of the popup opened for it, vessel key derived from the item id is still bound"