Severity: P0. On the Workstation flagship, create a nested column by dragging one dock item above or below another, then resize the enclosing column through the visually vertical divider of its outer horizontal split. Only one stacked pane follows the new width; its sibling keeps the old cross-axis extent, leaving a large empty region inside the column.
The operator supplied a rendered Workstation screenshot showing unequal right edges after this journey. The dock document remains structurally plausible; the rendered descendants do not agree on their parent column's width.
Live baseline: origin/dev@fa20136f29 (merged PRs #17974, #17973, and #17977).
Creation-time duplicate evidence:
Live latest-open sweep: checked the latest 20 open issues at 2026-08-31T21:34Z; no equivalent ticket exists.
Recent all-read-state A2A claim sweep: no claim owns the nested-column geometry failure. #17980 owns a different retained-chrome duplication race.
The exact issue/discussion corpus contained no equivalent. The Knowledge Base query returned only the #13158 umbrella and older geometry lineage, but its stale corpus is advisory and does not certify freshness; live GitHub plus the A2A claim sweep are the duplicate authority.
The Problem
Existing witnesses prove flat adjacent-pair splitter behavior and individual drag/drop behavior, but none composes the sequence that failed:
real tab drag to split-above/below
-> retained tab container enters a nested vertical split
-> outer horizontal split is resized
-> every stacked descendant must track the column width
The red-first E2E confirms the committed model and settled projection are correct. The failure exists only when the outer splitter starts while the preceding structural DockFlip still owns retained descendants: DockFlip has hoisted those panes to fixed old-pixel geometry, so the direct outer pair grows while the visible panes remain frozen. Once DockFlip settles, the layout heals. The bug is therefore a real live-resize correctness defect at the presentation-to-interaction ownership handoff, not a reducer or nested-flex defect.
This is a successor to the resolved flat-pair contract in #17820 / PR #17849. Reopening that ticket would erase the fact that the missing composition is newly observed.
The Architectural Reality
model/Operations.splitNode() creates the expected nested tree, and resizeSplit() commits one normalized immediate-child vector. The E2E proves the model remains byte-identical during preview and changes only the outer size vector on release.
projection/LayoutAdapter.projectSplitNode() correctly projects the nested vertical split as one direct flex child; both tab shells stretch with it.
DockSplitter.getResizeConfig() correctly names the two direct outer layout participants. Recursively resizing descendants would duplicate flexbox authority.
Main-thread DockFlip.play() temporarily uses position: fixed plus the old pixel width to preserve structural motion across clipping boundaries. Those descendants are deliberately outside flex flow until its cleanup runs.
projection/MotionSignal remains the worker-owned, counted observability signal; its finite fail-safe cannot own physical admission. Main-thread DockFlip snapshot/pending/active registries are the actual presentation authority, and DragDrop.onDragStart() consults them on the native event path before Resize.start() or App delivery.
ADR 0029 §2.1 separates committed state, projection, runtime interaction pixels, and main-thread DOM geometry. Direct manipulation must reclaim geometry authority from presentation before it measures or resizes.
The Fix
Make Neo.main.addon.DockFlip.land({hostId}) a remote, idempotent, strictly host-scoped settlement seam. Missing hostId is refused; destroy alone uses the private all-host path. Snapshot-only, pending-wait, and active-stage generations share one owner: pending rAF/timer waits are interrupted and cancelled immediately, same-host successor capture lands its predecessor first, active cleanup is defensive LIFO, committed inline geometry is restored exactly, and interrupted plays resolve false without an external carrier.
In Main DragDrop.onDragStart(), call the same-window DockFlip.landFromPath(nativePath) synchronously beforeResize.start() and before publishing drag:start to App. DockFlip's own registry identifies the first path-owned host, so both live-resize and proxy-mode splitter starts are covered without trusting an App descriptor or waiting for a worker acknowledgement. Missing addon, foreign path, or no active presentation is a cheap fail-open no-op.
Keep DockSplitter.onDragStart() App-side and semantic: after Main admission it captures the direct pair, projects optional proxy paint, and opens the inherited logical gesture under its generation fence. Add the exact trusted-pointer Workstation journey plus focused Main/DockFlip/DockSplitter lifecycle and order arms.
Contract Ledger
Target surface
Source of authority
Required behavior
Fallback / failure
Evidence
Nested split as outer pair member
dock document + LayoutAdapter.projectSplitNode()
The nested subtree is one direct outer flex child; its tab shells stretch to the same cross-axis extent
Layout shells diverging by >1px is failure
Real Workstation E2E, worker topology + DOM rect matrix
Presentation-to-interaction handoff
Main DragDrop + DockFlip host registry; MotionSignal observability only
Path-owned snapshot/pending/active FLIP state lands synchronously before native Resize admission and App delivery; fixed-stage descendants release to committed layout
Missing addon, foreign path, or no presentation is a synchronous no-op; proxy mode is covered without a resize descriptor
Held-App/immediate-move Main unit + DockFlip settlement mutants + Workstation E2E
Outer splitter preview and terminal
DockSplitter + main-thread Resize + ADR 0029 §2.1
Preview conserves the direct outer pair; tab shells stay within 1px and transform-inclusive panes within 2px; release commits only the outer resizeSplit
Escape restores the full column and commits zero operations
Mid-gesture, release, and reverse-Escape E2E receipts
Decision Record impact
Aligned with ADR 0029 §2.1. This restores the existing state-ownership boundary; it adds no persisted field, operation, or public API and does not require an ADR amendment.
Acceptance Criteria
A Workstation Whitebox E2E uses trusted pointer input to place Matrix right of Alerts, place Feed above Alerts, and prove the resulting nested vertical split in worker-owned dockModel.
The E2E positively enters the structural neo-dashboard-dock-animating / fixed-stage window before grabbing the enclosing outer splitter.
The live resize resolves the two direct outer layout participants; no descendant-array contract is introduced.
During preview, both stacked tab shells track the nested parent within 1px and transform-inclusive pane rects within 2px; the outer pair stays conserved.
The serialized document is byte-identical while held; release changes only the outer split size vector, preserves the nested vector, and retains pane/tab identities.
A reverse-direction Escape arm restores the whole column and commits zero operations.
DockFlip.land({hostId}) is remote, requires one host, is idempotent, retires captured First state, interrupts pending frame/timer waits without servicing either carrier, serializes same-host successor capture, restores active fixed stages and exact inline styles without destroying the addon, and resolves interrupted plays.
Main DragDrop uses DockFlip's own path-to-host registry to land presentation synchronously before Resize.start() and App drag:start delivery. A held App handler plus immediate native move cannot mutate while fixed-stage presentation remains; live and proxy modes are covered, while missing addon/foreign path/no motion stay fail-open and synchronous.
Programmatic-only topology setup: rejected because it bypasses the retained-instance path created by a real tab drag.
First visible splitter selector: rejected because edge and nested splitters share orientation classes; dockNodeId is the semantic selector.
Reducer patch first: rejected because current model operations already produce normalized nested trees and would not explain divergent rendered edges.
Arrays of descendant resize targets: rejected because the verified direct participant is the nested container; recursive pixel writes would make Splitter fight DockFlip and duplicate flexbox authority.
Waiting or refusing the pointer: rejected because direct manipulation should respond immediately; landing presentation is deterministic and uses DockFlip's existing cleanup authority.
Context
Severity: P0. On the Workstation flagship, create a nested column by dragging one dock item above or below another, then resize the enclosing column through the visually vertical divider of its outer horizontal split. Only one stacked pane follows the new width; its sibling keeps the old cross-axis extent, leaving a large empty region inside the column.
The operator supplied a rendered Workstation screenshot showing unequal right edges after this journey. The dock document remains structurally plausible; the rendered descendants do not agree on their parent column's width.
Live baseline:
origin/dev@fa20136f29(merged PRs #17974, #17973, and #17977).Creation-time duplicate evidence:
The Problem
Existing witnesses prove flat adjacent-pair splitter behavior and individual drag/drop behavior, but none composes the sequence that failed:
The red-first E2E confirms the committed model and settled projection are correct. The failure exists only when the outer splitter starts while the preceding structural DockFlip still owns retained descendants: DockFlip has hoisted those panes to fixed old-pixel geometry, so the direct outer pair grows while the visible panes remain frozen. Once DockFlip settles, the layout heals. The bug is therefore a real live-resize correctness defect at the presentation-to-interaction ownership handoff, not a reducer or nested-flex defect.
This is a successor to the resolved flat-pair contract in #17820 / PR #17849. Reopening that ticket would erase the fact that the missing composition is newly observed.
The Architectural Reality
model/Operations.splitNode()creates the expected nested tree, andresizeSplit()commits one normalized immediate-child vector. The E2E proves the model remains byte-identical during preview and changes only the outer size vector on release.projection/LayoutAdapter.projectSplitNode()correctly projects the nested vertical split as one direct flex child; both tab shells stretch with it.DockSplitter.getResizeConfig()correctly names the two direct outer layout participants. Recursively resizing descendants would duplicate flexbox authority.DockFlip.play()temporarily usesposition: fixedplus the old pixel width to preserve structural motion across clipping boundaries. Those descendants are deliberately outside flex flow until its cleanup runs.projection/MotionSignalremains the worker-owned, counted observability signal; its finite fail-safe cannot own physical admission. Main-threadDockFlipsnapshot/pending/active registries are the actual presentation authority, andDragDrop.onDragStart()consults them on the native event path beforeResize.start()or App delivery.The Fix
Neo.main.addon.DockFlip.land({hostId})a remote, idempotent, strictly host-scoped settlement seam. MissinghostIdis refused; destroy alone uses the private all-host path. Snapshot-only, pending-wait, and active-stage generations share one owner: pending rAF/timer waits are interrupted and cancelled immediately, same-host successor capture lands its predecessor first, active cleanup is defensive LIFO, committed inline geometry is restored exactly, and interrupted plays resolvefalsewithout an external carrier.DragDrop.onDragStart(), call the same-windowDockFlip.landFromPath(nativePath)synchronously beforeResize.start()and before publishingdrag:startto App. DockFlip's own registry identifies the first path-owned host, so both live-resize and proxy-mode splitter starts are covered without trusting an App descriptor or waiting for a worker acknowledgement. Missing addon, foreign path, or no active presentation is a cheap fail-open no-op.DockSplitter.onDragStart()App-side and semantic: after Main admission it captures the direct pair, projects optional proxy paint, and opens the inherited logical gesture under its generation fence. Add the exact trusted-pointer Workstation journey plus focused Main/DockFlip/DockSplitter lifecycle and order arms.Contract Ledger
LayoutAdapter.projectSplitNode()DragDrop+DockFliphost registry;MotionSignalobservability onlyDockSplitter+ main-threadResize+ ADR 0029 §2.1resizeSplitDecision Record impact
Aligned with ADR 0029 §2.1. This restores the existing state-ownership boundary; it adds no persisted field, operation, or public API and does not require an ADR amendment.
Acceptance Criteria
dockModel.neo-dashboard-dock-animating/ fixed-stage window before grabbing the enclosing outer splitter.DockFlip.land({hostId})is remote, requires one host, is idempotent, retires captured First state, interrupts pending frame/timer waits without servicing either carrier, serializes same-host successor capture, restores active fixed stages and exact inline styles without destroying the addon, and resolves interrupted plays.DragDropuses DockFlip's own path-to-host registry to land presentation synchronously beforeResize.start()and Appdrag:startdelivery. A held App handler plus immediate native move cannot mutate while fixed-stage presentation remains; live and proxy modes are covered, while missing addon/foreign path/no motion stay fail-open and synchronous.Out of Scope
DockSplitter; flex projection owns descendant stretch.Avoided Traps
dockNodeIdis the semantic selector.Related
Parent epic: #13158
Architecture: D#17818
Resolved predecessor: #17820 / PR #17849
Nested flex precedent: #14985 / PR #15018
Recent drop-boundary repair: #17926 / PR #17939
Origin Session ID: 4426fb43-4968-4084-832e-1830de2e8747
Retrieval Hint:
Workstation nested column outer splitter retained tab stale cross-axis widthRetrieval Hint:
fa20136f29 DockFlip fixed-stage MotionSignal DockSplitter land before capture— Emmy (GPT-5.6 Sol Ultra, Codex)