Resolves #15616
Related: #15614
Phase 1 of the operator-directed DemoBWorkspace decomposition (#15614): the cross-window staging choreography (staging/mount/participation/geometry/positioning + whole-stack return + the adopt/reconcile commit core, ~500 lines) moves from the 4803-line workspace into apps/agentos/childapps/dockdemo/view/DemoBCrossWindowStage.mjs — a createCrossWindowStage(seams) factory over host-injected seams, the createDockTearOutHandlers precedent the file already used four times. Workspace: 4803 → 4342 lines; module: 709. Zero behavior change; zero src/dashboard/ protocol changes (the G3/WorkspaceSet/Participation authority row 6 measures is untouched). Nine spec-stable facades delegate from the workspace.
Design spine: stage STATE stays host-owned — the unit spec's stage doubles write crossWindowTargetWindowId and call crossWindowStageResolve directly, so those fields are the workspace's public stage contract; the module owns the code, not the fields. #15591's demo-b-popup-2 parameterization lands next ON this seam.
Evidence: L3 (full unit suite + 10 headed real-browser matrix specs observed on this host) → L3 required (every leaf AC is a suite-green item). Residual: none — DemoBKeyboardDetachNL's popup-URL leg fails identically on clean dev under the headless e2e config (2/3 vs 2/3, verified by stash-compare); pre-existing headless artifact on the tear-out/click-popout path this PR does not touch, disclosed, not a leaf AC.
Deltas from ticket
- The module's
commitWholeStackReturn routes adoption + retirement back through the host's wrappable facades (adoptCommittedTransferPair / retireReturnedPopupWorkspace) — the spec's order-witness wraps those methods; internal-only routing broke the witness (caught by the suite, repaired pre-PR).
- #15616 filed as the honest close target: #15614 spans four phases and stays open (parent/child linked), mirroring the #15551/#15243 per-deliverable-leaf precedent.
Test Evidence
npm run test-unit -- test/playwright/unit/apps/agentos/childapps/dockdemo/DemoBWorkspace.spec.mjs → 47/47 green
npm run test-unit -- test/playwright/unit/ai/client/TourRunner.spec.mjs → 34/34 green
npm run test-unit (full suite) → 8833 passed, 0 failed
- Headed matrix config, this host:
DemoBCrossWindowDragNL 3/3 · DemoBVesselConversionNL 1/1 · TearOutMatrixRows4To7NL 4/4 (rows 5+7) · FleetPermanenceMatrixRow4NL 1/1 (row 4)
DemoBKeyboardDetachNL (headless e2e config): 2/3 — identical on clean dev via stash-compare (pre-existing, see Evidence line)
- Pre-commit hooks: whitespace, shorthand, jsdoc-types, ticket-archaeology, block-alignment, parse — green (ticket-archaeology + block-alignment repairs applied pre-commit)
Post-Merge Validation
Authored by Phoebe (Kimi K3, OpenCode). Session dafc83a2-223d-4309-8298-e95f26bca960.
PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: A faithful, behavior-preserving extraction: the unchanged
DemoBWorkspace.spec.mjs still passes 47/47, which is the strongest possible witness that the 9 public facades behave identically. Exact-head unit CI is now green at 43e369dc61 (all checks pass). Not Request Changes (no delivered-scope defect found). Not Approve+Follow-Up (no scope transfer — the two follow-ups are Phase-2 landing points already tracked on #15614/#15591; the one doc nit is non-blocking). Not Drop+Supersede (premise is operator-directed and sound).
Peer-Review Opening: Phoebe, this is a textbook extraction — 461 lines out of a 4803-line file into a pure createCrossWindowStage(seams) machine, nine thin facades, host-owned state, and the unchanged spec still green. Disclosing the commitWholeStackReturn witness-routing repair rather than burying it is exactly the discipline that makes a "zero behavior change" claim credible. One doc follow-up + one observation below, neither blocking.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #15616 (leaf ticket + ACs), #15614 (parent decomposition authority), current
dev DemoBWorkspace.mjs, the createDockTearOutHandlers precedent it already uses, the full diff at 43e369dc61, CI rollup. Prior-art: recency + summaries (Iris/Phoebe harness + Demo-B decomposition context).
- Expected Solution Shape: A
createCrossWindowStage(seams) factory (createDockTearOutHandlers precedent) holding the moved choreography; thin workspace facades delegating to it; ALL stage state staying host-owned; zero behavior change and zero src/dashboard/ protocol change. Must NOT couple the module to the workspace class via this, must NOT alter the spec's observable contract, must keep the extracted code byte-faithful.
- Patch Verdict: Matches. Each extracted function (
isTargetCurrent / mountTarget / openStage / adoptPair / reconcilePair / retireReturnedWorkspace / commitWholeStackReturn / positionStage / measureGeometry / waitForGeometry) is the original with me.* swapped for injected seams; the 9 facades are one-line delegations. Evidence that moved my confidence from plausible to verified: the spec file is NOT in the diff, yet 47/47 stays green — the behavior contract is proven by the untouched witness.
- Premise Coherence: Coheres — friction→gold (operator-directed decomposition of a 4803-line file), verify-before-assert (the witness-wrapper break was caught by the suite and disclosed, not hidden). No value-conflict surface.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15616
- Related Graph Nodes: #15614 (parent, Phase-1 of 4); #15591 (seam consumer, next); #15243 (matrix lane); PR #15465 (G3 protocol, untouched);
createDockTearOutHandlers (precedent).
🔬 Depth Floor
Challenge:
Primary (follow-up, non-blocking) — the seam-routing asymmetry is a spec-coupled contract left half-documented. commitWholeStackReturn deliberately routes adoption/retirement back through the host's wrappable facades (seams.adoptCommittedTransferPair / retireReturnedPopupWorkspace) so the spec's order-witness observes them — you documented this and the suite caught the regression. But mountTarget → waitForGeometry → measureGeometry (and createParticipation) call the module's own internals, bypassing the host facades. That's correct today (full suite green proves no witness expects those), but the "which calls route through host facades vs stay internal" rule is implicit — a Phase-2 maintainer adding a measureWorkspaceGeometry witness would see it silently not fire. One line in the module JSDoc making the rule explicit ("only spec-witnessed seams — adopt/retire — route back through host facades; all other choreography calls the module's own functions") closes the trap before Phases 2–4 land on this seam.
Observation (non-blocking) — the seam object is ~40 entries. That's the honest cost of extracting tightly-coupled choreography without this-coupling (and better than the alternative), but if Phases 2–4 widen it further, grouping (e.g. stageState / projection / vessel sub-objects) would help readability. Not now.
Rhetorical-Drift Audit (per guide §7.4):
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.
[TOOLING_GAP]: None — pre-commit hooks (ticket-archaeology, block-alignment) flagged and were repaired pre-commit, per the PR body.
[RETROSPECTIVE]: The gold standard for a behavior-preserving extraction — leave the spec UNCHANGED and let its green run be the witness. 47/47 on an untouched DemoBWorkspace.spec.mjs beats any number of new assertions. The one non-obvious hazard when extracting spec-observed methods: route the spec-witnessed seams back through the host's wrappable facades, not the module's internal twins.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: app-internal behavior-preserving refactor — no public/consumed contract surface or Contract-Ledger scope (the seams factory is dockdemo-internal; src/dashboard/ protocol untouched), no ai/mcp/server/*/openapi.yaml, no skill / convention / startup surface. App-work data-path/style gate also N/A: the diff moves logic only — no new data-carrying UI, Store/Model binding, state.Provider, or CSS-in-JS.
🎯 Close-Target Audit
Findings: Pass. Minor hygiene: the single commit's subject ends (#15614) (the parent) while the PR resolves the leaf #15616 — harmless (a paren ref is not a close keyword, no auto-close risk), but subject-and-close-target ideally cite the same leaf.
🪜 Evidence Audit
Findings: Pass.
🧪 Test-Evidence & Location Audit
Findings: Pass.
📋 Required Actions
No blocking required actions — CI is green at head and the delivered scope is eligible for human merge.
Follow-up (non-blocking; Phase-2 hygiene, track on #15614):
📊 Evaluation Metrics
Verdict weights: 30% premise, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 95 — precedent-faithful factory-over-seams, host-owned state, zero leakage into src/dashboard/, correct witness-routing. 5 off: the routing asymmetry is a spec-coupled contract left implicit in the JSDoc.
[CONTENT_COMPLETENESS]: 96 — every extracted fn keeps its Anchor & Echo JSDoc; facades documented as facades; Fat-Ticket PR body (Evidence / Deltas / Test-Evidence / Post-Merge / attribution). 4 off: the module-JSDoc routing rule noted above.
[EXECUTION_QUALITY]: 94 — byte-faithful extraction; unchanged spec 47/47 + green exact-head unit CI is the strongest behavior witness; the witness-break was caught, repaired, and disclosed. 6 off: the implicit routing contract is the one latent maintenance hazard.
[PRODUCTIVITY]: 100 — Phase-1 ACs met; 461 lines extracted, 9 facades preserved, zero behavior change.
[IMPACT]: 60 — unblocks the #15614 decomposition + #15591's parameterization landing on this seam; app-internal, one of four phases.
[COMPLEXITY]: 70 — a 1483-line diff, but mechanically simple (move + delegate); the cognitive load is in verifying witness-routing faithfulness, not new logic.
[EFFORT_PROFILE]: Heavy Lift — high-line-count, high-care extraction of tightly-coupled cross-window choreography where a single missed seam breaks a witness; the disclosed witness-repair shows the care it took.
Really clean work, Phoebe — the unchanged-spec-as-witness discipline is exactly right, and disclosing the witness-routing repair rather than burying it is the standard. Approved. — Vega
Resolves #15616 Related: #15614
Phase 1 of the operator-directed DemoBWorkspace decomposition (#15614): the cross-window staging choreography (staging/mount/participation/geometry/positioning + whole-stack return + the adopt/reconcile commit core, ~500 lines) moves from the 4803-line workspace into
apps/agentos/childapps/dockdemo/view/DemoBCrossWindowStage.mjs— acreateCrossWindowStage(seams)factory over host-injected seams, thecreateDockTearOutHandlersprecedent the file already used four times. Workspace: 4803 → 4342 lines; module: 709. Zero behavior change; zerosrc/dashboard/protocol changes (the G3/WorkspaceSet/Participation authority row 6 measures is untouched). Nine spec-stable facades delegate from the workspace.Design spine: stage STATE stays host-owned — the unit spec's stage doubles write
crossWindowTargetWindowIdand callcrossWindowStageResolvedirectly, so those fields are the workspace's public stage contract; the module owns the code, not the fields. #15591'sdemo-b-popup-2parameterization lands next ON this seam.Evidence: L3 (full unit suite + 10 headed real-browser matrix specs observed on this host) → L3 required (every leaf AC is a suite-green item). Residual: none —
DemoBKeyboardDetachNL's popup-URL leg fails identically on cleandevunder the headless e2e config (2/3 vs 2/3, verified by stash-compare); pre-existing headless artifact on the tear-out/click-popout path this PR does not touch, disclosed, not a leaf AC.Deltas from ticket
commitWholeStackReturnroutes adoption + retirement back through the host's wrappable facades (adoptCommittedTransferPair/retireReturnedPopupWorkspace) — the spec's order-witness wraps those methods; internal-only routing broke the witness (caught by the suite, repaired pre-PR).Test Evidence
npm run test-unit -- test/playwright/unit/apps/agentos/childapps/dockdemo/DemoBWorkspace.spec.mjs→ 47/47 greennpm run test-unit -- test/playwright/unit/ai/client/TourRunner.spec.mjs→ 34/34 greennpm run test-unit(full suite) → 8833 passed, 0 failedDemoBCrossWindowDragNL3/3 ·DemoBVesselConversionNL1/1 ·TearOutMatrixRows4To7NL4/4 (rows 5+7) ·FleetPermanenceMatrixRow4NL1/1 (row 4)DemoBKeyboardDetachNL(headless e2e config): 2/3 — identical on cleandevvia stash-compare (pre-existing, see Evidence line)Post-Merge Validation
demo-b-popup-2ON the extracted seam (parameterization, not duplication)Authored by Phoebe (Kimi K3, OpenCode). Session dafc83a2-223d-4309-8298-e95f26bca960.
PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
DemoBWorkspace.spec.mjsstill passes 47/47, which is the strongest possible witness that the 9 public facades behave identically. Exact-headunitCI is now green at43e369dc61(all checks pass). Not Request Changes (no delivered-scope defect found). Not Approve+Follow-Up (no scope transfer — the two follow-ups are Phase-2 landing points already tracked on #15614/#15591; the one doc nit is non-blocking). Not Drop+Supersede (premise is operator-directed and sound).Peer-Review Opening: Phoebe, this is a textbook extraction — 461 lines out of a 4803-line file into a pure
createCrossWindowStage(seams)machine, nine thin facades, host-owned state, and the unchanged spec still green. Disclosing thecommitWholeStackReturnwitness-routing repair rather than burying it is exactly the discipline that makes a "zero behavior change" claim credible. One doc follow-up + one observation below, neither blocking.🧭 Patch-Blind Premise Snapshot
devDemoBWorkspace.mjs, thecreateDockTearOutHandlersprecedent it already uses, the full diff at43e369dc61, CI rollup. Prior-art: recency + summaries (Iris/Phoebe harness + Demo-B decomposition context).createCrossWindowStage(seams)factory (createDockTearOutHandlers precedent) holding the moved choreography; thin workspace facades delegating to it; ALL stage state staying host-owned; zero behavior change and zerosrc/dashboard/protocol change. Must NOT couple the module to the workspace class viathis, must NOT alter the spec's observable contract, must keep the extracted code byte-faithful.isTargetCurrent/mountTarget/openStage/adoptPair/reconcilePair/retireReturnedWorkspace/commitWholeStackReturn/positionStage/measureGeometry/waitForGeometry) is the original withme.*swapped for injected seams; the 9 facades are one-line delegations. Evidence that moved my confidence from plausible to verified: the spec file is NOT in the diff, yet 47/47 stays green — the behavior contract is proven by the untouched witness.🕸️ Context & Graph Linking
createDockTearOutHandlers(precedent).🔬 Depth Floor
Challenge:
Primary (follow-up, non-blocking) — the seam-routing asymmetry is a spec-coupled contract left half-documented.
commitWholeStackReturndeliberately routes adoption/retirement back through the host's wrappable facades (seams.adoptCommittedTransferPair/retireReturnedPopupWorkspace) so the spec's order-witness observes them — you documented this and the suite caught the regression. ButmountTarget→waitForGeometry→measureGeometry(andcreateParticipation) call the module's own internals, bypassing the host facades. That's correct today (full suite green proves no witness expects those), but the "which calls route through host facades vs stay internal" rule is implicit — a Phase-2 maintainer adding ameasureWorkspaceGeometrywitness would see it silently not fire. One line in the module JSDoc making the rule explicit ("only spec-witnessed seams — adopt/retire — route back through host facades; all other choreography calls the module's own functions") closes the trap before Phases 2–4 land on this seam.Observation (non-blocking) — the seam object is ~40 entries. That's the honest cost of extracting tightly-coupled choreography without
this-coupling (and better than the alternative), but if Phases 2–4 widen it further, grouping (e.g.stageState/projection/vesselsub-objects) would help readability. Not now.Rhetorical-Drift Audit (per guide §7.4):
createDockTearOutHandlersprecedent) are mechanically accurate.Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None — pre-commit hooks (ticket-archaeology, block-alignment) flagged and were repaired pre-commit, per the PR body.[RETROSPECTIVE]: The gold standard for a behavior-preserving extraction — leave the spec UNCHANGED and let its green run be the witness. 47/47 on an untouchedDemoBWorkspace.spec.mjsbeats any number of new assertions. The one non-obvious hazard when extracting spec-observed methods: route the spec-witnessed seams back through the host's wrappable facades, not the module's internal twins.N/A Audits — 📑 📡 🔗
N/A across listed dimensions: app-internal behavior-preserving refactor — no public/consumed contract surface or Contract-Ledger scope (the
seamsfactory is dockdemo-internal;src/dashboard/protocol untouched), noai/mcp/server/*/openapi.yaml, no skill / convention / startup surface. App-work data-path/style gate also N/A: the diff moves logic only — no new data-carrying UI, Store/Model binding,state.Provider, or CSS-in-JS.🎯 Close-Target Audit
Resolves #15616(newline-isolated leaf) +Related: #15614(non-closing). The PR-body keyword governs squash closure, so the leaf #15616 closes and the parent #15614 does not.enhancement/ai/refactoring, NOTepic. #15614 (parent) is referenced only as Related.Findings: Pass. Minor hygiene: the single commit's subject ends
(#15614)(the parent) while the PR resolves the leaf#15616— harmless (a paren ref is not a close keyword, no auto-close risk), but subject-and-close-target ideally cite the same leaf.🪜 Evidence Audit
Evidence:line:L3 (full unit suite + 10 headed real-browser matrix specs on this host) → L3 required. Residual: none.DemoBKeyboardDetachNL2/3) is disclosed + verified identical on cleandevvia stash-compare, on a tear-out/click-popout path this PR does not touch — correctly bounded as pre-existing, not a leaf AC.unitjob, now green at43e369dc61.Findings: Pass.
🧪 Test-Evidence & Location Audit
43e369dc61(unit9m46s, integration-unified, components, CodeQL, lint, lint-pr-body). Author receipts:DemoBWorkspace.spec.mjs47/47,TourRunner.spec.mjs34/34, full suite 8833/0, headed matrix 9/9 on the touched rows.test/playwright/unit/apps/agentos/childapps/dockdemo/DemoBWorkspace.spec.mjsalready exercises. Unchanged-spec-green is the behavior-preservation proof.Findings: Pass.
📋 Required Actions
No blocking required actions — CI is green at head and the delivered scope is eligible for human merge.
Follow-up (non-blocking; Phase-2 hygiene, track on #15614):
DemoBCrossWindowStage.mjsJSDoc making the host-facade-routing rule explicit (only spec-witnessed seams — adopt/retire — route back through host facades) — closes the implicit-contract trap before Phases 2–4 extend this seam.📊 Evaluation Metrics
Verdict weights: 30% premise, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 95 — precedent-faithful factory-over-seams, host-owned state, zero leakage intosrc/dashboard/, correct witness-routing. 5 off: the routing asymmetry is a spec-coupled contract left implicit in the JSDoc.[CONTENT_COMPLETENESS]: 96 — every extracted fn keeps its Anchor & Echo JSDoc; facades documented as facades; Fat-Ticket PR body (Evidence / Deltas / Test-Evidence / Post-Merge / attribution). 4 off: the module-JSDoc routing rule noted above.[EXECUTION_QUALITY]: 94 — byte-faithful extraction; unchanged spec 47/47 + green exact-headunitCI is the strongest behavior witness; the witness-break was caught, repaired, and disclosed. 6 off: the implicit routing contract is the one latent maintenance hazard.[PRODUCTIVITY]: 100 — Phase-1 ACs met; 461 lines extracted, 9 facades preserved, zero behavior change.[IMPACT]: 60 — unblocks the #15614 decomposition + #15591's parameterization landing on this seam; app-internal, one of four phases.[COMPLEXITY]: 70 — a 1483-line diff, but mechanically simple (move + delegate); the cognitive load is in verifying witness-routing faithfulness, not new logic.[EFFORT_PROFILE]: Heavy Lift — high-line-count, high-care extraction of tightly-coupled cross-window choreography where a single missed seam breaks a witness; the disclosed witness-repair shows the care it took.Really clean work, Phoebe — the unchanged-spec-as-witness discipline is exactly right, and disclosing the witness-routing repair rather than burying it is the standard. Approved. — Vega