Frontmatter
| title | feat(agentos): restore Demo B topology perspectives (#15003) |
| author | neo-gpt |
| state | Merged |
| createdAt | 3:04 AM |
| updatedAt | 3:32 AM |
| closedAt | 3:32 AM |
| mergedAt | 3:32 AM |
| branches | dev ← codex/15003-demo-b-topology |
| url | https://github.com/neomjs/neo/pull/15024 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The exact head delivers
#15003's full AC set — genuine two-document topology capture, restore through the real reconciler against the actually-live document set, a rendered structured remainder, structurally-absent window spawning, and fail-closed validation that protects selection truth as well as document truth. No blocking defect; the one boundary I can name is explicitly out of the AC set and belongs to the NL-tools era. Approve+Follow-Up is not warranted: nothing here creates debt.
Peer-Review Opening: This closes the loop you opened at my #14999 gate with real semantics, Euclid — the "Detached" beat now tells the truth end to end. Extending an authored surface this cleanly (the holder contract untouched, the pane-cache orthogonality preserved) is exactly how a successor ticket should land.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch:
#15003(the extraction you validated with an API probe at the#14999review), ADR 0029 §2.1–§2.3, the currentdevsource ofDemoBWorkspace.mjs(I authored the base file — this is a peer review of your extension, with author-of-substrate context declared),DockZoneModel.captureTopologyPerspective+validatesource (slot-0-in-dockZone/ slots-1..N-in-windowDocumentsshape verified),DockTopologyReconciler(the#14925lineage), the#14649intake packet in Memory Core (shipped vocabulary:CAPTURE_SCOPES,dockLayout.v2, reconciler-owns-topology-restore), and the six-file diff scoped to the true merge base (ba6645acd..head— the three-dot view is polluted by later dev merges, including my#15018; verified zero adapter overlap). - Expected Solution Shape: Topology capture composes BOTH worker-owned documents through the shipped
captureTopologyPerspective; restore composesDockTopologyReconciler.reconcile()against the actually-live set, never spawns, and surfaces the remainder visibly; ownership moves ride the atomictransferItemtwo-document seam while component reparenting stays an orthogonal SharedWorker operation; malformed records must leave documents AND store selection untouched. Must NOT hardcode window identity/geometry into persisted records, and must not regress the pane-instance permanence contract. - Patch Verdict: Matches, and improves it in two places I verified in source: (1)
loadPerspectiveByNameruns the reconciler as a commit-free PREVIEW beforeloadPerspectiveadvances the store's active id — fail-closed extended to selection truth, which the ticket asked for less precisely; (2) the popup-open failure path restores BOTH pristine input documents rather than replaying a compensating placement — commit-or-neither honored even across the vessel boundary (the old home may have normalized away, so replay would be lossy; the code comment says exactly this). - Premise Coherence: Coheres — verify-before-assert made structural: the demo renders the reconciler's remainder instead of narrating success, and the no-spawn result is asserted, not implied.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15003
- Related Graph Nodes:
#14590·#14999·#14925·#14945·#14649· ADR 0029 ·#13158
🔬 Depth Floor
Challenge (per guide §7.1): The live-popup topology-restore path commits documents[1] to popupDocument (loadPerspectiveByName → preview.hasLivePopup && ...) without a component-motion consumer: if a future topology record restores an item ACROSS live windows (workbench committed out of the popup document while the popup stays open), document truth and pane location diverge — nothing moves the live instance. Unexercised on this surface (the tour and both unit paths only topology-restore into a one-window world), so non-blocking here — but #14649/PR #15019's restore_perspective NL tool will reach this seam from outside the demo's choreography, and the cross-window motion consumer will need an owner then. Worth one sentence in #14649's ledger conversation rather than code today.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: every mechanical claim substantiated — "commit-or-neither" (verified in both transfer paths + the vessel-failure rollback test), "renders the structured remainder" (dedicated strip, escaped), "no popup auto-spawn" (
vessel.openCountpinned flat across restore). - Anchor & Echo summaries: JSDoc on
popupDocument,restoreReport,restoreTopologyPerspective,createPopupDocumentis precise codebase terminology; the empty-tabs-normalization note documents a real subtlety (re-seed on next pop-out). -
[RETROSPECTIVE]-class prose: the S4 scene retitle ("restore truth, never summon a window") matches the shipped mechanics exactly. - Linked anchors:
#14925(reconciler) and the §2.2 fail-closed framing check out against source. The "fast-forward chain rooted directly at currentorigin/dev" claim was true at publish; dev has since advanced two merges (no overlap — verified).
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None — the shipped capture/reconcile vocabulary was consumed exactly (the#14649intake packet's ledger matches what this PR exercises).[TOOLING_GAP]: None in this PR's lifecycle on my side; the author's notedEMFILE/uv_uptimehost exhaustion on a redundant rerun produced no contradictory evidence and did not reproduce in my runs.[RETROSPECTIVE]: The preview-before-selection-advance pattern (reconcile withcommit: false, only then let the store advance its active id) is the right generalization of fail-closed — selection state is state too. Worth adopting wherever a store-advance and a document-commit pair up.
N/A Audits — 📡 🔗
N/A across listed dimensions: no OpenAPI surfaces touched; no skill/convention/MCP-tool surfaces introduced (app-demo + specs + tour data only).
🎯 Close-Target Audit
- Close-targets identified:
Resolves #15003(PR body, newline-isolated); commit subjects carry(#15003)without magic keywords. - #15003 confirmed not
epic-labeled (assigned leaf, v13.2).
Findings: Pass.
📑 Contract Completeness Audit
The surfaces added are demo-internal (workspace methods + a static document factory consumed by the specs and tour): no public/consumed contract crosses this PR. The NL-facing perspective contract lives in #14649's ledger (PR #15019), which is the correct owner. #15003's AC set — which you validated executable via API probe before filing — is what I audited against, and each AC has a verifying test I executed.
Findings: Pass — no ledger surface in scope; ACs fully covered.
🪜 Evidence Audit
- PR body carries the greppable
Evidence:line —L3 (exact-head Chromium + Neural Link tour with a real popup...) → L3 required. Residual: none. - Achieved ≥ required: the e2e witness IS the L3 surface (real popup round-trip, two deterministic runs, replay-identical logs, CounterPane identity preserved).
- No residuals deferred; the Post-Merge item is explicitly optional smoke, not an acceptance residual.
- No evidence-class collapse: L2 unit claims and L3 live claims are kept distinct in the body.
Findings: Pass.
🧪 Test-Execution & Location Audit
- Branch checked out at exact head
b38efbe51d9882d0155acf7b8ff6774b7747e8ab. -
npm run test-unit -- test/playwright/unit/apps/agentos/childapps/dockdemo/DemoBWorkspace.spec.mjs→ 12/12 passed (the three new pins: the full topology round-trip withwindowDocumentslength-1 semantics — verified correct againstcaptureTopologyPerspectivesource, slot 0 ridesdockZone; invalid-topology atomicity by object identity AND byte snapshot AND active-selection; popup-open rollback). -
NEO_E2E_PORT=8123 npx playwright test DemoBPerspectivesNL→ 1/1 passed (43.3s) — two full tour runs, one real popup each, no-spawn restore, instance preservation. - Canonical locations: e2e beside the cockpit NL suites in
test/playwright/e2e/agentos/; unit extension in place. - CI at head: CodeQL, integration-unified, lint ×3, lint-pr-body, unit — all pass.
Findings: Tests pass at exact head; evidence claims reproduced independently.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 100 — actively checked: reducer/view-sync holder contract untouched; ownership moves exclusively through the atomictransferItemseam; reconciler composed (not reimplemented); component reparenting kept orthogonal to document truth; no window identity/geometry persisted; placement stays in the childapp beside its siblings.[CONTENT_COMPLETENESS]: 100 — actively checked: every new member and method carries Anchor & Echo JSDoc with the two genuinely subtle contracts documented at the right sites (popup-tree normalization/re-seed; commit-ownership-before-vessel-await with the bookkeeping-as-re-entrancy-guard note); PR body is a complete Fat Ticket with truthful evidence lines.[EXECUTION_QUALITY]: 95 — 12/12 + 1/1 reproduced at exact head; rollback and atomicity pinned by identity and byte-snapshot; 5 deducted for the named unowned seam: live-popup topology restore commits popup-document truth with no component-motion consumer (out of AC scope, will surface via#14649).[PRODUCTIVITY]: 100 — all#15003ACs delivered with verifying tests I executed; the two ticket-strengthening deltas (preview-before-selection, both-documents rollback) are improvements inside scope, not creep.[IMPACT]: 80 — the flagship demo's honesty story is now mechanically real (capture/reconcile/remainder/no-spawn), and it establishes the preview-before-selection pattern; demo-surface blast radius, not engine core.[COMPLEXITY]: 70 — two-document ownership with vessel-failure rollback across an async boundary plus store-selection interplay is genuinely intricate; contained to one workspace class + specs.[EFFORT_PROFILE]: Heavy Lift — cross-document atomicity, a real-popup e2e witness, and fail-closed semantics across three state surfaces (documents, selection, bookkeeping) in one coherent PR.
The reconciler's remainder rendered in the UI — unrestored, displaced, unmatched, no-window-spawned — is the demo doing what this whole epic keeps teaching: show the truth, never narrate it.
Resolves #15003
Demo B now tells the real changed-topology story: the App Worker owns valid primary and popup workspace documents, pop-out and reattach transfer the workbench atomically between them, “Detached” captures topology scope, and restore composes DockTopologyReconciler instead of swapping only the primary document. The UI renders the structured remainder — including the missing popup slot, displaced item, and explicit no-window-spawn result — while invalid topology input leaves both live documents and active perspective selection untouched. The cached CounterPane remains the same live instance throughout the real popup round-trip and final Focus restore.
Evidence: L3 (exact-head Chromium + Neural Link tour with a real popup, two deterministic runs, visible reconciliation remainder, and live component identity proof) → L3 required (runtime topology restore, no-spawn behavior, fail-closed validation, and state continuity). Residual: none.
Deltas from ticket
None substantive. The implementation makes two ticket requirements mechanically stronger: topology restore is previewed before the store advances its active selection, and a denied popup open restores both pristine workspace documents rather than replaying a weaker compensating placement.
Architectural Shape
DockZoneModel.transferItem()is the only ownership move; component reparenting remains an orthogonal SharedWorker render operation.captureTopologyPerspective()persists the primary and popup documents as one topology record, while ordinary named views remain window-scoped.DockTopologyReconciler.reconcile()runs against the actually live document set and never spawns a missing window.unrestored,displaced, andunmatchedLiveinstead of hiding reconciliation semantics in logs.Test Evidence
npm run test-unit -- test/playwright/unit/apps/agentos/childapps/dockdemo/DemoBWorkspace.spec.mjs— 12/12 passed.NEO_E2E_PORT=<fresh> npx playwright test DemoBPerspectivesNL.spec.mjs -c test/playwright/playwright.config.e2e.mjs --workers=1— 1/1 passed; the witness runs the full tour twice, performs one real popup round-trip per run, proves identical timestamp-free logs, and preserves the CounterPane id.EMFILE/uv_uptime EPERM; it produced no contradictory product evidence.node ./buildScripts/util/check-jsdoc-types.mjs— 1,722 files scanned, 0 unparseable type expressions.npm run agent-preflight -- --no-fix <changed files>— all requested gates passed.git diff --check— passed.origin/dev; no unrelated branch history.Commits
b3185519a— implement the Demo B topology capture/reconciliation journey.b38efbe51d— express the optional restore report in Closure/JSDoc-compatible syntax.Post-Merge Validation
devsmoke: play Demo B once in the portal and confirm host popup policy matches the already-green exact-head witness. No acceptance residual is deferred.Related: #14590 Related: #14999 Related: #14945
Authored by Euclid (GPT-5.6 Sol, Codex Desktop). Session 019f484c-662f-7f31-969a-cbde373efd4a.