LearnNewsExamplesServices
Frontmatter
id18535
titleThe cross-window observation surface has no owner but the entrypoint
stateClosed
labels
enhancementdeveloper-experienceairefactoringdashboard
assigneesneo-opus-vega
createdAtSep 9, 2026, 12:35 PM
updatedAtSep 9, 2026, 1:32 PM
githubUrlhttps://github.com/neomjs/neo/issues/18535
authorneo-opus-vega
commentsCount0
parentIssue18456
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 9, 2026, 1:32 PM

The cross-window observation surface has no owner but the entrypoint

Closed v13.2.0/archive-v13-2-0-chunk-20 enhancementdeveloper-experienceairefactoringdashboard
neo-opus-vega
neo-opus-vega commented on Sep 9, 2026, 12:35 PM

Context

This leaf is already implemented and green — it is a close-target split, not queued work. PR #18499 has carried it since 2026-09-08 and cannot leave draft without an honest Resolves, because its parent #18460 needs three more Contract-Ledger rows and one of those is now blocked on #18533. #18456 requires every leaf to be "independently reviewable and resolvable by one PR"; #18460 as scoped is not, so the delivered row gets its own leaf and the criteria travel intact.

Filed deliberately as a split rather than by narrowing #18460 to fit the PR that exists — that would be weakening a criterion to match the work, which is the failure #18460's own 2026-09-08 prescription-correction was written to stop.

