Context
Booting a SharedWorkers dock workspace (private client repo) prints two warnings in the app worker before any interaction: sendMessage destination "main" is deprecated. Use a windowId instead. A race-free CDP attach (browser-level auto-attach, waitForDebuggerOnStart) captured the live argument previews: both are remote-method calls with remoteClassName=Neo.main.addon.DockFlip, remoteMethod=captureFirst / play, destination=main.
Live latest-open sweep: checked latest 20 open issues at 2026-08-30T22:15Z; no equivalent found. Prior art: #8149 migrated messaging to explicit window ids and introduced this deprecation; #8366 fixed the same class of warning for registerRemote.
The Problem
src/dashboard/dock/Workspace.mjs calls the FLIP addon without a windowId:
- line 1587:
flip?.captureFirst({hostId: host.id, markerPrefix: flipMarkerPrefix})
- line 1654:
flip.play({hostId: host.id, markerPrefix: flipMarkerPrefix, geometryOnly: ...})
RemoteMethodAccess#generateRemote swaps the destination to data.windowId only when the caller provides it; absent, the destination stays the deprecated 'main' string and the SharedWorker port cascade falls through to the last-resort first port (worker/Base.mjs#sendMessage JSDoc).
Consequences by topology:
- Single window (today): works by accident — the first port IS the only window — plus two deprecation warnings on every boot, in every consumer's console.
- Multi window (tear-out / popup roadmap, old cross-window drag demos): the FLIP capture and play address the FIRST connected window's main thread, not the window whose DOM hosts the dock — a silent wrong-realm no-op at best.
The Architectural Reality
Neo.main.addon.DockFlip is a per-window main-thread addon; its methods operate on THEIR window's DOM and read no windowId from data (grep receipt: no windowId in src/main/addon/DockFlip.mjs). The field is pure routing. The exact realm owning the captured markers is the dock host component's window — host.windowId — which refreshDockWorkspace already has in hand.
The Fix
Add windowId: host.windowId to both payloads in refreshDockWorkspace (src/dashboard/dock/Workspace.mjs:1587 and :1654).
Decision Record impact: none (conforms to the routing contract #8149 established).
Acceptance Criteria
Out of Scope
- Any DockFlip addon-side change — the addon is realm-correct once routing is.
- The deprecation warning mechanism itself (
worker/Base.mjs#sendMessage), and other no-windowId callers outside the dock namespace (none fire on the observed boot path).
Related
#8149 (windowId migration, prior art), #8366 (registerRemote precedent), #13158 (QT-parity docking epic), #17836 (v13.2 dock rebuild — the code's origin), #17885/#17891 (the client-workspace investigation this fell out of).
Origin Session ID: b51135ac-ec45-4689-ac45-0e99fb073069
Retrieval Hint: "DockFlip windowId first-port routing deprecation"
Context
Booting a SharedWorkers dock workspace (private client repo) prints two warnings in the app worker before any interaction:
sendMessage destination "main" is deprecated. Use a windowId instead.A race-free CDP attach (browser-level auto-attach,waitForDebuggerOnStart) captured the live argument previews: both are remote-method calls withremoteClassName=Neo.main.addon.DockFlip,remoteMethod=captureFirst/play,destination=main.Live latest-open sweep: checked latest 20 open issues at 2026-08-30T22:15Z; no equivalent found. Prior art: #8149 migrated messaging to explicit window ids and introduced this deprecation; #8366 fixed the same class of warning for
registerRemote.The Problem
src/dashboard/dock/Workspace.mjscalls the FLIP addon without awindowId:flip?.captureFirst({hostId: host.id, markerPrefix: flipMarkerPrefix})flip.play({hostId: host.id, markerPrefix: flipMarkerPrefix, geometryOnly: ...})RemoteMethodAccess#generateRemoteswaps the destination todata.windowIdonly when the caller provides it; absent, the destination stays the deprecated'main'string and the SharedWorker port cascade falls through to the last-resort first port (worker/Base.mjs#sendMessageJSDoc).Consequences by topology:
The Architectural Reality
Neo.main.addon.DockFlipis a per-window main-thread addon; its methods operate on THEIR window's DOM and read nowindowIdfrom data (grep receipt: nowindowIdinsrc/main/addon/DockFlip.mjs). The field is pure routing. The exact realm owning the captured markers is the dock host component's window —host.windowId— whichrefreshDockWorkspacealready has in hand.The Fix
Add
windowId: host.windowIdto both payloads inrefreshDockWorkspace(src/dashboard/dock/Workspace.mjs:1587and:1654).Decision Record impact: none (conforms to the routing contract #8149 established).
Acceptance Criteria
windowId: host.windowId; a unit spec on the workspace seam proves the payload shape (stubbedNeo.main.addon.DockFlipcapturing call args).destination "main" is deprecatedwarnings from DockFlip calls — receipt from the CDP instrument or an equivalent browser-plane check.Out of Scope
worker/Base.mjs#sendMessage), and other no-windowId callers outside the dock namespace (none fire on the observed boot path).Related
#8149 (windowId migration, prior art), #8366 (registerRemote precedent), #13158 (QT-parity docking epic), #17836 (v13.2 dock rebuild — the code's origin), #17885/#17891 (the client-workspace investigation this fell out of).
Origin Session ID: b51135ac-ec45-4689-ac45-0e99fb073069 Retrieval Hint: "DockFlip windowId first-port routing deprecation"