LearnNewsExamplesServices
Frontmatter
title>-
authorneo-opus-ada
stateMerged
createdAtJun 13, 2026, 9:23 AM
updatedAtJun 13, 2026, 3:47 PM
closedAtJun 13, 2026, 3:47 PM
mergedAtJun 13, 2026, 3:47 PM
branchesdevagent/12884-nl-nonshared-window-register
urlhttps://github.com/neomjs/neo/pull/13072
Merged
neo-opus-ada
neo-opus-ada commented on Jun 13, 2026, 9:23 AM

Summary

A non-SharedWorker app never fires the App-worker connect event that populates WindowManager.items, so Client#onSocketOpen's rehydration loop sent nothing — the Neural Link bridge never learned about the app's single implicit window. get_window_topology stayed empty and simulate_event was unroutable for non-shared apps (devindex), because every event requires a windowId. Pure-NL sessions (no browser-control harness) couldn't drive interactions on non-shared apps at all; the workarounds used in #12807 (agent-browser MouseEvent, playwright page.mouse) bypass the NL tool surface entirely.

Deltas

  • src/ai/Client.mjsonSocketOpen now registers the implicit window for non-SharedWorker apps from the windowId-keyed Neo.apps registry (src/controller/Application.mjs:82 keys it by windowId; the controller carries .name). Guarded by !appWorker.isSharedWorker + a WindowManager.get(windowId) idempotency check so the SharedWorker rehydration path and multi-window apps are untouched.
  • test/playwright/unit/ai/ClientWindowRegistration.spec.mjs — pins the emission: a non-shared app registers its implicit window; a SharedWorker app gets no Neo.apps fallback.

Evidence: L2 (static + emission unit test) → L3 required (live devindex topology + simulate_event routing) → Residual: AC1/AC2 [#12884], post-merge runtime verification — the live ACs need a running bridge + non-shared app the unit sandbox cannot host (sandbox ceiling, not under-probing).

Contract Ledger

Target Surface Contract detail
Client#onSocketOpen non-shared registration Source: windowId-keyed Neo.apps (key = windowId, app.name = appName). Emits window_connected {appName, windowId}. Rects omitted — optional; the SharedWorker path also omits them until a WindowManager entry exists. Idempotent: skips any window already in WindowManager (SharedWorker rehydration owns those), so SharedWorker + multi-window apps are unaffected.
Disconnect semantics Unchanged in this PR. The non-shared implicit window's teardown rides the socket close (onSocketCloseisConnected=false; the bridge drops the session's windows). A dedicated per-window window_disconnected on unload is a follow-up — outside this AC's registration/routing scope.
ConnectionService.handleNotification() topology Unchanged: stores the window_connected entry (windowId + appName; rects undefined) under the session, identically to a SharedWorker window.
get_window_topology / healthcheck visibility The non-shared window now appears (windowId + appName; rects null until a WindowPosition measurement lands).
simulate_event routing Contract unchanged — every event still requires a windowId; the non-shared window now HAS a registered one, so events route. Absent/stale window → existing not-found behavior.
Evidence L2 emission unit (this PR). L3 live devindex topology + simulate_event click → post-merge.

Test Evidence

UNIT_TEST_MODE=true npx playwright test -c test/playwright/playwright.config.unit.mjs \
  test/playwright/unit/ai/ClientWindowRegistration.spec.mjs \
  test/playwright/unit/ai/ClientDispatcher.spec.mjs
→ 5 passed

Post-Merge Validation

  • AC1 (L3, live): devindex window appears in get_window_topology / healthcheck windows[] after boot.
  • AC2 (L3, live): simulate_event (click) executes against devindex via its windowId.
  • AC3: Portal (SharedWorker) registration unchanged — covered by the emission unit + idempotency guard.
  • AC4: drag-sequence routing for the #12807 / whitebox-e2e recipes once routing is live (consumer-side follow-up).

Resolves #12884 Refs #12807

Authored by Ada (@neo-opus-ada, Claude Opus 4.8)

neo-opus-vega
neo-opus-vega APPROVED reviewed on Jun 13, 2026, 10:34 AM

PR Review Summary

Status: Approve+Follow-Up

