LearnNewsExamplesServices
Frontmatter
id14857
titleDock drop-zone producer: hit-test + dockPreview.v1 for cross-zone tab drag
stateOpen
labels
enhancementaiarchitecture
assigneesneo-opus-grace
createdAt7:07 PM
updatedAt7:07 PM
githubUrlhttps://github.com/neomjs/neo/issues/14857
authorneo-opus-grace
commentsCount0
parentIssue13158
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[ ] 14769 Dock workspace cross-window participation: source hooks + target wiring

Dock drop-zone producer: hit-test + dockPreview.v1 for cross-zone tab drag

Open Backlog/active-chunk-4 enhancementaiarchitecture
neo-opus-grace
neo-opus-grace commented on 7:07 PM

Context

#14850 (merged) wired the dock's first gesture: a tab reorders within its own tabs node. The next gesture — the one the operator has explicitly asked to SEE — is dragging a tab header and releasing it into a different drop zone (another tabs node, or an edge/split of the workspace). That gesture is blocked on one missing piece: the drop-zone producer.

The Problem

The dock's drag pipeline is executor-complete but producer-empty:

  • Built: DockZoneModel semantic ops (moveItem, splitNode, addTab); AgentOS.view.DockPreview (previewToOperation descriptor + the transient visual affordance renderer); the example's applyDockZoneOperation / onDockZoneDocumentChange commit loop.
  • Missing (this leaf): the producer — raw drag geometry → a neo.harness.dockPreview.v1 object. DockPreview's own JSDoc names it out of scope ("The producer (raw drag geometry → dockPreview) … a separate docking leaf"), and it is wired nowhere — a grep for any producer of a dockPreview.v1 / placement kind returns zero hits.

V-B-A correction to #14769's premise: #14769 maps its previewFor owner-seam to "the landed hover→dockPreview compute path." That path is not landed. src/dashboard/CrossWindowDragTarget.mjs exposes hitTest (line 71) and previewFor (line 79) as null owner-seams — fail-closed shells awaiting an owner, not implementations. So #14769 (cross-window) depends-on this producer to fill those seams; it cannot bind them to a compute path that does not exist yet.

The Architectural Reality

  • Owner tier: src/dashboard/DockLayoutAdapter.mjs (projection SSOT) + apps/agentos/view/DockPreview.mjs (the render seam the app passes in). src/dashboard/ imports no app module — the app-side workspace composition passes the preview seam.
  • Reuse, not rebuild (no parallel drag system): the producer hooks the EXISTING drag lifecycle. The tab-header drag already fires via the tab-header SortZone (#14850); the container SortZone fires dragBoundaryEntry / dragBoundaryExit (src/draggable/container/SortZone.mjs:290,323); the dashboard SortZone + DragCoordinator own cross-container/cross-window remote drag. The producer is a hit-test + preview-compute layered on those events — it never adds a second drag system.
  • Placement vocabulary is already fixed by DockPreview.VALID_PLACEMENT_KINDS: edge-{top,right,bottom,left}, split-{before,after}, tab-{before,after,into}, rejected.
  • On drop: DockPreview.previewToOperation(preview) → a semantic descriptor → applyDockZoneOperation → commit + re-project. Already landed; the producer just has to feed it a valid preview.

The Fix

Scaffold the producer + land the tab-into placement first (drop a tab into another tabs node → moveItem(itemId, targetNodeId)): a workspace hit-test that maps a pointer (x,y) over the projected dock rects to a placement kind, produces a neo.harness.dockPreview.v1, feeds DockPreview (renders the affordance during the drag), and on drop routes through previewToOperationapplyDockZoneOperation. Wire it into the dock example's drag lifecycle. edge-* / split-* placements (drop-to-split) are follow-up slices on the same scaffold.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
producer: (pointer, projected rects) → dockPreview.v1 learn/agentos/HarnessDockZoneModel.md schema; DockPreview.VALID_PLACEMENT_KINDS Resolves the zone + placement kind under the pointer; emits a valid preview (tab-into first) Off any zone → placement.kind: 'rejected' → affordance clears, no mutation inline + DockPreview JSDoc updated (producer now landed) whitebox-e2e drops a tab cross-zone; unit test for the hit-test → placement mapping
CrossWindowDragTarget.hitTest / previewFor seams CrossWindowDragTarget.mjs:71,79 (null seams) Producer is the implementation #14769 binds these to fail-closed already enforced by the shell #14769 can cite this leaf as the landed producer

Decision Record impact

aligned-with ADR 0029 (§"no parallel drag system"; the producer rides the existing SortZone/DragCoordinator lifecycle). Corrects a stale premise in #14769 (its previewFor compute path is unbuilt) — #14769 becomes blocked-by this leaf.

Acceptance Criteria

  • A hit-test maps a pointer over the projected dock workspace to a placement kind (tab-into at minimum; off-workspace → rejected) — unit-tested against known rects.
  • The producer emits a schema-valid neo.harness.dockPreview.v1; DockPreview renders the affordance during a live drag.
  • Dropping a tab over a different tabs node commits moveItem to that node (App-Worker truth: the item leaves its source node and lands in the target) — fail-closed on rejected/errors[].
  • Whitebox-e2e drives the native cross-zone gesture and asserts the model move (ships in this PR — gesture-proof guardrail).
  • Cross-family review.

Out of Scope

  • edge-* / split-* drop-to-split placements — follow-up slices on this scaffold.
  • Cross-window / foreign-window transfer (#14769, now depends-on this) and its two-window demo (#14772).
  • Grouped-node drag (#14770), transition animation (#14779).

Related

Parent #13158 · authority ADR 0029 §2.3/§2.6 · unblocks #14769 (fills its hitTest/previewFor seams) → #14772 · renderer apps/agentos/view/DockPreview.mjs · builds on #14850.

Live latest-open sweep: checked latest open ai/enhancement issues on 2026-07-05; no equivalent producer/drop-zone leaf (#14769 is cross-window, #14771 overflow, #14772 demo). A2A in-flight sweep: mailbox scanned same session, no competing claim.

Origin Session ID: 9e42a8de-4291-46fc-944e-92ceb0db1748 Retrieval Hint: "dock drop-zone producer hit-test dockPreview.v1 previewToOperation cross-zone tab-into CrossWindowDragTarget seams"