Epic #17836 is the greenfield DockLayouts authority. The pane-header family shipped through individually gated leaves (#17947, #17948, #17950, #17951, #17963), but the operator acceptance bar was never delivered as one product contract: every DockLayout tabs node uses inline chrome; overflow is first when active; reload · pin · pop-out · maximize occupy the focus-gated middle rail; close is persistent and last; the flagship proves every action and its visual language.
The goal-recovery matrix is recorded at Epic comment 5491147214. Euclid's cross-family convergence review is comment 5491304086. Vega independently mapped the Workstation lifecycle/cache constraints and self-selected that surface. This body folds both peer reviews into one successor rather than creating a second ticket.
Live source was revalidated at dev@bd463173f2; the relevant files are unchanged from the measured current-dev Workstation run.
The Problem
The implementation optimised every leaf for byte-identical-off adoption:
DockWorkspace defaults enableDockCloseAction, enableDockPinAction, enableDockReloadAction, enableDockMaximizeAction, and enableDockPopOutAction to false;
LayoutAdapter owns the correct frozen ordering, but projects only the subset a consumer explicitly enabled;
Workstation enables only close, pin, and maximize;
Workstation has no resolveFreshPane contract and its paneCache has no post-commit adoption seam;
Workstation owns a mature custom tearOutHandlers lifecycle while the base pop-out action is gated by a separate enableDockTearOutLifecycle construction path;
the flagship E2E asserts overflow-first and close-last, so an empty middle rail still passes.
This is the exact leaf-green/product-incomplete failure the recovery is correcting. The five action flags remain public opt-outs, but their product default must be the complete rail.
Rail round-trip acceptance correction
Operator screenshots on current Workstation state expose two product defects in the pin round-trip:
The reveal overlay's restore control inherits the default primary Button UI, producing an oversized blue Pin CTA inside pane chrome.
Railing the final live item of a tabs child inside an edge-band split leaves that empty tab container and its close action rendered. Closed #15837 removed direct empty tabs bands but explicitly preserved split bands; this is the nested tail of that exemption.
The Architectural Reality
Default rail
src/dashboard/dock/projection/LayoutAdapter.mjs#resolveTabConfig already owns the stable node-level action array and frozen order.
Neo.tab.plugin.Overflow contributes independently through projectAsAction: true; it must remain first only while overflow exists and must never enter the tab collection.
Middle actions inherit TabContainer's showOnFocus / reactive containsFocus contract. Stable action instances change state without replacing the array. #18015 makes focus-inactive actions occupy zero space and excludes collapsed actions from Overflow measurement. Focus may legitimately repartition direct tabs versus the overflow menu.
close is the deliberate exception: persistent, contextual: false, and last.
lock is outside the operator goal and remains opt-in.
Reload / cache ownership
Merged #17996 already routes reload to dockReload() when present and otherwise to the two-phase recreate transaction.
apps/workstation/view/Workspace.mjs#resolvePane is cache-backed and owns pane constructors plus shared Provider/Store injection.
Workstation's root Provider owns shared Store instances. A generic per-pane “reload the store” default would refresh multiple panes behind a pane-local affordance. Workstation therefore requires an explicit fresh-pane contract; persisted blueprint/store reload is not an honest fallback.
resolveFreshPane cannot update paneCache during prepare. A failed insert would leave the old pane live while the cache pointed at an uncommitted candidate.
Successful commit needs one post-commit acknowledgement (hook or committed-pane result): candidate is live, cache adopts that exact pane, then the predecessor retires. Refusal/throw leaves slot and cache identities unchanged.
Pop-out / lifecycle ownership
Workstation already owns one proven tear-out handler bundle, vessel embodiment, park owners, connection admission, and a custom onDockTearOutExit.
Enabling base enableDockTearOutLifecycle merely to satisfy dockPopOutActionActive would construct a second handler/listener lifecycle.
Pop-out capability must derive from the one effective host handler/admission bundle. A header click enters the exact same exit → terminal → retire/reintegrate path as the pointer gesture.
#18015 owns generic toolbar flow and collapsed-action exclusion from Overflow measurement. This ticket proves that landed behavior in Workstation; it does not duplicate the algorithm.
2. Make the five action flags default-on
Keep these public configs as explicit opt-outs, but default them to true:
enableDockCloseAction
enableDockPinAction
enableDockReloadAction
enableDockPopOutAction
enableDockMaximizeAction
Keep enableDockLockAction default-off.
Every DockWorkspace projects stable engine identities in this order:
Overflow remains plugin-owned and conditional on actual overflow. Capability/policy changes state, never list membership. Close remains persistent/last; inactive middle actions occupy zero space, and focus may repartition tabs versus the overflow menu without changing action membership or the active-tab invariant.
3. Close the rail round-trip tails
Give the reveal overlay's pin/restore affordance a compact non-primary Button treatment through the shared component seam; do not patch only Workstation.
During split projection, omit child tab flows with zero live items after railing. Rebuild splitters only between surviving children; an all-empty split makes the owning edge band rail-only. The committed split/tree stays unchanged and returns intact when an item is restored.
4. Complete Workstation reload
Factor Workstation's cache-miss pane construction into one fresh-candidate factory that does not consult or mutate paneCache.
resolvePane uses it only on cache miss; resolveFreshPane always creates independently.
Add the narrow post-commit adoption seam needed to swap paneCache[itemId] only after the exact candidate is live.
Delegation retains priority where a pane implements dockReload(); contract-less panes recreate.
5. Complete Workstation pop-out
Make action availability derive from Workstation's existing effective handler bundle.
Reuse the exact current handler identity and custom exit seam; do not create another lifecycle or listener set.
The action measures the live pane and enters the existing pointer tear-out terminal path.
6. Close on one flagship acceptance artifact
Extend the existing Workstation acceptance surface with multiple independent real-click arms—not one order-dependent pane screenplay:
exact ordered vector on every projected tabs node;
focus reveals the stable middle rail from zero inactive extent without changing action membership; direct tabs may repartition against overflow while the active tab remains directly visible;
reload proves delegation and contract-less recreate on different panes;
pin proves rail transition and reversible reveal;
pop-out proves existing vessel admission and same-pane identity;
maximize proves measured workspace geometry and restore;
four Engine themes plus Workstation's custom palette produce computed-style receipts;
cache adopts exact committed pane after insert succeeds
any refusal/throw leaves cache byte-identical
post-commit hook/result JSDoc
slot/cache identity arms
Workstation pop-out capability
existing tearOutHandlers bundle
header action enters same owner and exit/terminal pair
no handler ⇒ action hidden/disabled
lifecycle JSDoc
handler identity + vessel journey
flagship product acceptance
operator goal + Epic recovery comment
all actions clicked; four themes/custom palette accepted
no fixture-only substitution
existing Workstation spec comments
current-dev E2E + screenshots
Decision Record impact
aligned-with ADR 0029 §§2.1, 2.6, and 2.8 and Epic #17836's greenfield/no-compatibility authority. No persisted schema or wire change.
Acceptance Criteria
enableDockCloseAction, enableDockPinAction, enableDockReloadAction, enableDockPopOutAction, and enableDockMaximizeAction default to true and retain explicit false opt-out; enableDockLockAction remains default-off.
Every default DockWorkspace projects stable action identities ordered reload · pin · pop-out · maximize · close; overflow is the first action only while overflowing, and remains outside the tab collection.
Close is persistent/last. The four middle actions use showOnFocus, have zero main-axis extent while context-inactive, and reveal without replacing/reordering actions; direct tabs may repartition against overflow while the active tab stays directly visible.
Reload/pin/pop-out capability or item-policy changes update stable instances through state. Host action ordering and generic non-dock tab behavior remain unchanged.
The reveal overlay pin control uses a compact non-primary treatment in all four Engine themes and Workstation palettes; enabled and disabled states remain legible.
Railing the last live item from one split child removes that empty tabs shell and its orphan actions; surviving children fill the split, all-empty splits yield rail-only, and restoring an item reconstructs the committed split geometry.
Workstation's fresh-pane factory bypasses paneCache; resolvePane uses it only on cache miss and resolveFreshPane always creates independently.
Successful recreate adopts the exact committed pane in paneCache only after it is live; every refusal/throw preserves the exact predecessor, slot, cache entry, and document. Delegation retains priority.
Workstation pop-out uses the exact existing tearOutHandlers identity and custom exit/terminal path; no second handler/listener/vessel owner is created.
Header-action pop-out opens/adopts a vessel at the measured pane rect, and existing retire/reintegration behavior returns the same live pane where required. Refusal commits nothing.
One existing Workstation acceptance artifact asserts the ordered vector for every tabs node and independently clicks reload, pin, pop-out, and maximize through production paths.
That artifact proves no inactive-action gap, focus-time repartition preserves the active-tab/overflow invariants, no duplicate action owner, and no action/tab contamination.
All four Engine themes plus Workstation's custom light/dark palette have computed-style and screenshot evidence. Operator visual acceptance is required before the Epic goal row closes.
Exact-head unit, component, and targeted Workstation E2E suites are green; mutation controls prove the default vector, cache adoption, and lifecycle-owner arms red when reverted.
Out of Scope
Making lock part of the default engine set.
New action names, new action semantics, or a new focus system.
Generic showOnFocus flow and collapsed-action exclusion from Overflow measurement (#18015).
Restyling inline tabs/header actions; #17950/#17963 own the shipped chrome/value layer.
A second reload or tear-out lifecycle.
Per-pane Store topology changes.
Persisting reload/maximize/action state.
Updating external consumer repositories in this PR.
Avoided Traps
Delete the public flags. That is an API break not required by the operator goal; default-on plus explicit opt-out delivers the product without forcing every consumer.
Another per-app opt-in patch. It fixes one screenshot and leaves the framework default wrong.
Generic data reload. Shared Store instances turn a pane-local affordance into a multi-pane refresh.
Mutate paneCache during prepare. Failed commit would split live slot and cache truth.
Enable the base tear-out lifecycle beside Workstation's bundle. Two handlers/listener sets violate single ownership.
Vary action arrays per active item. Retained toolbar identity and overflow projection would race again.
One sequential all-action screenplay. Pin/pop-out intentionally move panes; independent arms in one flagship artifact test contracts rather than choreography order.
Fixture transfer. Dedicated fixtures do not prove Workstation wiring or operator-visible quality.
Creation freshness: the initial live latest-open/A2A/KB/local sweep found no equivalent. The attempted Workstation successor was not filed; its content was folded here when the last-moment sweep surfaced peer convergence on one close target.
Context
Epic #17836 is the greenfield DockLayouts authority. The pane-header family shipped through individually gated leaves (
#17947,#17948,#17950,#17951,#17963), but the operator acceptance bar was never delivered as one product contract: every DockLayout tabs node uses inline chrome; overflow is first when active;reload · pin · pop-out · maximizeoccupy the focus-gated middle rail; close is persistent and last; the flagship proves every action and its visual language.The goal-recovery matrix is recorded at Epic comment 5491147214. Euclid's cross-family convergence review is comment 5491304086. Vega independently mapped the Workstation lifecycle/cache constraints and self-selected that surface. This body folds both peer reviews into one successor rather than creating a second ticket.
Live source was revalidated at
dev@bd463173f2; the relevant files are unchanged from the measured current-dev Workstation run.The Problem
The implementation optimised every leaf for byte-identical-off adoption:
DockWorkspacedefaultsenableDockCloseAction,enableDockPinAction,enableDockReloadAction,enableDockMaximizeAction, andenableDockPopOutActiontofalse;LayoutAdapterowns the correct frozen ordering, but projects only the subset a consumer explicitly enabled;resolveFreshPanecontract and itspaneCachehas no post-commit adoption seam;tearOutHandlerslifecycle while the base pop-out action is gated by a separateenableDockTearOutLifecycleconstruction path;This is the exact leaf-green/product-incomplete failure the recovery is correcting. The five action flags remain public opt-outs, but their product default must be the complete rail.
Rail round-trip acceptance correction
Operator screenshots on current Workstation state expose two product defects in the pin round-trip:
PinCTA inside pane chrome.The Architectural Reality
Default rail
src/dashboard/dock/projection/LayoutAdapter.mjs#resolveTabConfigalready owns the stable node-level action array and frozen order.Neo.tab.plugin.Overflowcontributes independently throughprojectAsAction: true; it must remain first only while overflow exists and must never enter the tab collection.TabContainer'sshowOnFocus/ reactivecontainsFocuscontract. Stable action instances change state without replacing the array. #18015 makes focus-inactive actions occupy zero space and excludes collapsed actions from Overflow measurement. Focus may legitimately repartition direct tabs versus the overflow menu.closeis the deliberate exception: persistent,contextual: false, and last.lockis outside the operator goal and remains opt-in.Reload / cache ownership
dockReload()when present and otherwise to the two-phase recreate transaction.apps/workstation/view/Workspace.mjs#resolvePaneis cache-backed and owns pane constructors plus shared Provider/Store injection.resolveFreshPanecannot updatepaneCacheduring prepare. A failed insert would leave the old pane live while the cache pointed at an uncommitted candidate.Pop-out / lifecycle ownership
onDockTearOutExit.enableDockTearOutLifecyclemerely to satisfydockPopOutActionActivewould construct a second handler/listener lifecycle.The Fix
1. Consume #18015's focus-geometry prerequisite
#18015 owns generic toolbar flow and collapsed-action exclusion from Overflow measurement. This ticket proves that landed behavior in Workstation; it does not duplicate the algorithm.
2. Make the five action flags default-on
Keep these public configs as explicit opt-outs, but default them to
true:enableDockCloseActionenableDockPinActionenableDockReloadActionenableDockPopOutActionenableDockMaximizeActionKeep
enableDockLockActiondefault-off.Every DockWorkspace projects stable engine identities in this order:
overflow → reload → pin → pop-out → maximize → closeOverflow remains plugin-owned and conditional on actual overflow. Capability/policy changes state, never list membership. Close remains persistent/last; inactive middle actions occupy zero space, and focus may repartition tabs versus the overflow menu without changing action membership or the active-tab invariant.
3. Close the rail round-trip tails
4. Complete Workstation reload
paneCache.resolvePaneuses it only on cache miss;resolveFreshPanealways creates independently.paneCache[itemId]only after the exact candidate is live.dockReload(); contract-less panes recreate.5. Complete Workstation pop-out
6. Close on one flagship acceptance artifact
Extend the existing Workstation acceptance surface with multiple independent real-click arms—not one order-dependent pane screenplay:
Contract Ledger
falseopt-out; lock remains default-offreload · pin · pop-out · maximize · close; overflow contribution firsttearOutHandlersbundleDecision Record impact
aligned-with ADR 0029 §§2.1, 2.6, and 2.8 and Epic #17836's greenfield/no-compatibility authority. No persisted schema or wire change.Acceptance Criteria
enableDockCloseAction,enableDockPinAction,enableDockReloadAction,enableDockPopOutAction, andenableDockMaximizeActiondefault totrueand retain explicitfalseopt-out;enableDockLockActionremains default-off.reload · pin · pop-out · maximize · close; overflow is the first action only while overflowing, and remains outside the tab collection.showOnFocus, have zero main-axis extent while context-inactive, and reveal without replacing/reordering actions; direct tabs may repartition against overflow while the active tab stays directly visible.paneCache;resolvePaneuses it only on cache miss andresolveFreshPanealways creates independently.paneCacheonly after it is live; every refusal/throw preserves the exact predecessor, slot, cache entry, and document. Delegation retains priority.tearOutHandlersidentity and custom exit/terminal path; no second handler/listener/vessel owner is created.Out of Scope
showOnFocusflow and collapsed-action exclusion from Overflow measurement (#18015).Avoided Traps
paneCacheduring prepare. Failed commit would split live slot and cache truth.Related
Parent: #17836. Blocked by: #18015. Goal-recovery artifact: comment 5491147214. Peer convergence: comment 5491304086. Precedents: #13771, #15837, #17874/#17875, #17947, #17948, #17950/#17956, #17951/#17960, #17963/#17977, #17966/#17996.
Creation freshness: the initial live latest-open/A2A/KB/local sweep found no equivalent. The attempted Workstation successor was not filed; its content was folded here when the last-moment sweep surfaced peer convergence on one close target.
Origin Session ID: 309a78d7-2d95-4f23-bdfc-69d2ae393a5d
Retrieval Hint:
query_raw_memories("default DockLayout action rail Workstation paneCache resolveFreshPane one tear-out lifecycle")— Emmy (GPT-5.6 Sol Ultra, Codex), incorporating Euclid and Vega peer-role convergence.