LearnNewsExamplesServices
Frontmatter
id14772
titleCross-window drag showcase: the two-window transfer demo scene
stateOpen
labels
enhancementai
assigneesneo-gpt-emmy
createdAtJul 4, 2026, 3:17 PM
updatedAtJul 14, 2026, 10:42 PM
githubUrlhttps://github.com/neomjs/neo/issues/14772
authorneo-fable-clio
commentsCount4
parentIssue13158
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 15189 Stop cross-window transfers from invalidating dockZone.v1, [x] 14980 Early gestures are deaf to worker-side drag zones + no gesture-time key capture exists
blocking[]
milestonev13.2

Cross-window drag showcase: the two-window transfer demo scene

Open Backlog/active-chunk-4 enhancementai
neo-fable-clio
neo-fable-clio commented on Jul 4, 2026, 3:17 PM

Context

v13.2 needs one public scene that shows Neo's unique cross-window docking property: a live component moves between two active OS-window workspaces on the shared App-Worker heap without being serialized, recreated, or remounted.

Live reconciliation (2026-07-12): the broader pop-out / reattach continuity story already shipped through #14590 / PR #14999. The unique remaining value here is the real mid-gesture transfer: cold first gesture, remote target commit exactly once, source-local drop suppression exactly once, both workspace documents changing truthfully, and the same live instance continuing in the target.

The Problem

The engine contracts now exist, but the public product scene does not. A semantic transferItem unit or test-scoped composition can prove the reducer and participation seams; it cannot show the actual two-window pointer journey or falsify a broken gesture move leg. Conversely, a narrated pause cue with enough delay can look correct while racing the driver, which would violate the tour runner's settledness contract.

Architectural Reality

  • ADR 0029 §2.3 remains the authority: DragCoordinator is dock-blind; both workspaces share one sortGroup; target-side DockCrossWindowParticipation commits transferItem; source-side completion suppresses the local drop; documents stay worker-owned.
  • neo.tour.script.v1 currently executes op, pause, and topology-assert. It reserves cross-window and rejects it fail-closed. TourRunner passes ordinary surface cues as data but does not await them.
  • Neo.ai.client.InteractionService#simulateEvent already dispatches an ordered event sequence to named windows. Mouse-event options are forwarded to MouseEvent, including screenX / screenY; this is the existing primitive to falsify before inventing a new driver.
  • Placement is the AgentOS dockdemo childapp, reusing Demo B's stateful Workbench/counter and visual language. This leaf does not own #14640's separate live examples/dashboard/dock smoke residual.
  • #14980 is the live readiness dependency. A blind delay is forbidden; the scene waits for the owning readiness contract or fails closed.

Intended Solution

Phase 0 — the driver falsifier (first implementation action after #14980)

Build two active dockdemo workspaces with the same sortGroup, place their windows deterministically, and drive one event sequence through the existing InteractionService:

  1. mousedown on the source tab header;
  2. source-window mousemove events through the local drag threshold;
  3. source-window mousemove events whose screenX / screenY cross into the target workspace;
  4. source-window mouseup after the target accepts.

The probe passes only if the real move leg reaches DragCoordinator, the target commits once, the source suppresses its local drop once, and both documents reach the expected state. Synthetic DOM success alone is not success.

If this probe fails, stop the ticket before schema work and route the need for a new native/external driver through the Ideation Sandbox. Do not conceal the failure behind Playwright-only semantic calls or sleeps.

Phase 1 — activate the reserved tour step, only after the probe passes

Activate cross-window as an additive neo.tour.script.v1 step through an optional injected host executor, mirroring the existing injected dockService pattern:

{
    type             : 'cross-window',
    itemId           : 'workbench',
    sourceWorkspaceId: 'demo-b-main',
    targetWorkspaceId: 'demo-b-popup',
    targetNodeId     : 'popup-tabs'
}

The JSON script carries semantic workspace/item/node identities only—never runtime window ids, DOM ids, pixel coordinates, functions, or live references. The dockdemo host resolves current windows and geometry and executes the verified InteractionService sequence.

TourRunner awaits crossWindowExecutor.executeCrossWindowStep(step) and accepts only a structured result:

{
    applied,
    errors,
    sourceDocument,
    targetDocument,
    witness: {instanceId, mountCount}
}

Without a compatible executor, cross-window remains unavailable and validation fails closed. Existing scripts and all three existing step types remain byte-for-byte compatible. The runner logs the semantic step + structured outcome; no timestamps or runtime coordinates enter the replay log.

Phase 2 — product + proof

Reuse the Demo B Workbench counter as the visible continuity witness. The scene captures pre-state, performs the real drag, and then proves:

  • target document gained the item at the named node;
  • source document lost it and did not commit a second local move;
  • the live instanceId is identical before/after;
  • the mount counter did not increment and the visible counter kept advancing;
  • the record-mode take uses the same script and structured step outcome as the spec.

Contract Ledger

Target surface Source of authority Behavior Failure posture Evidence
cross-window script step neo.tour.script.v1 reserved vocabulary + this ticket semantic workspace/item/node data; enabled only with an injected executor absent/incompatible executor remains reserved and fails closed validator + mode/log identity units
gesture driver existing InteractionService.simulateEvent + #14980 readiness one source-window event sequence crosses target screen coordinates failed move-leg/target acceptance aborts; no sleep fallback two-window falsifier against the real coordinator
participation ADR 0029 §2.3 + DockCrossWindowParticipation target transferItem once; source local-drop suppression once unknown source/target/sortGroup refuses without document mutation counters/traces + both-document truth
continuity witness Demo B Workbench live instance same instance and mount count; visible state continues missing witness or remount fails the scene NL instance read + visible counter
topology proof each workspace's live dock document + diff_dock_topology deterministic pre/post deltas on both documents missing/invalid holder fails closed exact diff assertions in whitebox E2E
record surface TourRunner record mode same semantic step/log as spec; reduced-motion preflight remains enforced driver failure aborts the take visibly repeat-run log equality + operator eyes-on

Acceptance Criteria

  • #14980's readiness contract is landed and the cold-first-gesture path is green without a blind settle.
  • The Phase-0 InteractionService falsifier passes against two real active windows; otherwise the ticket stops and escalates before protocol work.
  • cross-window becomes executable only with the injected host executor; absent executor still fails closed as reserved.
  • Script data stays semantic and JSON-first; no runtime ids, coordinates, functions, or live refs enter the screenplay/log.
  • Target commit-once + source suppression-once and both-document topology deltas are asserted.
  • Workbench instanceId is stable, mount count does not increment, and visible state continues through transfer.
  • The same script drives demo/spec/record; two runs produce the same semantic operation log.
  • Cross-family review plus operator eyes-on for the visual bar.

Out of Scope

Rebuilding Demo B's generic pop-out/reattach continuity · changing DragCoordinator semantics · window-manager architecture · a new driver subsystem before the existing InteractionService falsifier · #14640's standalone-example smoke residual.

Dependencies and Lineage

Parent #13158 · live blocker #14980 · consumes landed #14768/#14769/#14640 substrate · reuses #14590 / PR #14999 continuity pane · siblings #14589/#14591. Decision-record impact: aligned with ADR 0029 §2.3; additive reserved-step activation only after the falsifier.

Origin Session ID: de713f27-0e82-4960-b4c6-f281e0c36449

Retrieval Hint: "cross-window tour step InteractionService screen coordinates commit once suppression once instance continuity"

tobiu referenced in commit 0401d09 - "fix(dashboard): lazy the DockTabSortZone DragCoordinator import — adapter spec loadable (#15065) (#15067) on Jul 12, 2026, 8:09 AM