Context
DockSplitterZoneIdNL.spec.mjs AC3 boots the Workstation three times in one page and requires each boot's first drag:start to carry its zone id. In the Brain-gated burn-in it fails at boot 2 or 3, never at boot 1. It was red on both attempts of the retry in dev run 38313618683, and in most ten-shard dev runs since.
The Problem
The test selects its splitter before a restored boot's dock has settled.
- Boot 1 starts with empty storage, so the Workspace projects its dock once. Boots 2 and 3 restore the topology boot 1 saved.
ViewportController#createRoot() constructs the Workspace from it, then writes it through the Group as a cold-hydrate transaction. That write re-projects the dock after its first render: splitters 1–5 are replaced by 6–10, and 1–5 are torn down about half a second later.
- The test waits only for
.workstation-dock-host, then takes the first horizontal splitter from the vdom. Before the refresh lands, that is …-splitter-1, which the refresh replaces. The drag's first drag:start then carries no zone.
Observed, on probes from an unmerged branch:
- Run 38317881739, red 6 of 6: every failing boot had selected
…-splitter-1.
- Run 38319422351, green 6 of 6, with every register and unregister logged. On boots 2 and 3,
…-splitter-6 registered at about 1.1–1.4 s, …-splitter-1 to -5 unregistered at about 1.6–1.9 s, and the test dragged -splitter-6.
- Boot 3 reuses
neo-dragzone-6 and …-splitter-6, so ids restart on every boot. With a single page, the worker does not survive this spec's page.goto.
The Architectural Reality
apps/workstation/view/ViewportController.mjs createRoot(): hydrate, construct the Workspace, Transaction.write({cause: 'cold-hydrate'}), then view.add(workspace).
src/dashboard/dock/Workspace.mjs refreshPromise is the settled-surface contract: a consumer that must observe a settled surface awaits it. refreshDockWorkspace() awaits the host's mount before it reconciles, so the first projection always renders first.
- Sibling specs await it after a committed operation:
app.callMethod(id, 'refreshPromise.then').
The Fix
The spec's boot() finds the page's Workspace and awaits its recorded refresh before it selects the splitter. A fresh boot records none (refreshPromise stays null) and skips the wait.
Acceptance Criteria
Out of Scope
- Whether a restored boot should project its dock twice. The second projection rebuilds every splitter and registers its zones again. That is a question for the dock, not this failure.
Corrections
Two earlier versions of this ticket were wrong:
- A guarded keyed delete in
unregisterZone. On a head carrying it, the spec still failed 3 of 6 rounds (run 38318942599). The keyed-delete defect is unit-proven but is not this failure, and its branch is dropped.
- "Two app generations in a surviving SharedWorker, with the old generation's zone traffic reaching the new window." Boot 3 reusing
neo-dragzone-6 refutes it. Both projections belong to the same boot, in the same window.
Related
#16758 (eager zone registration), #19657, epic #19655.
Origin Session ID: 02040656-932a-48c8-8894-6f43d0368663
Context
DockSplitterZoneIdNL.spec.mjsAC3 boots the Workstation three times in one page and requires each boot's firstdrag:startto carry its zone id. In the Brain-gated burn-in it fails at boot 2 or 3, never at boot 1. It was red on both attempts of the retry in dev run 38313618683, and in most ten-sharddevruns since.The Problem
The test selects its splitter before a restored boot's dock has settled.
ViewportController#createRoot()constructs the Workspace from it, then writes it through the Group as acold-hydratetransaction. That write re-projects the dock after its first render: splitters 1–5 are replaced by 6–10, and 1–5 are torn down about half a second later..workstation-dock-host, then takes the first horizontal splitter from the vdom. Before the refresh lands, that is…-splitter-1, which the refresh replaces. The drag's firstdrag:startthen carries no zone.Observed, on probes from an unmerged branch:
…-splitter-1.…-splitter-6registered at about 1.1–1.4 s,…-splitter-1to-5unregistered at about 1.6–1.9 s, and the test dragged-splitter-6.neo-dragzone-6and…-splitter-6, so ids restart on every boot. With a single page, the worker does not survive this spec'spage.goto.The Architectural Reality
apps/workstation/view/ViewportController.mjscreateRoot(): hydrate, construct the Workspace,Transaction.write({cause: 'cold-hydrate'}), thenview.add(workspace).src/dashboard/dock/Workspace.mjsrefreshPromiseis the settled-surface contract: a consumer that must observe a settled surface awaits it.refreshDockWorkspace()awaits the host's mount before it reconciles, so the first projection always renders first.app.callMethod(id, 'refreshPromise.then').The Fix
The spec's
boot()finds the page's Workspace and awaits its recorded refresh before it selects the splitter. A fresh boot records none (refreshPromisestaysnull) and skips the wait.Acceptance Criteria
boot()awaits the Workspace's recorded refresh before it selects the splitter, and skips the wait when none is recorded. (#19702)devspec fails at least one round, so the run is known to reproduce the race. (Run 38323201218: thedevcopy failed 1 of 8, the fix passed 8 of 8.)devrun. (Run 38326477238: first attempt, whole burn-in green.)Out of Scope
Corrections
Two earlier versions of this ticket were wrong:
unregisterZone. On a head carrying it, the spec still failed 3 of 6 rounds (run 38318942599). The keyed-delete defect is unit-proven but is not this failure, and its branch is dropped.neo-dragzone-6refutes it. Both projections belong to the same boot, in the same window.Related
#16758 (eager zone registration), #19657, epic #19655.
Origin Session ID: 02040656-932a-48c8-8894-6f43d0368663