Context
The unfiled §2.3 executor half of ADR 0029 (learn/agentos/decisions/0029-harness-docking-design.md) — cross-window drag lands its target contract in #14670 (PR #14757), but the operation the drop ultimately commits does not exist yet. Filed to the delegatable bar under the fable budget regime: non-fable implementable; the ADR section is the complete design authority.
The Problem
Moving an item between two workspace documents (window A's dock tree → window B's) needs ONE semantic operation with atomic two-document semantics. Without it, the receiving-window target (#14670) can only commit same-document operations, and any ad-hoc two-step (remove here, add there) can strand an item — the ADR names a half-transferred item a contract violation, not an error state.
The Architectural Reality
- Executor:
src/dashboard/DockZoneModel.mjs — the pure static op family (applyOperation switch) + the landed fail-closed {document, errors} contract, extended to a two-document result.
- The op shape (ADR §2.3, verbatim):
{operation: 'transferItem', itemId, sourceWorkspaceId, targetWorkspaceId, target: {operation: 'addTab'|'splitNode', ...}} — the nested target reuses the landed single-document placement descriptors.
- The executor operates on documents, not workspaces: signature takes
(sourceDocument, targetDocument, descriptor) and returns both post-op documents or neither; workspace-id resolution is the caller's (adapter tier).
- Vocabulary SSOT:
#14715 — the new op joins whatever exported vocabulary shape that leaf lands.
The Fix
One PR on DockZoneModel: transferItem (validate against BOTH documents first → remove from source tree+catalog → insert into target catalog + placement → normalize both → commit both or neither; item record travels verbatim — id, componentRef, title, kind, policy hints, blueprint, metadata). Fail-closed: any validation error on either side returns BOTH original documents + non-empty errors. Unit specs: happy path (catalog + tree membership moves, record verbatim), atomicity (target-side failure leaves source untouched), policy enforcement (movable: false rejects), unknown item/target fail-closed, normalize-collapse on the emptied source slot.
Acceptance Criteria
Out of Scope
Live-instance move / adapter commit wiring (sibling wiring leaf) · durable placement-hint updates (owningWorkspaceId — rides the wiring leaf where hints live) · transferNode (grouped-drag leaf reuses these semantics).
Related
Parent #13158 (authority ADR 0029 §2.3) · consumed by the participation-wiring leaf + #14668 (changed-topology restore's C3 boundary) · 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: "transferItem atomic two-document executor dockZone"
Context
The unfiled §2.3 executor half of ADR 0029 (
learn/agentos/decisions/0029-harness-docking-design.md) — cross-window drag lands its target contract in#14670(PR#14757), but the operation the drop ultimately commits does not exist yet. Filed to the delegatable bar under the fable budget regime: non-fable implementable; the ADR section is the complete design authority.The Problem
Moving an item between two workspace documents (window A's dock tree → window B's) needs ONE semantic operation with atomic two-document semantics. Without it, the receiving-window target (
#14670) can only commit same-document operations, and any ad-hoc two-step (remove here, add there) can strand an item — the ADR names a half-transferred item a contract violation, not an error state.The Architectural Reality
src/dashboard/DockZoneModel.mjs— the pure static op family (applyOperationswitch) + the landed fail-closed{document, errors}contract, extended to a two-document result.{operation: 'transferItem', itemId, sourceWorkspaceId, targetWorkspaceId, target: {operation: 'addTab'|'splitNode', ...}}— the nestedtargetreuses the landed single-document placement descriptors.(sourceDocument, targetDocument, descriptor)and returns both post-op documents or neither; workspace-id resolution is the caller's (adapter tier).#14715— the new op joins whatever exported vocabulary shape that leaf lands.The Fix
One PR on
DockZoneModel:transferItem(validate against BOTH documents first → remove from source tree+catalog → insert into target catalog + placement → normalize both → commit both or neither; item record travels verbatim — id, componentRef, title, kind, policy hints, blueprint, metadata). Fail-closed: any validation error on either side returns BOTH original documents + non-empty errors. Unit specs: happy path (catalog + tree membership moves, record verbatim), atomicity (target-side failure leaves source untouched), policy enforcement (movable: falserejects), unknown item/target fail-closed, normalize-collapse on the emptied source slot.Acceptance Criteria
targetdescriptor reuses landed placement validation (no second placement grammar).{sourceDocument, targetDocument, errors}result shape; policy hints enforced.Out of Scope
Live-instance move / adapter commit wiring (sibling wiring leaf) · durable placement-hint updates (
owningWorkspaceId— rides the wiring leaf where hints live) ·transferNode(grouped-drag leaf reuses these semantics).Related
Parent
#13158(authority ADR 0029 §2.3) · consumed by the participation-wiring leaf +#14668(changed-topology restore's C3 boundary) · 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: "transferItem atomic two-document executor dockZone"