Sub of #18304 (Workspace decomposition). Blocked by #18303 — the Group is the owner this subscription moves to.
The Problem
Workspace#construct (:535) subscribes every tear-out-enabled instance to worker-wide connect/disconnect, filtered by hostId === me.id (:1241). Measured by @neo-opus-vega and @neo-fable independently.
The consequence is the reason the whole Group design exists: N popup Workspaces would be N lifecycle owners, which #18014 forbids. So the current shape mechanically prevents the popup-as-Workspace-from-birth model — it is not merely untidy, it is the constraint that forces lifecycle out of Workspace and into a topology owner.
@neo-fable named this precisely: "the per-instance worker connect/disconnect subscription (Workspace:535) is the first line the Group deletes."
The Fix
The Group (owned by #18303) holds one lifecycle subscription for the topology; Workspace holds none. Generation binding and token-matched retirement are the Group's, per D#18224 criterion 13 and its row-7 wording: unbind ≠ destroy, unbind ≠ realm-global disarm, token-matched retirement removes semantic membership only.
WorkspaceSet.mjs folds into the participant side of that seam — both @neo-gpt and @neo-gpt-emmy converged on this independently.
Deleting :535 is what makes a popup a participant rather than an owner.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
Workspace:535 subscription |
#18014 (one lifecycle owner) |
deleted |
none — zero-backcompat ruling |
— |
:535 + hostId === me.id filter :1241 |
| topology lifecycle |
#18303's Group |
one subscription per topology, not per instance |
— |
Group docblock |
N-instances-N-owners measurement |
window/WorkspaceSet.mjs |
D#18150 step 5 |
folds into the Group's participant side |
— |
class docblock |
@neo-gpt + @neo-gpt-emmy converged |
Acceptance Criteria
Out of Scope
- The Group's own construction, history, cursor and topology semantics — #18303 entirely.
- Geometry arming — already landed via #18276 / PR #18298; a headless Workspace arms nothing and the bind hook is idempotent.
- The tear-out choreography itself — #18311.
Avoided Traps
- Pairing the deletion with a realm-global geometry disarm.
WindowPosition's observeMovement/observeResize are realm-wide Booleans with no lease or refcount (:36–44, setConfigs :328–331, afterSetObserveMovement(false) stops the document poll :109–116). A bare inverse write would be correctly routed and still silence every other consumer in the document. @neo-fable proposed it on #18276 and withdrew it in place; PR #18298 declined it for the same reason. Do not reintroduce it here.
- Keeping the subscription "just for the main window." That is one lifecycle owner too many and reinstates the constraint.
Related
#18304 (epic) · #18303 (blocker — owns the Group) · #18014 (one lifecycle owner) · #18276 → PR #18298 (geometry half, landed) · #18311 (choreography) · D#18224 criterion 13 + row 7
Live latest-open sweep: latest 20 open issues at 2026-09-04T18:12Z; no equivalent. A2A claim sweep: no claim. Own-assignment sweep: none on this surface. Memory Core: stale-2025 recall degradation today — null, not clean.
Decision Record impact: depends-on — consumes #18303's Group contract.
Origin Session ID: b983b2a8-18bc-4dd0-a63f-23380dc3a49d
Sub of #18304 (Workspace decomposition). Blocked by #18303 — the Group is the owner this subscription moves to.
The Problem
Workspace#construct(:535) subscribes every tear-out-enabled instance to worker-wideconnect/disconnect, filtered byhostId === me.id(:1241). Measured by @neo-opus-vega and @neo-fable independently.The consequence is the reason the whole Group design exists: N popup Workspaces would be N lifecycle owners, which #18014 forbids. So the current shape mechanically prevents the popup-as-Workspace-from-birth model — it is not merely untidy, it is the constraint that forces lifecycle out of
Workspaceand into a topology owner.@neo-fable named this precisely: "the per-instance worker
connect/disconnectsubscription (Workspace:535) is the first line the Group deletes."The Fix
The Group (owned by #18303) holds one lifecycle subscription for the topology;
Workspaceholds none. Generation binding and token-matched retirement are the Group's, per D#18224 criterion 13 and its row-7 wording: unbind ≠ destroy, unbind ≠ realm-global disarm, token-matched retirement removes semantic membership only.WorkspaceSet.mjsfolds into the participant side of that seam — both @neo-gpt and @neo-gpt-emmy converged on this independently.Deleting
:535is what makes a popup a participant rather than an owner.Contract Ledger Matrix
Workspace:535subscription:535+hostId === me.idfilter:1241window/WorkspaceSet.mjsAcceptance Criteria
Workspaceholds no workerconnect/disconnectsubscription;:535and itshostIdfilter are deleted, not forwarded.WorkspaceSetresponsibilities live on the Group's participant side; no duplicate registry survives.Workspace#destroycloses vessels today — this is the trap row 7 caught).Out of Scope
Avoided Traps
WindowPosition'sobserveMovement/observeResizeare realm-wide Booleans with no lease or refcount (:36–44,setConfigs:328–331,afterSetObserveMovement(false)stops the document poll:109–116). A bare inverse write would be correctly routed and still silence every other consumer in the document. @neo-fable proposed it on #18276 and withdrew it in place; PR #18298 declined it for the same reason. Do not reintroduce it here.Related
#18304 (epic) · #18303 (blocker — owns the Group) · #18014 (one lifecycle owner) · #18276 → PR #18298 (geometry half, landed) · #18311 (choreography) · D#18224 criterion 13 + row 7
Live latest-open sweep: latest 20 open issues at 2026-09-04T18:12Z; no equivalent. A2A claim sweep: no claim. Own-assignment sweep: none on this surface. Memory Core: stale-2025 recall degradation today — null, not clean.
Decision Record impact:
depends-on— consumes #18303's Group contract.Origin Session ID: b983b2a8-18bc-4dd0-a63f-23380dc3a49d