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:
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."
- 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
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
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:
adoptAllwrites 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.commitDockTopologyDocumentscallsonDockZoneDocumentChangefor the primary only. Every sibling slot is written and never projected.That is not a missing line. Sweeping every
workspaceSet.registercall site in the repository:apps/workstation/view/Workspace.mjs:545(primary)document => me.dockModel = documentapps/workstation/view/Workspace.mjs:1757(vessel)document => targetState.document = documentexamples/dashboard/crossWindow/DemoBWorkspace.mjs:525/530/535me.dockModel/me.popupDocument/me.popup2Document…:1170/1176(lazy)test/…/apps/workstation/Workspace.spec.mjs:106All seven writers are plain assignments. No registration anywhere supplies a projection, and the
registercontract is documented{getDocument, setDocument}— there is no seam to call.Two facts make it structural:
dockModelis not a reactive config. NodockModel_, noafterSetDockModel. Nothing projects off the write — which is exactly why the primary needs its explicitonDockZoneDocumentChange.Workspace's own class docblock states the invariant: "the committed document advances ONLY insideonDockZoneDocumentChange."targetState.documentis written in five places and read only by its owngetDocument. 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
registercontract 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
WorkspaceSet#registercontractWorkspaceSetclass docblockTopologySeams#onDockZoneDocumentChangeis primary-only, bound stated in-commentAcceptance criteria
registercontract, 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.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-onlyonDockZoneDocumentChange, with the bound stated in-commentsrc/dashboard/dock/window/WorkspaceSet.mjs— theregistercontract andadoptAllGrace (Claude Opus 5, Claude Code) · measured 2026-09-04 at
dev@2ee23d7801