Serves: #18304 — this is that Epic's re-derivation finding arriving as a live defect rather than a count.
Context
The #18304 closeout measured DemoBWorkspace re-implementing twelve dock-specific methods while extending Container rather than the dock Workspace. That was a number. @neo-opus-vega found what the number costs, while fixing #18421, and handed it over rather than widening her lane.
Every link below re-verified independently at dev@a4dc6c9441 before filing.
The Problem
examples/dashboard/crossWindow/DemoBCrossWindowStage.mjs carries a hand-copied measureGeometry whose root unwrap reads the zone descriptor directly:
rootId = nodes[document.root]?.type === 'edge-zone'
? (nodes[document.root].zones?.center ?? document.root)
: document.root,Under the v13.2 schema zones.center is an object descriptor, not an id. demoBPerspectives.mjs:37 ships exactly that shape:
root: {type: 'edge-zone', zones: {center: {nodeId: 'workbench-tabs'}, right: {nodeId: 'side-tabs'}}}So rootId becomes {nodeId: 'workbench-tabs'}, and the block then publishes root: {nodeId: rootId, rect: hostRect}. Two guards in PreviewProducer fail closed on precisely that, and it is worth naming which does what — produceCandidates:376 is the one that drops the chips, while resolveRootEdge:175 is the separate pointer-inference path (@neo-gpt, measured):
if (root && typeof root.nodeId === 'string' && root.nodeId && root.rect && root.nodeId !== zone.nodeId) { … }
and the pointer-inference guard:
if (!(band > 0) || typeof root?.nodeId !== 'string' || !root.nodeId || !rect || !pointer) return null;
Every root edge chip in Demo-B is off, silently, with no error. Reachable rather than theoretical: the perspective above ships in the demo, and DemoBWorkspace.mjs:4524 carries a popup-root shell of the same shape.
The Architectural Reality
The engine fixed this and the copy never heard. src/dashboard/dock/interaction/DragAffordances.mjs:150 carries the repair and a comment naming this exact regression:
"…id guard from silently dropping every root edge chip"
rootId = nodes[…root]?.type === 'edge-zone'
? (WorkspaceDocument.getZoneNodeId(nodes[…root].zones?.center) ?? …root)
: …root;Census, one instrument across both files:
| file |
getZoneNodeId uses |
src/dashboard/dock/interaction/DragAffordances.mjs |
1 |
examples/dashboard/crossWindow/DemoBCrossWindowStage.mjs |
0 |
⭐ This is the cost of re-derivation stated as a defect instead of a line count. One file got the repair; its duplicate kept the bug; nothing in the tree could tell them apart, because the duplicate is not in the inheritance chain that would have carried the fix.
The same block also pairs a centre nodeId with the host's rect — the #18421 mismatch @neo-opus-vega fixed engine-side in PR #18426. The duplicate holds both defects.
The Fix
Call the canonical unwrap. WorkspaceDocument.getZoneNodeId is a static, so the stage can use it without inheriting from DockWorkspace — this de-duplicates the decision, not merely the current copy, so the two cannot diverge on this point again.
What this ticket deliberately does not claim to fix. The duplication itself. Demo-B remains a standalone stage that re-derives twelve dock methods, and the engine's newer boundary seam (resolveDockableRoot()) still cannot reach it. That disposition belongs to #18304 and is named in its seam account. Repairing the symptom here is worth doing because the defect is live and user-visible; it is not worth pretending it addresses the cause.
Acceptance Criteria
Constraints
- Symptom-level by design. Do not fold the decomposition in; #18304 owns it and widening a lane mid-flight is what cost the team five hours on #18383.
- No engine change. The existing
DragAffordances descriptor unwrap and WorkspaceDocument.getZoneNodeId are the reference for this bounded repair; #18426 owns the engine's separate boundary alignment.
Decision Record impact
none — this restores conformance to the existing WorkspaceDocument contract rather than changing it.
Evidence and framing from @neo-opus-vega, re-verified before filing.
Serves:#18304 — this is that Epic's re-derivation finding arriving as a live defect rather than a count.Context
The #18304 closeout measured
DemoBWorkspacere-implementing twelve dock-specific methods while extendingContainerrather than the dockWorkspace. That was a number. @neo-opus-vega found what the number costs, while fixing #18421, and handed it over rather than widening her lane.Every link below re-verified independently at
dev@a4dc6c9441before filing.The Problem
examples/dashboard/crossWindow/DemoBCrossWindowStage.mjscarries a hand-copiedmeasureGeometrywhose root unwrap reads the zone descriptor directly:rootId = nodes[document.root]?.type === 'edge-zone' ? (nodes[document.root].zones?.center ?? document.root) : document.root,Under the v13.2 schema
zones.centeris an object descriptor, not an id.demoBPerspectives.mjs:37ships exactly that shape:root: {type: 'edge-zone', zones: {center: {nodeId: 'workbench-tabs'}, right: {nodeId: 'side-tabs'}}}So
rootIdbecomes{nodeId: 'workbench-tabs'}, and the block then publishesroot: {nodeId: rootId, rect: hostRect}. Two guards inPreviewProducerfail closed on precisely that, and it is worth naming which does what —produceCandidates:376is the one that drops the chips, whileresolveRootEdge:175is the separate pointer-inference path (@neo-gpt, measured):// produceCandidates — the chip set if (root && typeof root.nodeId === 'string' && root.nodeId && root.rect && root.nodeId !== zone.nodeId) { … } // else rootOut stays nulland the pointer-inference guard:
if (!(band > 0) || typeof root?.nodeId !== 'string' || !root.nodeId || !rect || !pointer) return null;Every root edge chip in Demo-B is off, silently, with no error. Reachable rather than theoretical: the perspective above ships in the demo, and
DemoBWorkspace.mjs:4524carries apopup-rootshell of the same shape.The Architectural Reality
The engine fixed this and the copy never heard.
src/dashboard/dock/interaction/DragAffordances.mjs:150carries the repair and a comment naming this exact regression:rootId = nodes[…root]?.type === 'edge-zone' ? (WorkspaceDocument.getZoneNodeId(nodes[…root].zones?.center) ?? …root) : …root;Census, one instrument across both files:
getZoneNodeIdusessrc/dashboard/dock/interaction/DragAffordances.mjsexamples/dashboard/crossWindow/DemoBCrossWindowStage.mjs⭐ This is the cost of re-derivation stated as a defect instead of a line count. One file got the repair; its duplicate kept the bug; nothing in the tree could tell them apart, because the duplicate is not in the inheritance chain that would have carried the fix.
The same block also pairs a centre
nodeIdwith the host's rect — the #18421 mismatch @neo-opus-vega fixed engine-side in PR #18426. The duplicate holds both defects.The Fix
Call the canonical unwrap.
WorkspaceDocument.getZoneNodeIdis a static, so the stage can use it without inheriting fromDockWorkspace— this de-duplicates the decision, not merely the current copy, so the two cannot diverge on this point again.What this ticket deliberately does not claim to fix. The duplication itself. Demo-B remains a standalone stage that re-derives twelve dock methods, and the engine's newer boundary seam (
resolveDockableRoot()) still cannot reach it. That disposition belongs to #18304 and is named in its seam account. Repairing the symptom here is worth doing because the defect is live and user-visible; it is not worth pretending it addresses the cause.Acceptance Criteria
DemoBCrossWindowStage.mjsresolves the root zone throughWorkspaceDocument.getZoneNodeId; agetZoneNodeIdcensus of that file returns ≥ 1.rootIdis a string for the shippeddemoBPerspectivesedge-zone root — asserted, with a red arm on the current code proving the object form.Constraints
DragAffordancesdescriptor unwrap andWorkspaceDocument.getZoneNodeIdare the reference for this bounded repair; #18426 owns the engine's separate boundary alignment.Decision Record impact
none— this restores conformance to the existingWorkspaceDocumentcontract rather than changing it.Evidence and framing from @neo-opus-vega, re-verified before filing.