Epic #15239 leaf — the cleanup-invariant enforcement of the #15240 outcome machine, split from G3/G4 so the idempotency work is one reviewable PR (D#15204 graduation shape named "the coordinator teardown hygiene leaf" explicitly; Step-Back ✗4 falsified the current residue). Unowned — self-select.
The Problem
Falsified residue paths in the current coordinator family (Step-Back ✗4, source-verified):
DragCoordinator.onDragEnd() calls source onRemoteDropOut() UNCONDITIONALLY — CrossWindowDragTarget.onRemoteDrop() returning null (no preview/operation committed) still retires the source gesture: a no-commit drop can strand the dragged item's source state.
DragCoordinator.unregister() clears candidates but can leave activeTargetZone populated — a stale target survives a vessel's departure.
Candidate timers (the 450 ms/250 ms dwell path) and preview state need exact-once disposal across ALL four terminals (COMMITTED_TARGET | TERMINAL_DETACHED | REJECTED | CANCELLED).
The Architectural Reality
Neo.manager.DragCoordinator (App Worker) + the participation seams (DockCrossWindowParticipation, CrossWindowDragTarget, DockTabSortZone.onRemoteDropOut/suspend/resume). The #15240 amendment ratifies the invariants; this leaf makes the code and witnesses match them. Blocked-by: #15240 (the invariant authority). Parallel-safe with G1 (different files).
The Fix
One PR: outcome-aware onDragEnd (source retirement ONLY on a committed outcome), unregister clearing activeTargetZone + timers, and an idempotency witness suite over every terminal × every cleanup surface.
Acceptance Criteria (the graduated invariant set)
onRemoteDropOut() fires ONLY when the target committed (onRemoteDrop() returned a real operation) — the null-commit path resumes/restores the source with zero model mutation; witnessed with the exact falsifier shape (begin drop, no commit, assert source intact).
unregister() leaves no activeTargetZone, no candidate timer, no preview residue; re-registering the same identity starts clean.
Every cleanup surface (preview, claim, candidate timer, activeTargetZone, registration, vessel bookkeeping) is idempotent — double-invocation of any terminal is a witnessed no-op.
The witness matrix covers all four terminals, including a mid-gesture vessel disappearance (window closed under the drag) resolving to a clean terminal.
Zero behavior change on the committed happy path (the existing cross-window witness stays green unmodified).
Out of Scope
The claim protocol itself (G3) · vessel close policy (G4) · any new gesture capability.
Context
Epic
#15239leaf — the cleanup-invariant enforcement of the#15240outcome machine, split from G3/G4 so the idempotency work is one reviewable PR (D#15204 graduation shape named "the coordinator teardown hygiene leaf" explicitly; Step-Back ✗4 falsified the current residue). Unowned — self-select.The Problem
Falsified residue paths in the current coordinator family (Step-Back ✗4, source-verified):
DragCoordinator.onDragEnd()calls sourceonRemoteDropOut()UNCONDITIONALLY —CrossWindowDragTarget.onRemoteDrop()returningnull(no preview/operation committed) still retires the source gesture: a no-commit drop can strand the dragged item's source state.DragCoordinator.unregister()clears candidates but can leaveactiveTargetZonepopulated — a stale target survives a vessel's departure.COMMITTED_TARGET | TERMINAL_DETACHED | REJECTED | CANCELLED).The Architectural Reality
Neo.manager.DragCoordinator(App Worker) + the participation seams (DockCrossWindowParticipation,CrossWindowDragTarget,DockTabSortZone.onRemoteDropOut/suspend/resume). The#15240amendment ratifies the invariants; this leaf makes the code and witnesses match them. Blocked-by:#15240(the invariant authority). Parallel-safe with G1 (different files).The Fix
One PR: outcome-aware
onDragEnd(source retirement ONLY on a committed outcome),unregisterclearingactiveTargetZone+ timers, and an idempotency witness suite over every terminal × every cleanup surface.Acceptance Criteria (the graduated invariant set)
onRemoteDropOut()fires ONLY when the target committed (onRemoteDrop()returned a real operation) — the null-commit path resumes/restores the source with zero model mutation; witnessed with the exact falsifier shape (begin drop, no commit, assert source intact).unregister()leaves noactiveTargetZone, no candidate timer, no preview residue; re-registering the same identity starts clean.activeTargetZone, registration, vessel bookkeeping) is idempotent — double-invocation of any terminal is a witnessed no-op.Out of Scope
The claim protocol itself (G3) · vessel close policy (G4) · any new gesture capability.
Related
Parent
#15239· blocked-by#15240· D#15204 (Step-Back ✗4) · siblings#15246(G3) /#15247(G4, consumes these invariants).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: "coordinator teardown activeTargetZone onRemoteDropOut null-commit idempotent exact-once"