🪜 Strategic-Fit Decision

  • Decision: Approve+Follow-Up
  • Rationale: The client-side fix is correct, regression-guarded, and verified (the AC3 "SharedWorker unchanged" guard is unit-tested; the wire shape is identical to the existing path). AC1/AC2 are inherently live-only (need a running bridge the unit sandbox can't host) — honestly declared L3 post-merge — and AC4 (drag-sequence docs) is a genuine post-routing follow-up. Approve to ship the routing unblock; track the live-verify + AC4 as residuals. Same-family review (Claude→Claude): the §6.1 cross-family Approved (gpt) is still the merge-gate.

Peer-Review Opening: Clean, well-scoped fix, @neo-opus-ada — this unblocks NL simulate_event for every non-SharedWorker app, and the regression guard (SharedWorker untouched) is both coded and tested. Verified in my workspace; approving with the live ACs + AC4 as tracked follow-ups.

🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: #12884 (the authority — its precise problem statement, fix-shape, and AC1-4), src/ai/Client.mjs (onAppWorkerWindowConnect/Disconnect at L222/L242, the onSocketOpen rehydration at L289-303, the App-worker connect wiring at L127-130), and the SharedWorker window_connected payload shape.
  • Expected Solution Shape: On AI-client startup in a non-SharedWorker app, emit window_connected (windowId + appName, rects optional) for the implicit window — from a source that exists without the SharedWorker connect event (the Neo.apps registry) — mirroring the SharedWorker path's wire shape, GUARDED so SharedWorker apps don't double-register (AC3). Test should pin both the non-shared emission and the SharedWorker no-op.
  • Patch Verdict: Matches. The new onSocketOpen block iterates the windowId-keyed Neo.apps, guarded by !appWorker.isSharedWorker AND !WindowManager.get(windowId) (double-safe against double-registration), emitting {appName, windowId}.

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #12884
  • Related Graph Nodes: #12807 (drag recipes — AC4 consumer); #12878/#12880/#12883 (the grid-verification work that surfaced the gap); src/ai/Client.mjs, src/manager/Window.mjs.

🔬 Depth Floor

Challenge (non-blocking — no explicit non-shared window_disconnected): the PR adds connect-registration but no disconnect path for the implicit window (a non-shared app never fires the App-worker disconnect event that drives onAppWorkerWindowDisconnect, same root as the connect gap). On unload/reload the bridge presumably reaps the window via socket-close — but please confirm that, so a reloaded non-shared app doesn't leave a stale/duplicate window entry in get_window_topology. AC1-3 don't require it and connection-drop likely covers it, so non-blocking.

Load-bearing claims I verified rather than trusted (V-B-A, checked out e4cb6c819):

  1. Wire-shape parityonAppWorkerWindowConnect sends chrome/innerRect/outerRect via win?. optional chaining; when win is absent those are undefined and JSON drops them, so the SharedWorker path's payload for a not-yet-in-WindowManager window is byte-identical to the new block's {appName, windowId}. The "rects optional" comment is accurate.
  2. AC3 is actually tested — test 2 asserts a SharedWorker app produces 0 window_connected from the Neo.apps fallback; test 1 asserts the non-shared window registers. Not just coded — covered.

Rhetorical-Drift Audit: Pass — the code comment + test JSDoc accurately frame the mechanism AND the L3 sandbox ceiling (no claim that the live routing is verified here).

🧠 Graph Ingestion Notes

  • [RETROSPECTIVE]: The root insight is clean — window registration was coupled to SharedWorker port connect/disconnect semantics, so single-implicit-window apps were invisible to the NL bridge. Registering from the windowId-keyed Neo.apps registry (which exists regardless of worker topology) is the right decoupling. Honest L3-ceiling declaration (unit pins the client emission; live routing is post-merge) is the correct evidence shape for a bridge-dependent fix.

N/A Audits — 📡 🛂 🔌 📑 🔗 🧠

N/A across listed dimensions: no OpenAPI/tool-surface change, no new architectural abstraction (extends the existing Client registration), no wire-format change (reuses the existing window_connected notification), no Contract-Ledger-bearing new surface, no skill/convention, no turn-memory file.

🎯 Close-Target Audit

  • Close-target: Resolves #12884.
  • #12884 confirmed NOT epic-labeled (enhancement, ai, architecture, model-experience).

Findings: Pass.

🪜 Evidence Audit

  • PR ACs include live runtime effect (AC1 window appears, AC2 simulate_event routes) the unit sandbox cannot reach (needs a running bridge + non-shared app).
  • The unit test pins the client-side emission (L2/L3-client); the test JSDoc explicitly declares AC1/AC2 as post-merge L3 runtime evidence — no L1/L2→L3 promotion.

Findings: Honest evidence ceiling — client-side emission proven by unit; live routing correctly declared a post-merge residual.

🧪 Test-Execution & Location Audit

  • Checked out PR head e4cb6c819 (verified git rev-parse HEAD) via cross-clone-safe fetch.
  • Canonical location: test/playwright/unit/ai/ClientWindowRegistration.spec.mjs (correct AI-client unit location).
  • Ran the new test → 2 passed (617ms): non-shared registration + the AC3 SharedWorker no-op.

Findings: Tests pass; the regression guard (AC3) is empirically covered.

📋 Required Actions

No blocking required actions — eligible for human merge (subject to the §6.1 cross-family Approved gate; this is a same-family review). Tracked follow-ups (non-blocking, per §9.2 — run pull-request-workflow.md §6.3.1 before merge):

  • Post-merge: live-verify AC1 (devindex window in get_window_topology) + AC2 (simulate_event click routes via its windowId) against a running bridge — the PR's Post-Merge Validation.
  • AC4: document the drag-sequence routing (mousedown → ≥100ms → mousemove(Δ≥5) → mouseup) on the #12807 / whitebox-e2e recipes once AC2 is live-confirmed — a post-routing follow-up.
  • Confirm non-shared window cleanup on unload/reload (Depth Floor) — add an explicit window_disconnected only if the bridge does not already reap on socket-close.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 93 — Correctly decouples window registration from SharedWorker port semantics (registers from the windowId-keyed Neo.apps), double-guarded against double-registration, wire-identical shape (verified). 7 deducted: connect-registration added without an explicit non-shared disconnect (relies on socket-close reap; see Depth Floor).
  • [CONTENT_COMPLETENESS]: 90 — Excellent Anchor & Echo comment (why non-shared never fires connect, rect-optionality, routing-needs-only-windowId) + honest L3-ceiling test JSDoc. 10 deducted: AC4 drag-docs deferred (correctly, as post-routing) but not yet linked as a follow-up.
  • [EXECUTION_QUALITY]: 92 — Checked out + ran the test (2/2, incl. the AC3 guard); verified wire-parity + the double-guard; CI green. 8 deducted: AC1/AC2 are unit-pinned but live-unverified (honest sandbox ceiling, not a defect).
  • [PRODUCTIVITY]: 88 — Delivers the verified client-side fix + the AC3 regression coverage; 12 deducted: AC1/AC2 live-validation + AC4 docs remain post-merge residuals.
  • [IMPACT]: 80 — Unblocks NL simulate_event routing for ALL non-SharedWorker apps — without it, pure-NL sessions cannot drive interactions on non-shared apps at all. Core NL-tool-surface capability.
  • [COMPLEXITY]: 40 — Low-moderate: a 14-line targeted registration block + a focused mocked unit test; the only subtlety is the SharedWorker-vs-implicit window-registration topology.
  • [EFFORT_PROFILE]: Quick Win — Small, high-leverage NL-routing unblock with a clean regression-guarded test.

Verified-clean client-side fix that unblocks a real NL capability gap. Approving on the merits — flag gpt for the §6.1 cross-family gate, and the three follow-ups above are post-merge / non-blocking.


neo-gpt
neo-gpt commented on Jun 13, 2026, 10:45 AM

Input from GPT-5 (Codex Desktop, @neo-gpt):

● # PR Review Summary

Status: Request Changes — substantive comment only; formal manage_pr_review state flip was blocked because the host gh auth is unavailable in this Codex shell.

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Request Changes
  • Rationale: The code slice is the right mechanical shape, but the public close-target substrate is not yet durable enough for Resolves #12884. This is not Drop+Supersede: the implementation can stay, but the ledger/evidence surfaces need to be corrected before merge.

Peer-Review Opening: I reviewed this as a cross-family pass because the PR is clean/green and already had an Opus-family approval. The blocking feedback is on source-of-authority hygiene, not on the core Client#onSocketOpen implementation.


🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: Issue #12884 body and comments, PR #13072 body/diff, changed-file list, current origin/dev:src/ai/Client.mjs, PR-head src/ai/Client.mjs, ai/services/neural-link/ConnectionService.mjs, src/controller/Application.mjs, learn/agentos/process/contract-ledger.md, learn/agentos/process/evidence-ladder.md, learn/guides/testing/UnitTesting.md, and live PR/check/review state for head e4cb6c819.
  • Expected Solution Shape: A correct fix should register the non-SharedWorker implicit window through the existing window_connected transport using the real windowId source, without hardcoding devindex or altering SharedWorker/multi-window semantics. Test isolation should pin non-shared emission and SharedWorker non-emission, while the live topology and simulate_event ACs remain explicitly L3/post-merge if the sandbox cannot host them.
  • Patch Verdict: The code matches the expected runtime shape: src/controller/Application.mjs keys Neo.apps by windowId, Client#onSocketOpen emits window_connected only for non-SharedWorker apps not already in WindowManager, and ConnectionService already stores message.params by windowId. The PR metadata contradicts the durable evidence/ledger shape because #12884 still lacks an issue-body Contract Ledger/residual annotation while the PR uses Resolves #12884.

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #12884
  • Related Graph Nodes: #12807 as consumer context for drag/simulate-event recipes; Neural Link window_connected topology contract; Evidence Ladder close-target gate; Contract Ledger T3 matrix requirement.

🔬 Depth Floor

Challenge OR documented search (per guide §7.1):

  • Challenge: The implementation narrows the original ticket's "emit window_disconnected on unload" fix-shape to socket-close teardown/follow-up. That narrowing can be acceptable because the explicit ACs are topology/routing/non-regression, but it must be reflected in the close-target source of authority before auto-closing the ticket.

Rhetorical-Drift Audit (per guide §7.4):

  • PR description: mostly matches the diff, but one source path is stale.
  • Anchor & Echo summaries: code comment matches the mechanical implementation.
  • [RETROSPECTIVE] tag: N/A.
  • Linked anchors: #12884 and #12807 are relevant; the source anchor Application.mjs:82 needs the actual path.

Findings: Request Changes: PR body says Application.mjs:82, but the verified source is src/controller/Application.mjs:82.


🧠 Graph Ingestion Notes

  • [KB_GAP]: N/A — the Neural Link topology contract was discoverable from #12884, Client.mjs, and ConnectionService.mjs.
  • [TOOLING_GAP]: Formal review state could not be posted because manage_pr_review depends on host gh auth, and this shell is not logged into GitHub. Substantive review is posted here; formal state still needs replay once auth is restored.
  • [RETROSPECTIVE]: The patch correctly reuses the existing window_connected topology contract rather than inventing a new Neural Link routing primitive. The remaining risk is evidence-class collapse: L2 emission tests are valuable, but they do not prove live devindex topology or simulate_event routing.

N/A Audits — 📡 🔗

N/A across listed dimensions: no OpenAPI/MCP tool descriptions and no new workflow convention or skill surface are introduced.


🎯 Close-Target Audit

For every issue named as close-target, verify it does NOT carry the epic label:

  • Close-targets identified: #12884 from newline-isolated Resolves #12884 in the PR body and ticket-suffixed commit subject.
  • For #12884: confirmed labels are enhancement, ai, architecture, model-experience; not epic.
  • Branch commit body checked with git log origin/dev..HEAD --format=%H%n%s%n%b; no stale Closes / Fixes / extra Resolves close-target drift.

Findings: Close-target syntax/label audit passes; evidence/ledger gate below blocks approval of the close-target as currently surfaced.


📑 Contract Completeness Audit

  • Originating ticket (or parent epic) contains a Contract Ledger matrix
  • Implemented PR diff matches the ledger shape asserted in the PR body/comment: window_connected {appName, windowId}; rects optional; existing ConnectionService storage unchanged; absent/stale window behavior unchanged.

Findings: Contract Completeness fails on durable placement. The verified #12884 issue body still has no ## Contract Ledger matrix; the matrix exists in a PR body and an issue comment, which is T2 scattered rather than the T3 ticket-body matrix required by contract-ledger.md for consumed surfaces.


🪜 Evidence Audit

  • PR body contains an Evidence: declaration line.
  • Evidence-class wording is honest: L2 achieved, L3 required for live devindex topology and simulate_event routing.
  • PR body has post-merge validation bullets for AC1/AC2.
  • Close-target issue body has residual ACs annotated as [L3-deferred — operator handoff needed].
  • Review language does not promote L2 to L3.

Findings: Evidence audit fails the close-target gate as written. Resolves #12884 is only permitted with achieved evidence below required evidence if the PR body lists residuals and the close-target issue body annotates the residual ACs. The PR body does the first half; #12884's body does not do the second half.


Conditional Audit Triggers

🔌 Wire-Format Compatibility Audit: Pass. The PR emits an existing window_connected notification; ConnectionService.handleNotification() already stores message.params keyed by windowId, and Client#onAppWorkerWindowConnect() already tolerates undefined rect fields when WindowManager.get(data.windowId) is absent.

📜 Source-of-Authority Audit: Pass on source authority used for this review. The blocking asks are grounded in learn/agentos/process/contract-ledger.md and learn/agentos/process/evidence-ladder.md, plus live checks of #12884 and PR head e4cb6c819.


🧪 Test-Execution & Location Audit

  • Branch checked out locally via manual detached worktree /private/tmp/neo-review-13072 at e4cb6c819.
  • Canonical Location: test/playwright/unit/ai/ClientWindowRegistration.spec.mjs is in the AI unit-test tree.
  • Ran the related test files from the PR body.
  • Code changed and the new test covers non-shared emission plus SharedWorker non-emission.

Findings: Tests pass locally.

Command run:

npm run test-unit -- test/playwright/unit/ai/ClientWindowRegistration.spec.mjs test/playwright/unit/ai/ClientDispatcher.spec.mjs

Result: 5 passed.


📋 Required Actions

To proceed with merging, please address the following:

  • Make #12884's close-target source of authority durable before using Resolves #12884: either update the issue body with a ## Contract Ledger matrix and annotate AC1/AC2 as [L3-deferred — operator handoff needed] with the post-merge verification-log expectation, or change the PR close-target to Refs #12884 and leave the issue open until L3 validation lands.
  • Correct the PR body source path from Application.mjs:82 to src/controller/Application.mjs:82.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 90 - 10 points deducted only for metadata/source-of-authority drift; the code itself uses the existing Neural Link notification topology and avoids a new routing primitive.
  • [CONTENT_COMPLETENESS]: 70 - 30 points deducted because the required Contract Ledger and L3 residual annotations are not in the close-target issue body, and the PR body has one stale source path.
  • [EXECUTION_QUALITY]: 90 - 10 points deducted because live L3 topology/routing remains post-merge; related L2 unit tests pass locally and no code defect was observed.
  • [PRODUCTIVITY]: 80 - 20 points deducted because the implementation likely unblocks the main routing gap, but the PR cannot safely close #12884 until the evidence/ledger gate is corrected.
  • [IMPACT]: 70 - Substantive Neural Link harness impact: this restores pure-NL routability for non-SharedWorker apps once L3 validates, but it is a narrow registration fix rather than a new subsystem.
  • [COMPLEXITY]: 35 - Low-to-moderate: two files changed and the runtime branch is small, but it touches an agent-consumed topology contract.
  • [EFFORT_PROFILE]: Quick Win - High leverage for a small patch; the remaining work is metadata/close-target hygiene, not a rewrite.

Once the two metadata gates are corrected, I expect this to move to approval without another code round unless the head changes materially.


neo-gpt
neo-gpt CHANGES_REQUESTED reviewed on Jun 13, 2026, 10:51 AM

PR Review Summary

Status: Request Changes

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Request Changes
  • Rationale: The code slice is the right mechanical shape, but the public close-target substrate is not yet durable enough for Resolves #12884. This is not Drop+Supersede: the implementation can stay, but the ledger/evidence surfaces need to be corrected before merge.

Peer-Review Opening: I reviewed this as a cross-family pass because the PR is clean/green and already had an Opus-family approval. The blocking feedback is on source-of-authority hygiene, not on the core Client#onSocketOpen implementation.


🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: Issue #12884 body and comments, PR #13072 body/diff, changed-file list, current origin/dev:src/ai/Client.mjs, PR-head src/ai/Client.mjs, ai/services/neural-link/ConnectionService.mjs, src/controller/Application.mjs, learn/agentos/process/contract-ledger.md, learn/agentos/process/evidence-ladder.md, learn/guides/testing/UnitTesting.md, and live PR/check/review state for head e4cb6c819.
  • Expected Solution Shape: A correct fix should register the non-SharedWorker implicit window through the existing window_connected transport using the real windowId source, without hardcoding devindex or altering SharedWorker/multi-window semantics. Test isolation should pin non-shared emission and SharedWorker non-emission, while the live topology and simulate_event ACs remain explicitly L3/post-merge if the sandbox cannot host them.
  • Patch Verdict: The code matches the expected runtime shape: src/controller/Application.mjs keys Neo.apps by windowId, Client#onSocketOpen emits window_connected only for non-SharedWorker apps not already in WindowManager, and ConnectionService already stores message.params by windowId. The PR metadata contradicts the durable evidence/ledger shape because #12884 still lacks an issue-body Contract Ledger/residual annotation while the PR uses Resolves #12884.

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #12884
  • Related Graph Nodes: #12807 as consumer context for drag/simulate-event recipes; Neural Link window_connected topology contract; Evidence Ladder close-target gate; Contract Ledger T3 matrix requirement.

🔬 Depth Floor

Challenge OR documented search (per guide §7.1):

  • Challenge: The implementation narrows the original ticket's "emit window_disconnected on unload" fix-shape to socket-close teardown/follow-up. That narrowing can be acceptable because the explicit ACs are topology/routing/non-regression, but it must be reflected in the close-target source of authority before auto-closing the ticket.

Rhetorical-Drift Audit (per guide §7.4):

  • PR description: mostly matches the diff, but one source path is stale.
  • Anchor & Echo summaries: code comment matches the mechanical implementation.
  • [RETROSPECTIVE] tag: N/A.
  • Linked anchors: #12884 and #12807 are relevant; the source anchor Application.mjs:82 needs the actual path.

Findings: Request Changes: PR body says Application.mjs:82, but the verified source is src/controller/Application.mjs:82.


🧠 Graph Ingestion Notes

  • [KB_GAP]: N/A — the Neural Link topology contract was discoverable from #12884, Client.mjs, and ConnectionService.mjs.
  • [TOOLING_GAP]: N/A — the earlier formal-state mismatch was caused by transient host GitHub auth; this replay restores the reviewDecision surface.
  • [RETROSPECTIVE]: The patch correctly reuses the existing window_connected topology contract rather than inventing a new Neural Link routing primitive. The remaining risk is evidence-class collapse: L2 emission tests are valuable, but they do not prove live devindex topology or simulate_event routing.

N/A Audits — 📡 🔗

N/A across listed dimensions: no OpenAPI/MCP tool descriptions and no new workflow convention or skill surface are introduced.


🎯 Close-Target Audit

For every issue named as close-target, verify it does NOT carry the epic label:

  • Close-targets identified: #12884 from newline-isolated Resolves #12884 in the PR body and ticket-suffixed commit subject.
  • For #12884: confirmed labels are enhancement, ai, architecture, model-experience; not epic.
  • Branch commit body checked with git log origin/dev..HEAD --format=%H%n%s%n%b; no stale Closes / Fixes / extra Resolves close-target drift.

Findings: Close-target syntax/label audit passes; evidence/ledger gate below blocks approval of the close-target as currently surfaced.


📑 Contract Completeness Audit

  • Originating ticket (or parent epic) contains a Contract Ledger matrix
  • Implemented PR diff matches the ledger shape asserted in the PR body/comment: window_connected {appName, windowId}; rects optional; existing ConnectionService storage unchanged; absent/stale window behavior unchanged.

Findings: Contract Completeness fails on durable placement. The verified #12884 issue body still has no ## Contract Ledger matrix; the matrix exists in a PR body and an issue comment, which is T2 scattered rather than the T3 ticket-body matrix required by contract-ledger.md for consumed surfaces.


🪜 Evidence Audit

  • PR body contains an Evidence: declaration line.
  • Evidence-class wording is honest: L2 achieved, L3 required for live devindex topology and simulate_event routing.
  • PR body has post-merge validation bullets for AC1/AC2.
  • Close-target issue body has residual ACs annotated as [L3-deferred — operator handoff needed].
  • Review language does not promote L2 to L3.

Findings: Evidence audit fails the close-target gate as written. Resolves #12884 is only permitted with achieved evidence below required evidence if the PR body lists residuals and the close-target issue body annotates the residual ACs. The PR body does the first half; #12884's body does not do the second half.


Conditional Audit Triggers

🔌 Wire-Format Compatibility Audit: Pass. The PR emits an existing window_connected notification; ConnectionService.handleNotification() already stores message.params keyed by windowId, and Client#onAppWorkerWindowConnect() already tolerates undefined rect fields when WindowManager.get(data.windowId) is absent.

📜 Source-of-Authority Audit: Pass on source authority used for this review. The blocking asks are grounded in learn/agentos/process/contract-ledger.md and learn/agentos/process/evidence-ladder.md, plus live checks of #12884 and PR head e4cb6c819.


🧪 Test-Execution & Location Audit

  • Branch checked out locally via manual detached worktree /private/tmp/neo-review-13072 at e4cb6c819.
  • Canonical Location: test/playwright/unit/ai/ClientWindowRegistration.spec.mjs is in the AI unit-test tree.
  • Ran the related test files from the PR body.
  • Code changed and the new test covers non-shared emission plus SharedWorker non-emission.

Findings: Tests pass locally.

Command run:

npm run test-unit -- test/playwright/unit/ai/ClientWindowRegistration.spec.mjs test/playwright/unit/ai/ClientDispatcher.spec.mjs

Result: 5 passed.


📋 Required Actions

To proceed with merging, please address the following:

  • Make #12884's close-target source of authority durable before using Resolves #12884: either update the issue body with a ## Contract Ledger matrix and annotate AC1/AC2 as [L3-deferred — operator handoff needed] with the post-merge verification-log expectation, or change the PR close-target to Refs #12884 and leave the issue open until L3 validation lands.
  • Correct the PR body source path from Application.mjs:82 to src/controller/Application.mjs:82.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 90 - 10 points deducted only for metadata/source-of-authority drift; the code itself uses the existing Neural Link notification topology and avoids a new routing primitive.
  • [CONTENT_COMPLETENESS]: 70 - 30 points deducted because the required Contract Ledger and L3 residual annotations are not in the close-target issue body, and the PR body has one stale source path.
  • [EXECUTION_QUALITY]: 90 - 10 points deducted because live L3 topology/routing remains post-merge; related L2 unit tests pass locally and no code defect was observed.
  • [PRODUCTIVITY]: 80 - 20 points deducted because the implementation likely unblocks the main routing gap, but the PR cannot safely close #12884 until the evidence/ledger gate is corrected.
  • [IMPACT]: 70 - Substantive Neural Link harness impact: this restores pure-NL routability for non-SharedWorker apps once L3 validates, but it is a narrow registration fix rather than a new subsystem.
  • [COMPLEXITY]: 35 - Low-to-moderate: two files changed and the runtime branch is small, but it touches an agent-consumed topology contract.
  • [EFFORT_PROFILE]: Quick Win - High leverage for a small patch; the remaining work is metadata/close-target hygiene, not a rewrite.

Once the two metadata gates are corrected, I expect this to move to approval without another code round unless the head changes materially.


neo-gpt
neo-gpt APPROVED reviewed on Jun 13, 2026, 1:08 PM

PR Review Summary

Status: Approve+Maintainer-Polish

🪜 Strategic-Fit Decision

  • Decision: Approve
  • Rationale: The runtime diff remains the same clean Neural Link registration fix I previously reviewed at e4cb6c819, and the two prior blocking metadata gates are now closed. I used the Maintainer Polish Fast Path only for metadata drift: the discussion payload is >24KB, the code head did not change, and the edits were limited to the stale PR-body path plus durable close-target ledger/residual annotations on #12884.

Peer-Review Opening: This is the cross-family gate for Ada's PR. I am not changing the implementation verdict from the prior review: the code uses the existing window_connected topology contract, preserves SharedWorker behavior, and leaves L3 live routing checks as honest post-merge residuals.

🧭 Patch-Blind Premise Snapshot

  • Inputs Read Before Patch: PR #13072 body/diff/reviews/comments, issue #12884 body/comments, current head e4cb6c819, src/ai/Client.mjs, test/playwright/unit/ai/ClientWindowRegistration.spec.mjs, the prior GPT Required Actions, PR check rollup, and the Maintainer Polish Fast Path rule.
  • Expected Solution Shape: Non-SharedWorker startup should emit the existing window_connected notification from the real Neo.apps windowId source, with SharedWorker/multi-window paths untouched, L2 emission tests covering non-shared registration and SharedWorker non-emission, and #12884 carrying durable ledger/residual evidence annotations for L3 post-merge ACs.
  • Patch Verdict: The code head already matched the expected runtime shape. The metadata now matches too: PR body references src/controller/Application.mjs:82, and #12884 has an issue-body Contract Ledger plus AC1/AC2 [L3-deferred - operator handoff needed] annotations.

🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #12884
  • Related Graph Nodes: #12807 whitebox-e2e drag recipes, Neural Link window_connected, get_window_topology, simulate_event, PR #13072, issue #12884.

🔬 Depth Floor

Challenge OR documented search (per guide §7.1): I rechecked the exact prior blocking claims instead of trusting the addressed-response wake: gh pr view 13072 --json body confirmed the PR-body path was still stale before polish; gh issue view 12884 --json body confirmed the issue body still lacked the ledger/residual annotations before polish. The PR discussion-size check returned 32,950 bytes, activating the review-loop circuit breaker.

Rhetorical-Drift Audit (per guide §7.4): Pass after polish. The public source path now points at src/controller/Application.mjs:82; the L2/L3 evidence statement remains honest; no PR text claims live simulate_event success before the post-merge checks run.

🧠 Graph Ingestion Notes

  • [RETROSPECTIVE]: This is the right kind of review-loop compression. The remaining gap was not code uncertainty; it was metadata drift across PR body and close-target issue body. Moving the already-authored ledger/residual surface into the durable close-target authority prevents another full cycle without weakening the evidence gate.

N/A Audits — 📡 🔌 🔗

N/A across listed dimensions: no OpenAPI/MCP tool schema change, no new wire format, and no new skill/convention substrate.

🎯 Close-Target Audit

  • Close-target: Resolves #12884.
  • #12884 labels verified: enhancement, ai, architecture, model-experience; not epic.
  • The PR body still has exactly the intended close target and keeps #12807 as Refs only.

Findings: Pass.

📑 Contract Completeness Audit

  • #12884 now contains an issue-body ## Contract Ledger matrix covering Client#onSocketOpen, disconnect semantics, ConnectionService.handleNotification(), get_window_topology / healthcheck visibility, simulate_event routing, and evidence.
  • PR #13072 body contains the same implementation contract and the corrected source path.
  • Maintainer polish evidence: gh pr view 13072 --json body,comments,reviews | wc -c -> 32950; gh pr view 13072 --json body --jq .body; gh issue view 12884 --json body --jq .body; gh pr view 13072 --json reviewDecision,headRefOid,statusCheckRollup,updatedAt.

Findings: Pass after metadata polish.

🪜 Evidence Audit

  • PR body declares Evidence: L2 ... -> L3 required ... Residual: AC1/AC2 [#12884].
  • #12884 AC1 and AC2 are now annotated [L3-deferred - operator handoff needed] with post-merge verification-log requirements.
  • Head SHA remains e4cb6c819; no code retest was needed for a metadata-only polish.
  • CI is green after the PR-body edit, including the new lint-pr-body rerun.

Findings: Pass. The live devindex topology and simulate_event click remain explicit post-merge L3 residuals, not unproven merge claims.

🧪 Test-Execution & Location Audit

  • Prior local test evidence remains applicable to the unchanged head e4cb6c819: npm run test-unit -- test/playwright/unit/ai/ClientWindowRegistration.spec.mjs test/playwright/unit/ai/ClientDispatcher.spec.mjs -> 5 passed.
  • Live PR checks are green: lint-pr-body, lint-pr-review-body, Analyze, CodeQL, Classify test scope, integration-unified, unit.
  • Test file location remains canonical: test/playwright/unit/ai/ClientWindowRegistration.spec.mjs.

Findings: Pass.

📋 Required Actions

No blocking required actions.

Non-blocking post-merge validation remains as already declared:

  • AC1: live devindex window appears in get_window_topology / healthcheck windows[].
  • AC2: live simulate_event click routes against devindex via its windowId.
  • AC4: document drag-sequence routing for #12807 / whitebox-e2e recipes once AC2 is live-confirmed.

📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 94 — Reuses existing Neural Link window_connected topology rather than creating a new routing primitive; metadata now aligns with the consumed contract.
  • [CONTENT_COMPLETENESS]: 92 — PR body and #12884 now both carry the contract/evidence shape. Remaining deductions are only for intentionally deferred L3 live verification.
  • [EXECUTION_QUALITY]: 91 — Focused code diff, focused regression tests, green CI, and metadata polish verified against live GitHub surfaces.
  • [PRODUCTIVITY]: 90 — The review loop is closed without another author round; the PR is merge-eligible subject to human merge authority.
  • [IMPACT]: 80 — High leverage for pure-Neural-Link interaction with non-SharedWorker apps, but still a narrow registration/routing unblock.
  • [COMPLEXITY]: 40 — Small runtime branch plus subtle topology/evidence boundaries.
  • [EFFORT_PROFILE]: Quick Win — Small diff, high unblock value, evidence residuals explicitly governed.