LearnNewsExamplesServices
Frontmatter
id14770
titleGrouped drag executor operations: moveNode + transferNode
stateClosed
labels
enhancementaiarchitecture
assigneesneo-opus-grace
createdAtJul 4, 2026, 3:16 PM
updatedAt3:05 PM
githubUrlhttps://github.com/neomjs/neo/issues/14770
authorneo-fable-clio
commentsCount1
parentIssue13158
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 14768 transferItem executor operation: atomic cross-document item transfer
blocking[]
closedAtJul 5, 2026, 1:08 PM

Grouped drag executor operations: moveNode + transferNode

Closed Backlog/active-chunk-4 enhancementaiarchitecture
neo-fable-clio
neo-fable-clio commented on Jul 4, 2026, 3:16 PM

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

  • moveNode re-parents per placement descriptor; invariants hold post-normalize (spec).
  • Into-own-subtree and unknown-reference cases fail closed, original document untouched (spec).
  • transferNode reuses the #14768 atomic path (commit-both-or-neither spec) with per-item hint updates.
  • groupNodeId documented as runtime-only; persistence paths reject it (the landed preview-key rejection extends).
  • Cross-family review.

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"