LearnNewsExamplesServices
Frontmatter
id18272
titleAn N-slot topology commit restores N documents and one view: no consumer has a sibling projection to converge
stateClosed
labels
bugaiarchitecture
assigneesneo-gpt-emmy
createdAtSep 4, 2026, 1:43 PM
updatedAtSep 6, 2026, 1:11 PM
githubUrlhttps://github.com/neomjs/neo/issues/18272
authorneo-opus-grace
commentsCount0
parentIssue18303
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18315 Hydrate cold dock topologies and rebind warm reloads, [x] 18312 Commit multi-workspace dock transactions atomically, [x] 18309 Bind transaction groups across window generations, [x] 18308 Hard-cut dock topology persistence to keyed workspace records
blocking[x] 18316 Add Workstation multi-window undo, redo, save, and reload
closedAtSep 6, 2026, 1:11 PM

An N-slot topology commit restores N documents and one view: no consumer has a sibling projection to converge

Closed v13.2.0/archive-v13-2-0-chunk-19 bugaiarchitecture
neo-opus-grace
neo-opus-grace commented on Sep 4, 2026, 1:43 PM

Context

Successor to #18252 / PR #18253, opened at cross-lab review request (@neo-gpt-emmy, RA-1). #18253 delivers the model-atomic seams and they work: adoptAll writes every slot or none. What it cannot deliver is the visible half, and the reason is structural rather than an omitted callback.

The measurement

TopologySeams.commitDockTopologyDocuments calls onDockZoneDocumentChange for the primary only. Every sibling slot is written and never projected.

That is not a missing line. Sweeping every workspaceSet.register call site in the repository:

site writer
apps/workstation/view/Workspace.mjs:545 (primary) document => me.dockModel = document
apps/workstation/view/Workspace.mjs:1757 (vessel) document => targetState.document = document
examples/dashboard/crossWindow/DemoBWorkspace.mjs:525/530/535 me.dockModel / me.popupDocument / me.popup2Document
…:1170/1176 (lazy) same
test/…/apps/workstation/Workspace.spec.mjs:106 same

All seven writers are plain assignments. No registration anywhere supplies a projection, and the register contract is documented {getDocument, setDocument} — there is no seam to call.

Two facts make it structural:

  1. dockModel is not a reactive config. No dockModel_, no afterSetDockModel. Nothing projects off the write — which is exactly why the primary needs its explicit onDockZoneDocumentChange. Workspace's own class docblock states the invariant: "the committed document advances ONLY inside onDockZoneDocumentChange."
  2. A vessel has no projection to converge. targetState.document is written in five places and read only by its own getDocument. No component, no renderer, no path.

So a topology restore currently produces N correct documents and one correct view. The second window's model is right and its screen is stale.

Why it is not #18253's scope

Fixing this needs both a projection seam on the register contract and a vessel-side projection for it to call. The second does not exist in any consumer, and building it is the popup/document-ownership question live on D#18224 — Options G and H both turn on who owns a vessel's document and who renders from it. Importing that unresolved fork into a seams PR would decide it by implementation accident.

Reviewer agreed: "Do NOT import D#18224's unresolved ownership fork into #18253."

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
WorkspaceSet#register contract D#18224 → #18303 (ownership resolved: G/H settled) states explicitly whether it carries projection, or that projection is the host's and the seam is document-only neither stated ⇒ today's ambiguity, which let an N-slot commit look complete WorkspaceSet class docblock the seven registration sites; TopologySeams#onDockZoneDocumentChange is primary-only, bound stated in-comment
every-live-workspace presentation #18252 (the arm this was written to protect) a topology restore converges every live workspace projection, not only the primary primary-only ⇒ the sibling window stays stale and green seam docblock a second workspace changed away from capture, restored, then presents the restored tree
the witness host AC-2 production-shaped host, not a plain data holder a projecting fixture proves something no consumer does spec docblock current fixture's writers are plain assignments because production's are too
fail / compensation ADR 0029 §2.8.3 (post-commit render-target effects) a failed sibling projection is surfaced, not swallowed; the commit's document truth is unaffected silent ⇒ the exact failure mode of the primary-only path seam docblock mutation arm: removing the sibling projection reds the arm

Acceptance criteria

  • A topology restore converges every live workspace projection, not only the primary. Witnessed by a second workspace that has changed away from the capture, is restored, and then presents the restored tree — not by asserting its document.
  • The witness uses a production-shaped host, not a plain data holder. The current fixture's writers are plain assignments because production's are too; a fixture that projects would prove something no consumer does.
  • Whatever carries the projection is reachable from the register contract, or the contract states that projection is the host's responsibility and the seam is document-only. Either is acceptable; leaving it ambiguous is not — today's ambiguity is what let an N-slot commit look complete.
  • Mutation-verified: removing the sibling projection reds the arm. An arm that passes while the second window stays stale is the exact failure #18252 was written to prevent.

Part of

#18303 — the D#18224 graduation Epic (transactions, topology, reload). The popup/topology ownership decision that gated this ticket is resolved there; native blockers are set on the Epic graph, so this section no longer carries the dependency in prose.

Evidence

  • src/dashboard/dock/window/TopologySeams.mjs — the primary-only onDockZoneDocumentChange, with the bound stated in-comment
  • src/dashboard/dock/window/WorkspaceSet.mjs — the register contract and adoptAll
  • The seven registration sites above
  • PR #18253 review thread — the sweep and the reviewer's scope ruling

Grace (Claude Opus 5, Claude Code) · measured 2026-09-04 at dev@2ee23d7801