Context
ADR 0029 §2.4's executor half (learn/agentos/decisions/0029-harness-docking-design.md) — the Qt-ADS bar: dragging a title bar moves the whole tabbed GROUP. Wholly unfiled per the ADR's §5 leaf table. Filed to the delegatable bar: non-fable implementable; the section is a complete op contract.
The Problem
The dock tree already models the group — a tabs node — but the executor vocabulary only moves ITEMS. Grouped drag needs node-level operations: re-parent a subtree within one document, and transfer a subtree across documents, both preserving every member item and normalizing afterward.
The Architectural Reality
- Executor:
src/dashboard/DockZoneModel.mjs, same pure static family + fail-closed result contract.
moveNode — {operation: 'moveNode', nodeId, targetNodeId, placement} within one document: re-parents the subtree per the landed placement descriptors; normalizeTree guarantees invariants after (ADR §2.4 verbatim).
transferNode — #14768's transferItem semantics applied to a subtree: atomic two-document commit, ALL member item records travel verbatim, hints update per item. Reuses #14768's machinery — no second atomicity implementation.
- Preview layer: ONE additive runtime-only field
groupNodeId on the existing dockPreview payload (set when the drag source is a group handle); dockPreview stays v1; the field never persists. Placement kinds unchanged; a group dropped tab-into merges its items into the target tabs node in order.
- Cycle guard: moving a node into its own subtree must fail closed (the landed fingerprint-walk cycle discipline extends to placement validation).
The Fix
One PR: both ops + the groupNodeId preview-field documentation + specs (moveNode re-parent + normalize; into-own-subtree fail-closed; transferNode atomicity via forced target failure; member records verbatim; tab-into merge order; unknown node/target fail-closed).
Acceptance Criteria
Out of Scope
The group-handle drag surface / tab-bar drag source UI (rides the §2.7/#13280 line) · tab overflow (sibling leaf) · #14768 itself.
Related
Parent #13158 · authority ADR 0029 §2.4 · blocked_by #14768 (transferNode reuse) · joins #14715's vocabulary. Decision Record impact: aligned-with ADR 0029.
Live latest-open sweep: latest 20 at 2026-07-04T13:15Z, no equivalent. A2A in-flight sweep: all-states 30 at 13:15Z, no competing claim.
Origin Session ID: fa2a6fd5-7488-4af6-a0d2-3855c86003e4
Retrieval Hint: "moveNode transferNode grouped drag subtree executor"
Context
ADR 0029 §2.4's executor half (
learn/agentos/decisions/0029-harness-docking-design.md) — the Qt-ADS bar: dragging a title bar moves the whole tabbed GROUP. Wholly unfiled per the ADR's §5 leaf table. Filed to the delegatable bar: non-fable implementable; the section is a complete op contract.The Problem
The dock tree already models the group — a
tabsnode — but the executor vocabulary only moves ITEMS. Grouped drag needs node-level operations: re-parent a subtree within one document, and transfer a subtree across documents, both preserving every member item and normalizing afterward.The Architectural Reality
src/dashboard/DockZoneModel.mjs, same pure static family + fail-closed result contract.moveNode—{operation: 'moveNode', nodeId, targetNodeId, placement}within one document: re-parents the subtree per the landed placement descriptors;normalizeTreeguarantees invariants after (ADR §2.4 verbatim).transferNode—#14768'stransferItemsemantics applied to a subtree: atomic two-document commit, ALL member item records travel verbatim, hints update per item. Reuses#14768's machinery — no second atomicity implementation.groupNodeIdon the existingdockPreviewpayload (set when the drag source is a group handle);dockPreviewstays v1; the field never persists. Placement kinds unchanged; a group droppedtab-intomerges its items into the target tabs node in order.The Fix
One PR: both ops + the
groupNodeIdpreview-field documentation + specs (moveNode re-parent + normalize; into-own-subtree fail-closed; transferNode atomicity via forced target failure; member records verbatim; tab-into merge order; unknown node/target fail-closed).Acceptance Criteria
moveNodere-parents per placement descriptor; invariants hold post-normalize (spec).transferNodereuses the#14768atomic path (commit-both-or-neither spec) with per-item hint updates.groupNodeIddocumented as runtime-only; persistence paths reject it (the landed preview-key rejection extends).Out of Scope
The group-handle drag surface / tab-bar drag source UI (rides the §2.7/#13280 line) · tab overflow (sibling leaf) ·
#14768itself.Related
Parent
#13158· authority ADR 0029 §2.4 · blocked_by#14768(transferNode reuse) · joins#14715's vocabulary. Decision Record impact: aligned-with ADR 0029. Live latest-open sweep: latest 20 at 2026-07-04T13:15Z, no equivalent. A2A in-flight sweep: all-states 30 at 13:15Z, no competing claim. Origin Session ID: fa2a6fd5-7488-4af6-a0d2-3855c86003e4 Retrieval Hint: "moveNode transferNode grouped drag subtree executor"