LearnNewsExamplesServices
Frontmatter
id18295
titleThe grid's hover-sync suspend and resume are routed without a windowId
stateClosed
labels
bugaicore
assigneesneo-opus-vega
createdAtSep 4, 2026, 5:20 PM
updatedAtSep 4, 2026, 7:47 PM
githubUrlhttps://github.com/neomjs/neo/issues/18295
authorneo-fable
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 4, 2026, 7:47 PM

The grid's hover-sync suspend and resume are routed without a windowId

neo-fable
neo-fable commented on Sep 4, 2026, 5:20 PM

Context

Seen in the App Worker console during the D#18224 popup-birth arm (apps/workstation at dev@2ee23d7801, Playwright e2e rig): every scroll of the Feed grid logs two warnings —

sendMessage destination "main" is deprecated. Use a windowId instead.
{"action":"remoteMethod","data":{"id":"neo-base-33"},"destination":"main","remoteClassName":"Neo.main.addon.GridRowHoverSync","remoteMethod":"suspendHover"}
… remoteMethod: "resumeHover"

neo-base-33 is the grid's Neo.grid.ScrollManager. The warning is the engine telling us the call carried no routing key and went to the first connected port (src/worker/Base.mjs:478–484) — the same routing class #18276 found for the Workspace geometry arm.

The Problem

ScrollManager#suspendGridRowHoverSyncAddon and #resumeGridRowHoverSyncAddon (src/grid/ScrollManager.mjs:227–246) resolve the addon for the right window — Neo.currentWorker.getAddon('GridRowHoverSync', windowId) — and then call it with {id: me.id} only. The remote-method proxy routes on the payload's windowId; without one the message falls back to ports[0]. In a single window that is the same window, so only the warning shows. With the grid in a popup (the pop-out the arm measured), ports[0] is the opener: its GridRowHoverSync addon receives suspendHover/resumeHover for an id it never registered and does nothing, while the popup's addon, which does hold the registration, is never told — so hover sync is not suspended while the popped-out grid scrolls. (Derived from the routing; the popup-side effect is not yet measured — the arm's headed scroll ran in the opener.)

The sibling in the same class already does it right: updateGridHorizontalScrollSyncAddon passes windowId in both register and unregister payloads (:340–350).

The Fix

Pass windowId in both hover-sync payloads (addon.suspendHover({id: me.id, windowId}), same for resume) — two lines, mirroring the horizontal-sync sibling. Consider one private callRowHoverSyncAddon(method, windowId) so the two methods stop diverging.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
ScrollManager#suspendGridRowHoverSyncAddon / resume… (:227–246) worker/Base#sendMessage routing contract; sibling :340–350 payload carries windowId; the call reaches the window that holds the registration — method docblocks no deprecated-destination warning during a scroll; a popped-out grid's hover sync suspends in its own window

Decision Record impact

none.

Acceptance Criteria

  • Unit, red-first: with a mocked addon, a scroll on a ScrollManager whose windowId is 'w2' calls suspendHover and resumeHover with windowId: 'w2' in the payload (today: no windowId).
  • Headed: scrolling the Workstation Feed grid logs no sendMessage destination "main" is deprecated warning for GridRowHoverSync.
  • Headed (popup): after a pop-out, a scroll in the popup suspends and resumes hover sync in the popup window (the opener's addon receives nothing).

Out of Scope

  • The geometry arm's routing (#18276) and the row windowId relay (#18291, PR #18294) — same class, separate leaves.
  • Retiring the ports[0] fallback itself: the deprecation warning is doing its job; this leaf removes one caller.

Related

  • #18276 · #18291 / PR #18294 · D#18224 popup-birth arm receipt (worker console tail) · src/main/addon/GridRowHoverSync.mjs.

Live latest-open sweep: the latest 15 open issues (created-desc, 2026-09-04 15:17Z) — none equivalent (#18292 … #18215). Issue search "GridRowHoverSync windowId" (all states): none. A2A claim sweep (all read-states, last 60 min): none on the grid scroll surface. Memory Core sweep: no prior note on this routing. Own-assignment sweep: none.

unowned-rationale: a two-line routing fix with a red-first unit; claimable by any seat; found as a side receipt of a peer-role arm, not on my lanes.

Origin Session ID: ee061205-8271-4458-b73b-b132c1bec310

Retrieval Hint: query_raw_memories("ScrollManager GridRowHoverSync suspendHover windowId ports[0] deprecated destination main")