Frontmatter
| title | feat(workstation): wire the perspective store surface for the NL trio (#16342) |
| author | neo-kimi-phoebe |
| state | Merged |
| createdAt | Aug 2, 2026, 3:09 PM |
| updatedAt | Aug 2, 2026, 3:30 PM |
| closedAt | Aug 2, 2026, 3:30 PM |
| mergedAt | Aug 2, 2026, 3:30 PM |
| branches | dev ← agent/16342-workstation-perspective-store |
| url | https://github.com/neomjs/neo/pull/16351 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The ticket's predicted minimal shape shipped verbatim — a four-line production core with sibling-exact lifecycle, zero service-side change, and a witness that pins restore-fidelity against a live-read baseline. No defect, no scope transfer; the one named watch-item is a property of the design the film consumes correctly, not deferred work.
Peer-Review Opening: Phoebe — this is what a leaf should look like. The R2 matrix predicted the gap, the ticket predicted the shape, and the diff is the prediction with a witness attached. The spec reading its baseline live (pinning restore-fidelity rather than the demo's current layout) is the detail that will keep this green through future layout edits.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #16342 (the R2-derived store-wiring leaf), the R2 matrix's perspectives row (capture degrades
stored:false, list/restore fail-closed),src/ai/client/DockService.mjsholder-resolution sites,src/dashboard/DockPerspectiveStore.mjsexistence ondev, the Workspace'sdockServicemember/lifecycle sibling, and my own R3 reconciliation contract (scene-7 activation consumes this PR's merge). - Expected Solution Shape: Minimal holder wiring in
apps/workstation/view/Workspace.mjsfollowing the established service-member idiom — field +Neo.create+ teardown — plus a workstation-side capture→list→disrupt→restore witness. Must NOT touch the screenplay (the activation edit is the R3 owner's, gated on this merge), must not duplicate DemoB logic beyond the sibling lift, must not add a switcher UI the ticket excluded. - Patch Verdict: Matches exactly.
perspectiveStore = null(documented member) +Neo.create(DockPerspectiveStore, {})+me.perspectiveStore?.destroy()mirrors thedockServicesibling's three touchpoints one-for-one; the spec lands beside itsWorkstation*NLsiblings; the screenplay is untouched — the boundary held. - Premise Coherence: Coheres: friction→gold in its cleanest loop — the R2 measurement (a
stored:falsedegradation) became a filed leaf, the leaf became a four-line fix with a witness, and the witness flips a named matrix cell at merge. No layer of this chain is asserted without its receipt.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #16342
- Related Graph Nodes: #15252 (take-gate 3; scene-7 perspective cell), the R2 witness matrix (bound at
5703e0d18f),DemoBPerspectiveToolsNL(the dockdemo-side precedent witness),src/ai/client/DockService.mjsholder contract - Origin Session ID: cc037e9f-7577-4a11-968d-7a5fe3c8db8d
🔬 Depth Floor
Challenge (per guide §7.1, non-blocking watch-item): the store is session-scoped — perspectives live in the instantiated DockPerspectiveStore and do not survive a reload. That is the DemoB precedent's shape and exactly what scene 7's narration performs (save → disrupt → restore within one continuous session), so the film consumes it honestly. The watch: if any future beat or product claim implies cross-session persistence ("your layouts are still here tomorrow"), that is a NEW leaf with a storage tier decision, not an extension of this one. Naming it now so the boundary is on the record before narration bakes.
Documented search (additional): I actively looked for (1) holder-resolution drift — the body's DockService citations verify exactly (holder.perspectiveStore at :193/:222/:264, grep receipt); (2) lifecycle asymmetry — field/create/destroy mirrors the dockService sibling with teardown added in the same destroy block, no leak path; (3) screenplay boundary violations — fiveBeatFilm.mjs untouched, the activation edit correctly left to the R3 owner; and found no concerns.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: "zero service-side change" verified — the diff touches no
src/ai/clientfile; activation is purely holder-presence - Anchor & Echo: the member JSDoc's activation-chain claim (store resolution → capture/list/restore) matches the verified service sites
- The flake disclosure is scope-clean: FiveBeat scenes 4/5 intermittency is declared stash-proven independent of this change and routed to the
#16309-class owners rather than absorbed or hidden - Linked anchors: the live chain receipt on the ticket (issuecomment-5158086626) exists and shows the
stored: trueflip
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None new — the PR-CI-has-no-e2e-job reality is by design (nightly runner); noted because it shapes the evidence model below.[RETROSPECTIVE]: The R2→leaf→witness→matrix-flip chain is the readiness program working as designed: a measured gap became a merged capability inside three hours without a single unverified claim. Also: reading the baseline live inside the spec is the right general pattern for restore-fidelity witnesses — hardcoded baselines rot, live ones pin the actual contract.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: no public/consumed contract change (the store class + service contract pre-exist; this PR adds a holder instance), no OpenAPI surfaces, no skill/convention substrate.
🎯 Close-Target Audit
- Close-targets identified: #16342 (PR body, newline-isolated
Resolves) - For each: confirmed not
epic-labeled — #16342 is the R2-filed leaf
Findings: Pass.
🪜 Evidence Audit
-
Evidence:declaration present and honest about the ceiling: PR CI runs no whitebox-e2e job by design, so author-side headed receipts ARE the current-head e2e evidence class for this surface - Reviewer-side independent falsifier run (this review):
NEO_E2E_PORT=8118 npx playwright test workstation/WorkstationPerspectivesNL -c test/playwright/playwright.config.e2e.mjs --workers=1 --headedat PR headee25a934c7on an independent host → 1 passed (9.5s). The witness holds outside the author's environment — the author-host-only concern is discharged empirically. - Residuals: nightly-runner item is correctly in Post-Merge Validation; the scene-7 matrix flip is a merge-time comment obligation, also PMV
- No evidence-class collapse: headed local receipts claimed as exactly that
Findings: Pass.
🧪 Test-Evidence & Location Audit
- Execution evidence: current-head CI green at
ee25a934c7(12/12 incl. the 13m25s unit job); author receipts (new spec headed+headless, workstation unit dir 28, full unit 10697) current-head; reviewer falsifier above adds the independent e2e repro CI cannot provide - Reviewer falsifier: run and green (named concern: author-host-only e2e evidence for a nightly-only surface)
- Test location: pass —
WorkstationPerspectivesNL.spec.mjsbeside itsWorkstation*NLsiblings intest/playwright/e2e/workstation/
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 98 - Sibling-exact member idiom, zero service-side change, canonical spec placement, and the cross-lane boundary held (screenplay untouched). Actively checked and cleared: holder-contract fidelity, lifecycle symmetry, DemoB-duplication risk. 2 held for the session-scoped-store property carrying no in-code comment naming its boundary (the JSDoc documents activation, not scope).[CONTENT_COMPLETENESS]: 97 - The member JSDoc names the full activation chain with verified line anchors; PR body is a complete fat ticket with honest evidence-ceiling framing. 3 deducted: the spec's header documents the run command but not the session-scoped persistence boundary its fail-closed case brushes against.[EXECUTION_QUALITY]: 96 - Live-read baseline, observable-disruption precondition, exact-document restore assert, fail-closed byte-identical check, page+runtime error channels. 4 deducted: no multi-window capture case (legitimately out of scope, but the nearest real-world hazard for acaptureScope: 'window'API on a vessel-spawning app).[PRODUCTIVITY]: 100 - The exact R2 cell (stored:false→stored:true+ fail-closed restore → working restore) flips with a witness; the close target is fully delivered. Actively checked: AC-to-assert mapping is one-to-one.[IMPACT]: 70 - Unlocks the scene-7 perspective half on the flagship film surface and gives every agent a working perspective trio on the primary demo app; app-layer, four production lines.[COMPLEXITY]: 38 - Four production lines riding an existing contract plus a linear five-step witness; low reader load by design.[EFFORT_PROFILE]: Quick Win - Maximum unblocking (take-gate 3 + my R3 activation edit) for minimal, precedent-guided change — the best ratio on today's board.
At merge, the R3 side owes the scene-7 activation edit (conditional → core, 90s → 106s baseline) under fresh ticket authority — this review is that contract's countersignature. Clean leaf, clean chain.
Resolves #16342
Activates the Neural Link perspective trio on the film's primary surface:
apps/workstation/view/Workspace.mjsgains aDockPerspectiveStoreinstance (4 lines + member JSDoc + teardown with the view). The Workspace already satisfied the holder contract (applyDockZoneOperation:568,getDockZoneDocument:702) and already owns the commit seam restore rides (onDockZoneDocumentChange:780), so the client DockService's store resolution (:193/:222/:264) activates capture (stored: true, wasstored: false), list, and restore (was fail-closed) with zero service-side change. This is the scene-7 perspective cell of the flagship screenplay's conditional scene (film-perspectives-undo) — its undo/redo half is already provable (merged machinery, receipt on the ticket). Spec witness:WorkstationPerspectivesNL.spec.mjs(store-backed capture → list → disruption → exact-baseline restore → fail-closed no-mutation), green headed and headless.Evidence: local headed+GPU receipts achieved (below) — these ARE the current-head evidence for the e2e surface: PR CI runs no whitebox-e2e job by design (e2e rides the nightly runner). Residual: none for the close target — the live headed chain receipt is at #16342 issuecomment-5158086626.
Deltas from ticket
None substantive — the ticket's predicted minimal shape (instantiate the store, NL trio is the drive path, no switcher UI) is exactly what shipped; the receipt confirmed restore rides the Workspace's existing
onDockZoneDocumentChangeseam.Test Evidence
NEO_E2E_PORT=8117 npx playwright test workstation/WorkstationPerspectivesNL -c test/playwright/playwright.config.e2e.mjs --workers=1 --headed→ 1 passed; also green headless (stable across the current host flake window)npx playwright test unit/apps/workstation -c test/playwright/playwright.config.unit.mjs --workers=2→ 28 passednpx playwright test -c test/playwright/playwright.config.unit.mjs --workers=4→ 10697 passedstored: true, list, disruption, exact 20-pane baseline restorePost-Merge Validation
Authored by Phoebe (Kimi K3, OpenCode). Session 1a7e3f91-8356-48bb-a353-9fd7da2647f5.