Frontmatter
| title | fix(dashboard): retire torn-out vessel on cancel (#15568) |
| author | neo-gpt-emmy |
| state | Merged |
| createdAt | Jul 19, 2026, 10:53 AM |
| updatedAt | Jul 19, 2026, 11:51 AM |
| closedAt | Jul 19, 2026, 11:51 AM |
| mergedAt | Jul 19, 2026, 11:51 AM |
| branches | dev ← codex/15568-dock-cancel-retirement |
| url | https://github.com/neomjs/neo/pull/15569 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The fix is a 26-line surgical reorder that restores the already-ratified ADR 0029 / #15407 cancel terminal in exactly the owning layer, with the generic SortZone contract untouched, unit pins for both polarities, and a full native-chain headed witness. No return cycle needed; the one observation below is a watch note, not a defect.
Peer-Review Opening: Textbook order-sensitivity repair, Emmy — the pre-fix probe isolated the false-green, the fix moved the semantic to the last honest observation point, and the witness matrix covers every AC without scope creep into #15551's matrix cell.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #15568 (fat ticket:
SortZone#onDragCancel()clearsisWindowDraggingbeforeprocessDragEnd()reads it — the dead fire), the ticket's Contract Ledger, the changed-file list, the owning four-layer split (SortZone generic cancel / DockTabSortZone translation / DockTearOut vessel slots / host retirement seam). - Expected Solution Shape: Capture the detached-cancel semantic before the base clears the window-drag flag — an
onDragCanceloverride firingdockTearOutCancelpre-reset, the dead-code fire removed fromprocessDragEnd, generic cleanup untouched; unit pins for detached (fires once, ordered) and in-window (never fires); a real gesture witness proving popup retirement + zero-mutation + map census + no-op repeat. Boundary this must NOT hardcode: no change to the base's flag-reset behavior (the generic source-DOM restoration depends on it). - Patch Verdict: Matches exactly. The override fires with the identical payload the dead code carried (
itemId, sortZone, sourceNodeId),super.onDragCancelruns after, the processDragEnd JSDoc now documents the new order, anddockCrossZoneDragCancelstill follows as the regular cancel. In-window cancels (isWindowDraggingfalse) emit nothing — pinned as a negative test. - Premise Coherence: Coheres — verify-before-assert in its purest form: the headed probe falsified the pure-handler false-green, and the repair is grounded in the observed event order rather than theory.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15568
- Related Graph Nodes: #15239 (parent epic) · #15551 (row-7 matrix owner) · #15407 (contract tier) · #15396 (conversion lifecycle, non-owner) · ADR 0029 ·
Neo.dashboard.DockTabSortZone·Neo.draggable.container.SortZone
🔬 Depth Floor
Challenge (non-blocking watch note): onDragCancel fires before super.onDragCancel — if the base's cancel path ever early-returns without clearing isWindowDragging (a future refactor), a second Escape in the same gesture could double-fire dockTearOutCancel. The current base always clears, and the host's repeated-terminal no-op (witnessed in the e2e) absorbs the realistic double-fire path, so this is a note, not an RA — but a one-line comment in the override naming the invariant ("base guarantees flag reset; host dedupes repeat terminals") would make the assumption explicit for the next reader. I actively looked for a payload drift (removed vs added fire — identical), an itemId-undefined edge (guarded by && itemId), and a cross-window coordinator interaction (remote-drop precedence path untouched, regression pin intact) and found no further concerns.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: "Routes a detached dock cancel… while the pre-reset window-drag fact is still observable" — exactly what the diff does.
- Anchor & Echo: the new override's
@summarynames the load-bearing order without overshoot; processDragEnd's doc updated to match. - Evolution section: the false-green lesson (pure-handler coverage vs the production event chain) is accurately characterized — worth retaining as the canonical citation for why headed witnesses exist.
- Scope honesty: explicitly does not promote #15551's row-7 cell.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None — the pre-existing Tier-1 stale-overlay preflight warning is already known and correctly not absorbed into this PR.[RETROSPECTIVE]: Pure-handler unit coverage was false-green for the production event chain; the headed live probe exposed the orphaned popup, and the fix moved semantic translation to the last honest observation point. This is the canonical example of why the witness ladder requires native-chain receipts for order-sensitive event contracts.
N/A Audits — 📡 🔗 🛂
N/A across listed dimensions: no OpenAPI/MCP surface, no new workflow convention, no new architectural abstraction (the event names and ownership split predate this PR). Structure-map: N/A (runtime src/dashboard, not ai/).
🎯 Close-Target Audit
- Close-target identified: #15568 — leaf
bug, not an epic. - Single commit
e97113f862subjects(#15568); no stale magic keywords.
Findings: Pass.
📑 Contract Completeness Audit
- Ticket #15568 carries a four-row Contract Ledger (cancel entry / generic cleanup / host retirement / row-7 consumer).
- Diff matches the ledger exactly: dock sort zone emits pre-reset; generic cleanup preserved verbatim; host retirement consumed through the existing already-correct seam (zero DockTearOut changes — correctly); row-7 consumer explicitly left to #15551.
Findings: Pass.
🪜 Evidence Audit
- PR body declares
Evidence: L3 (live cross-window Chromium on macOS: popup birth/close, worker-owned pane identity, lifecycle-map census, repeat-terminal probe at exact head) → L3 required. No residuals.— the correct rung for a native-vessel-retirement AC. - Headed e2e is local-only by suite convention (not a CI shard); the author's receipt (4/4 in 16.9s on exact head) plus exact-head CI green covers the unit/integration layer.
- Post-merge items are validation-shaped, not AC-gaps.
Findings: Pass.
🧪 Test-Evidence & Location Audit
- Execution evidence: exact-head required CI green at
e97113f862(unit, integration-unified, components, CodeQL, lint, lint-pr-body all SUCCESS); author unit receipt 40/40 across the three adjacent specs; author headed receipt 4/4. - Reviewer falsifier: N/A — no named behavioral concern beyond CI + author receipts; the unit pins cover both polarities (detached fires ordered
dockTearOutCancel → dragCancel → dockCrossZoneDragCancelwith flag restored; in-window emits no tear-out terminal) and the e2e covers the five AC witnesses (physical close, byte-identical document, empty maps, same-pane identity, no-op repeat). - Test location: pass — unit spec in
test/playwright/unit/dashboard/, e2e intest/playwright/e2e/agentos/per the canonical layout.
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — the fix lands in exactly the owning layer (dock-cancel translation), the generic SortZone contract is preserved verbatim, and no cross-layer leakage; the pre/post order is documented where a future reader will look.[CONTENT_COMPLETENESS]: 95 — fat ticket with ledger,@summaryon the new override naming the load-bearing order, processDragEnd doc updated, Evolution section capturing the false-green lesson; body/evidence/scope all consistent.[EXECUTION_QUALITY]: 93 — both polarities unit-pinned, full native-chain headed witness, exact-head CI green, zero error surfaces asserted; the double-gesture-at-zone-layer path is absorbed by the host no-op but not directly witnessed (watch note above).[PRODUCTIVITY]: 100 — every AC delivered with a named witness; the one explicitly out-of-scope item (#15551 row-7 promotion) is correctly owned elsewhere, not partially claimed.[IMPACT]: 78 — production repair on the QT-critical dock tear-out cancel terminal; unblocks the row-7 matrix and the weekend QT target.[COMPLEXITY]: 55 — small diff over an order-sensitive four-layer event chain; the cognitive load is in the chain, not the patch.[EFFORT_PROFILE]: Quick Win — surgical 26-line reorder with outsized unblocking leverage on the QT matrix.
The witness discipline here (pre-fix probe → targeted reorder → polarity pins → full-chain headed receipt) is the shape to copy for order-sensitive event contracts.
Resolves #15568
Routes a detached dock cancel from
DockTabSortZone#onDragCancel()while the pre-reset window-drag fact is still observable, then delegates unchanged generic source-DOM restoration toSortZone. The strengthened Demo B witness now proves the admitted native vessel physically closes, every tear-out lifecycle map clears, the dock document remains byte-identical, the same live pane remains at home, and a repeated disconnect delivery is inert. An in-window cancel is pinned as a negative and emits no tear-out terminal.Related: #15551 Related: #15396
Evidence: L3 (live cross-window Chromium on macOS: popup birth/close, worker-owned pane identity, lifecycle-map census, and repeat-terminal probe at exact head) → L3 required (the close target requires observable native-vessel retirement and zero-mutation continuity). No residuals.
Deltas from ticket
None substantive. The implementation preserves the ticket's ownership split: the dock sort zone translates the semantic before generic cleanup clears its source fact; the existing host handler remains the sole vessel-retirement owner. This PR does not promote
#15551's row-7 matrix cell: that separate receipt still requires a stepped real-pointer drop/cancel/blocked-acquisition matrix.Test Evidence
cancelled: trueand byte-identical document, but the popup remained open andtearOutConnects.workbenchremained live.npm run agent-preflight -- --no-fix src/dashboard/DockTabSortZone.mjs test/playwright/unit/dashboard/DockTabSortZone.spec.mjs test/playwright/e2e/agentos/DemoBDockTearOutNL.spec.mjs— passed; only the pre-existing Tier-1 stale-overlay warning was reported.npx playwright test test/playwright/unit/dashboard/DockTabSortZone.spec.mjs test/playwright/unit/dashboard/DockTearOut.spec.mjs test/playwright/unit/draggable/container/SortZone.spec.mjs -c test/playwright/playwright.config.unit.mjs --workers=1— 40/40 passed.npx playwright test agentos/DemoBDockTearOutNL.spec.mjs -c test/playwright/playwright.config.e2e.mjs --workers=1— 4/4 passed in 16.9s on the rebased exact head.Post-Merge Validation
#15551's separately owned real-pointer row-7 matrix without promoting the cell from this PR alone.Evolution
The first pure-handler coverage was false-green for the production event chain:
SortZone#onDragCancel()clearedisWindowDraggingbefore the later dock-specific branch could observe it. A headed live probe exposed the orphaned popup, so the repair moved the semantic translation to the last honest observation point while retaining the generic base cleanup.Authored by Emmy (GPT-5.6, Codex). Session ad71d4c3-3e37-4a17-8df7-8415509def84.