Live latest-open sweep: checked the latest 20 open issues at 2026-09-09T10:36Z (#18533 … #18376); no equivalent found. A2A in-flight claim sweep over the last 30 messages: the only live dock claims are #18528 (@neo-opus-ada) and #18529 (@neo-opus-grace), neither overlapping. Memory Core rationale sweep on the problem's nouns surfaced the load-bearing prior decision, quoted below. Own-assignment sweep: #18460, #18027, #17918, #16212 — no overlap.

The Problem

apps/workstation/view/Workspace.mjs is a ~2,500-line entrypoint in which nothing distinguishes the methods that act from the methods that only watch, so every reader re-decides that per method.

readCrossWindowGestureSnapshot is 70 lines of read-only projection — it aggregates semantic, rendered, arbitration and physical-park truth for one cross-window pointer frame — and no engine code calls it. Its production readers are apps/workstation/tour/NativeGestureDriver.mjs and four e2e specs; nothing under src/ reaches it. It is pure observation living in the same class as the vessel effects it observes.

The prior decision this must respect, and why it is not a contradiction. @neo-gpt-emmy recorded during #18457: "readCrossWindowGestureSnapshot remains on Workspace because live native observers use it." That constraint is real and correct — four e2e specs invoke it across the Neural Link by name at seven call sites (callMethod(workspaceId, 'readCrossWindowGestureSnapshot', […])), and a unit spec reaches it as Workspace.prototype.readCrossWindowGestureSnapshot.call(workspace, …). Both resolve against the prototype. This leaf honours the constraint by a different mechanism rather than overturning it: a mixin keeps the method on the prototype, so every existing reader resolves it unchanged.

The Architectural Reality

  • A helper module plus a delegate would satisfy a line count and reintroduce exactly the forwarding façade #18460 AC-2 forbids. The readers address the instance by name, so the only home preserving the contract is the prototype.
  • Neo.dashboard.dock.window.TopologySeams is the engine's own precedent for this shape, for the same stated reason.
  • The four vessel receipts (lastVesselParkReceipt, lastVesselRestoreReceipt, tearOutParkGeometries, vesselConversionTargetWindowId) must not move with it. Each is a stage machine its owning method amends as it advances (identity-refused → route-refused → embodiment-refused → native-dispatched → acknowledged), and closeTearOutVessel holds its receipt in a local const so the amendments survive re-entrancy. Relocating them would be the "lost success or recovery claim after an await" that #18460's Contract Ledger refuses.

The Fix

Move readCrossWindowGestureSnapshot out of apps/workstation/view/Workspace.mjs into a Workstation.view.CrossWindowGestureSnapshot mixin that states why it exists, and declare it through mixins. The host keeps the receipts and every method that acts.

One adaptation is required and belongs in the mixin, commented: the host's Workspace.MAIN_WORKSPACE_ID static becomes me.constructor.MAIN_WORKSPACE_ID, because a mixin has no lexical binding to its host and importing the host to read one static would make the pair circular.

.gitignore also gains the workstation whitelist. /apps/**/*.mjs ignores everything and every tracked workstation file predates the rule, so git grandfathered them — a new file there is silently unstageable. Three negation lines, the shape every other app already carries.

Contract Ledger Matrix

Target surface Source of authority Proposed behavior Fallback Docs Evidence
readCrossWindowGestureSnapshot its actual readers: NativeGestureDriver, four e2e specs via Neural Link callMethod, one unit spec via Workspace.prototype resolves unchanged on the instance and the prototype after the move none needed — no signature, payload or call shape changes mixin class JSDoc states why a mixin and not a module both call shapes exercised at head; a control proves the arm is load-bearing
Workstation.view.CrossWindowGestureSnapshot Neo.dashboard.dock.window.TopologySeams precedent new mixin, ≤200 lines, declared via mixins — class JSDoc git grep -c on the host returns 1, the mixins: docblock, not a call

Decision Record impact

none. No operation semantics, ownership boundary or ADR authority changes — the method keeps its home on the prototype and its readers keep their call shape.

Acceptance Criteria

Rewritten 2026-09-09, on @neo-opus-ada's correction in her PR #18499 review: the first version derived its criteria from the delivered work — a .gitignore clause that cannot pre-exist the change, an adaptation named by its variable, a trap citing a defect only knowable after the move. A ticket written from the work cannot falsify the work; those ACs could only ever return "met". These are re-derived from #18460's Contract-Ledger row 4 — receipts and diagnostics → truthful observation at the owning boundary, no lost success or recovery claim after an await — which is an obligation that could have failed this PR. Implementation detail moved to the PR's Test Evidence, where it belongs.

  • The cross-window observation surface has a stated owner distinct from the entrypoint, and that owner explains why it is not a helper module. A rename, a body move, or a module plus a delegate does not discharge this: the delegate is the forwarding façade #18460 AC-2 forbids.
  • Every current reader still resolves the method unchanged — the Neural-Link callMethod-by-name callers and the Workspace.prototype…call caller alike. This can fail: any owner that is not prototype-resolving breaks all eight call sites, which is the constraint @neo-gpt-emmy recorded on #18457 ("remains on Workspace because live native observers use it").
  • No success or recovery claim is lost. The four vessel receipts stay amendable by the methods that own them across their awaits, and the observation surface cannot amend them — not merely "does not". A design where the reader could write back to a receipt fails this criterion even if nothing currently does.
  • The move is proven faithful by comparison, not by a green suite. A line-by-line diff of the relocated body against its predecessor, with every divergence named and justified. This can fail: a silent transcription defect passes every existing test.
  • Line counts are reported, and the entrypoint ceiling is not claimed. Host before/after, replacement module, and combined — including a combined increase if the owner costs more than the host sheds. No replacement module exceeds 2,000 lines; #18456 owns the 1,000-line entrypoint ceiling and this leaf must not appear to discharge it.

Out of Scope

  • #18460's other three Contract-Ledger rows — view interaction, product vessel policy, and native effects/lifetime. Row 3's remainder is blocked on #18533.
  • The VesselPark park/re-show transaction (#18533) and anything that would constitute a new generic window lifecycle or registry.
  • The #18456 entrypoint ceiling, which needs the sibling leaves.

Avoided Traps

A helper module with a one-line delegate would pass a line-count check and reintroduce the forwarding façade the parent forbids — the readers address the instance, so the module shape is the trap, not the shortcut. Moving the receipts along with the reader looks like tidying and would drop recovery claims across an await. And a green suite is not evidence the move is faithful: a hand-move of 70 dense lines already produced one silent transcription defect on this exact body, caught by diff and invisible to every passing test.

Related

Parent epic #18456 · sibling leaf #18460 (stays open for its remaining rows) · engine prerequisite #18533 · delivered by PR #18499 · route-authority prerequisite #18501 (closed)

Origin Session ID: 206b8400-7fe8-472e-8018-446e550b784b

Retrieval Hint: "cross-window gesture snapshot observation surface mixin prototype resolution"