Context
Epic #15239 leaf G4 — beat 5 of the five-beat story: grab the merged stack in a popup, drag it back into main, previews light, drop commits, the emptied popup closes itself. Implements the #15240 outcome machine's terminal effects (D#15204 OQ5b [RESOLVED_TO_AC], cycle-4) and owns OQ5a as its first design task. Unowned — self-select.
The Problem
Four gaps: (a) transferNode() (ADR 0029 §2.4, landed) rejects workspace ROOTS — a whole popup stack has no source projection today (OQ5a, this leaf's first design decision: stack source projection vs the root rejection; additive on dockLayout.v2 only, per the epic's revalidationTrigger); (b) addTab APPENDS — exact-position reintegration needs stored-index capture/restore (cycle-4c verified, DC_kwDODSospM4BDXXd); (c) vessel close policy is undesigned; (d) ADR 0029 §2.2 placement hints are a named remaining obligation.
The Architectural Reality
- The
#15240 outcome machine governs every terminal: source cleanup + empty-vessel close ONLY after COMMITTED_TARGET; reject/no-preview restores the source with zero model mutation; model commit precedes window close — a close failure can neither roll back the commit nor double-reintegrate.
Container.onWindowDisconnect() may reintegrate unless its runtime flags are exact (falsified risk, Step-Back ✗4) — the close path must be idempotent against it.
- Empty-workspace registry disposition (Step-Back ✓7): closing a vessel unbinds a render target; whether the emptied workspace-set entry is retained or retired is named SEPARATELY from closing its OS window; recovery stays semantic through
fallbackTarget.
- Blocked-by:
#15246 (G3's workspace-set + claims are the substrate a stack transfer commits through).
The Fix
One PR: the stack source projection (OQ5a design + implementation, additive hints on dockLayout.v2 with migration + fail-closed tests if any schema field is added), stored-index capture/restore for exact return, the vessel close policy per the outcome machine, and the §2.2 placement-hint layer for the return drop.
Acceptance Criteria (the graduated OQ5a/OQ5b contracts)
Contract Ledger (folded 2026-07-18, claimant-implementer disposition — the body predates the ledger readiness gate)
| Surface |
Owner |
Caller(s) |
Inputs → Outputs |
Unknown / stale / failure behavior |
Persistence class (ADR-0029 §2.1 table) |
| Stack source projection (OQ5a — design-pending, resolved in-leaf per AC2) |
DockZoneModel (executor tier) |
the whole-stack reintegration gesture source |
a root-subtree source descriptor, additive on dockLayout.v2 → one atomic two-document transfer (commit-or-neither) |
transferNode's root rejection STAYS for the plain operation — the stack surface is explicit, never an implicit root-transfer; any schema field addition ships migration + fail-closed tests atomically (the epic's revalidationTrigger) |
dockZone.v1 documents = worker-owned shared truth; v2 hints additive |
| Stored-index capture/restore |
the workspace container host |
detach path (capture) + reintegration path (restore) |
{tabsNodeId, index} captured at detach → addTab append compensated to the exact stored position |
missing/stale index → semantic fallbackTarget recovery (nearest surviving ancestor), never pixel geometry |
durable placement-hint layer (§2.1 hints) |
| Vessel close policy |
the outcome-machine consumer (host) |
the COMMITTED_TARGET terminal only |
committed document pair → render-target close |
commit precedes close; a close failure can neither roll back the committed documents nor double-reintegrate (Container.onWindowDisconnect idempotent against committed state — the disconnect ownership-settlement landed on the cockpit is this contract's pre-G4 half) |
none — close is a post-commit render-target effect, never part of the model transaction |
| Emptied workspace-set entry disposition |
this leaf (the retained-vs-retired decision is G4's by name) |
the vessel-close path over DockWorkspaceSet.unregister |
explicit retain or retire per the decided policy |
the registry ships retirement-explicit-only precisely so this leaf owns the decision; post-retirement resolution fails closed (getDocument → null) |
registry runtime worker-owned; documents remain worker truth regardless of entry disposition |
| §2.2 placement hints on the return drop |
the shared affordance consumer |
the main window's preview pipeline during the return hover |
hint layer → rendered WHERE-the-stack-lands affordances |
no hints → no silent commit; the preview→operation pipeline is unchanged (no parallel drag system) |
runtime-only preview state |
Out of Scope
Claim arbitration (G3, consumed) · tear-out (G1/G2) · coordinator teardown residue (its own leaf) · the keyboard path (its own leaf).
Related
Parent #15239 · blocked-by #15246 · D#15204 (OQ5a/OQ5b; Step-Back ✗4/✓7) · #15240 (outcome authority) · #15193 (transfer guards) · cycle-4c deposit DC_kwDODSospM4BDXXd.
Live latest-open sweep: latest 20 at 2026-07-16T10:56Z + last-step re-check 11:09Z; no equivalent. A2A claim sweep: no competing claim.
Origin Session ID: c5d7cd6b-4e01-45fd-aa59-5ccbc0e5f091
Retrieval Hint: "G4 whole-stack reintegration vessel close stored-index transferNode root OQ5a"
Context
Epic
#15239leaf G4 — beat 5 of the five-beat story: grab the merged stack in a popup, drag it back into main, previews light, drop commits, the emptied popup closes itself. Implements the#15240outcome machine's terminal effects (D#15204 OQ5b[RESOLVED_TO_AC], cycle-4) and owns OQ5a as its first design task. Unowned — self-select.The Problem
Four gaps: (a)
transferNode()(ADR 0029 §2.4, landed) rejects workspace ROOTS — a whole popup stack has no source projection today (OQ5a, this leaf's first design decision: stack source projection vs the root rejection; additive ondockLayout.v2only, per the epic'srevalidationTrigger); (b)addTabAPPENDS — exact-position reintegration needs stored-index capture/restore (cycle-4c verified,DC_kwDODSospM4BDXXd); (c) vessel close policy is undesigned; (d) ADR 0029 §2.2 placement hints are a named remaining obligation.The Architectural Reality
#15240outcome machine governs every terminal: source cleanup + empty-vessel close ONLY afterCOMMITTED_TARGET; reject/no-preview restores the source with zero model mutation; model commit precedes window close — a close failure can neither roll back the commit nor double-reintegrate.Container.onWindowDisconnect()may reintegrate unless its runtime flags are exact (falsified risk, Step-Back ✗4) — the close path must be idempotent against it.fallbackTarget.#15246(G3's workspace-set + claims are the substrate a stack transfer commits through).The Fix
One PR: the stack source projection (OQ5a design + implementation, additive hints on
dockLayout.v2with migration + fail-closed tests if any schema field is added), stored-index capture/restore for exact return, the vessel close policy per the outcome machine, and the §2.2 placement-hint layer for the return drop.Acceptance Criteria (the graduated OQ5a/OQ5b contracts)
dockLayout.v2; any schema addition ships migration + fail-closed tests atomically).addTabappend semantics compensated); witnessed round-trip (detach → return → identical topology AND order).COMMITTED_TARGET; commit-precedes-close witnessed; a simulated close failure leaves the committed document intact with no double-reintegration (theonWindowDisconnectidempotency pinned).#15207consumer.Contract Ledger (folded 2026-07-18, claimant-implementer disposition — the body predates the ledger readiness gate)
DockZoneModel(executor tier)dockLayout.v2→ one atomic two-document transfer (commit-or-neither)transferNode's root rejection STAYS for the plain operation — the stack surface is explicit, never an implicit root-transfer; any schema field addition ships migration + fail-closed tests atomically (the epic'srevalidationTrigger)dockZone.v1documents = worker-owned shared truth;v2hints additive{tabsNodeId, index}captured at detach →addTabappend compensated to the exact stored positionfallbackTargetrecovery (nearest surviving ancestor), never pixel geometryCOMMITTED_TARGETterminal onlyContainer.onWindowDisconnectidempotent against committed state — the disconnect ownership-settlement landed on the cockpit is this contract's pre-G4 half)DockWorkspaceSet.unregistergetDocument→ null)Out of Scope
Claim arbitration (G3, consumed) · tear-out (G1/G2) · coordinator teardown residue (its own leaf) · the keyboard path (its own leaf).
Related
Parent
#15239· blocked-by#15246· D#15204 (OQ5a/OQ5b; Step-Back ✗4/✓7) ·#15240(outcome authority) ·#15193(transfer guards) · cycle-4c depositDC_kwDODSospM4BDXXd.Live latest-open sweep: latest 20 at 2026-07-16T10:56Z + last-step re-check 11:09Z; no equivalent. A2A claim sweep: no competing claim.
Origin Session ID: c5d7cd6b-4e01-45fd-aa59-5ccbc0e5f091 Retrieval Hint: "G4 whole-stack reintegration vessel close stored-index transferNode root OQ5a"