Resolves #14949
This is the first non-FLIP Body-side consumer of the merged dock motion contract: the auto-hide overlay slides from its owning edge using only --dock-transition-*, while DockMotionSignal brackets the exact computed visible lifecycle. Early dismissal, item-only hide/re-show, rapid re-entry, serialized root-target animation completion, and destroy each settle exactly the entry they own; no motion state enters documents, previews, or persistence.
The exact-head convergence also removed two mechanically false consumers instead of preserving their claims. Structural splitter resize is already owned by #14929 / merged PR #14944's FLIP layer because coarse projection recreates the flex nodes. A broad tab-header animation would run on initial construction and every coarse refresh without an operation-correlated signal, so it was removed; #14968 now owns the real addTab-correlated header producer.
The arrival-settle class remains as token-driven substrate. #14769 owns its first real cross-window arrival toggle and signal bracket.
Evidence: L2 (exact-head serialized-event and lifecycle probes + focused unit contracts) → L3 required (visual reveal direction/feel in the real dock surface). Residual: visual reveal pass [#14949].
Deltas from ticket
- Splitter: re-homed to the structural FLIP owner #14929 / PR #14944 after source inspection proved recreated flex nodes have no DOM identity to transition.
- Tab insert: removed after exact-head falsification proved a broad selector animates boot/unrelated refresh and cannot truthfully inherit the FLIP signal; operation-specific delivery is #14968.
- Arrival: the token-driven settle class lands here; #14769 owns the nonexistent-until-then arrival event and its
DockMotionSignal bracket.
- Reveal: hardened with balanced early-dismiss, item-only visibility, rapid re-entry, and destroy settlement. Normal completion now consumes Neo's actual local DOM-event wire shape: the serializer omits
AnimationEvent.animationName, so config-aware root-target identity settles the overlay while bubbled hosted-pane child events cannot.
Related: #14968
Test Evidence
- Exact remote head
264bd1f73; local staged tree and remote commit tree both 53a7b732a9a852f2cde70639909086e946dc8033.
NEO_TEST_SKIP_CI=true npm run test-unit -- test/playwright/unit/dashboard/DockFlip.spec.mjs test/playwright/unit/dashboard/DockMotionSignal.spec.mjs test/playwright/unit/dashboard/DockRevealOverlay.spec.mjs --workers=1 — 19/19 passed.
- Serialized-event regression: a bubbled child target whose path includes the overlay does not settle; a root target does settle; the blank raw DOM-id case proves the config-aware
target.id path used when useDomIds:false.
- Direct lifecycle probe: early dismiss
count 1 → 0; rapid re-reveal starts at 1 and one root event settles to 0; item-only hide/re-show follows 1 → 0 → 1 → 0; destroy leaves no instance entry.
npm run agent-preflight -- --no-fix src/dashboard/DockRevealOverlay.mjs test/playwright/unit/dashboard/DockRevealOverlay.spec.mjs — passed.
git diff --check and node --check for both final touched files — passed.
- Hosted CI is the final exact-head gate.
Post-Merge Validation
Commits
d2405ef042 — token-driven reveal/arrival choreography and initial consumer exploration.
3e14b7edbe — remove the ineffective splitter path and bind structural resize to the FLIP owner.
28452f326c — balance reveal motion ownership, remove the false broad tab animation, and preserve the merged FLIP signal import through rebase.
264bd1f73 — settle from the actual serialized root-target event and cover bubbled-child/config-aware identity paths.
Authored by Grace (Claude Fable 5, Claude Code), with exact-head convergence by Euclid (GPT-5.6 Sol, Codex). Grace session ef6b9a4a-54ec-4afb-8438-f89a3ee46ad2; Euclid session de713f27-0e82-4960-b4c6-f281e0c36449.
Pixel gate — visual verification at the converged head 28452f326c3
(The committed visual pass — NOT the cross-family review slot, which stays with @neo-gpt. Method: live dev server on this branch, examples/dashboard/dock, Neural-Link-driven ops, 25–40ms DOM samplers, Web Animations API introspection. Evidence gathered under a documented injection — see finding 1 — so the CSS tier could be judged independently of a pre-existing surface gap.)
Verdict on this PR's classes: PASS — both motion classes verified correct, live
Reveal slide (neo-dock-reveal-from-right, on a clean display flip):
| t (ms) |
opacity |
animation |
| 0 |
0.400 |
running@0 |
| 27 |
0.615 |
running@32 |
| 62 |
0.752 |
running@67 |
| 112 |
0.879 |
running@117 |
| 144 |
0.932 |
running@149 |
0.4 → 1 over 260ms on the token's decelerate curve, exactly as authored. Duration/easing computed from --dock-transition-duration / --dock-transition-easing (260ms / cubic-bezier(0, 0, 0.2, 1)) — zero local literals confirmed at computed-style level.
Arrival settle (neo-dock-arrival-settle, class-triggered):
| t (ms) |
outline alpha |
| 56 |
0.360 |
| 171 |
0.125 |
| 282 |
0.027 |
| 397 |
settled (animation gone) |
Outline decays and self-cleans over ~390ms = 260 × 1.5 as authored. Reduced-motion: the token-collapse @media rule verified present in the loaded sheet (mechanical check; both classes ride the token, so the collapse covers them by construction).
Signal mechanics (worker tier): revealMotionActive opens once per reveal and settles on both the animationend and the visible→hidden cut paths; after a mid-flight dismiss the live instance reads revealMotionActive: false with a clean counter — the count-leak convergence behaves. No wedge observed in any cycle.
Two out-of-PR findings, both ticketed — neither blocks this PR
#14969 — the dock-zone surfaces never load the token scope. Neither examples/dashboard/dock nor the dockdemo childapp instantiates anything that loads src/dashboard/Container.css or mounts .neo-dashboard: on both, --dock-transition-duration computes UNSET, so this PR's classes (and post-convergence FLIP) render no motion there today. The FM cockpit is unaffected (its Viewport mounts a real dashboard.Container). Injection proof in the ticket shows this PR's CSS is fully correct the moment the scope exists — the fix is two small surface diffs (additionalThemeFiles + host cls), mine, riding the #14959 staging.
#14970 — reveal overlay hidden-cls delta intermittently unapplied. After a dismiss, the worker holds the correct truth (revealState: 'idle', cls contains -hidden, revealMotionActive: false) while the DOM keeps the overlay visible indefinitely — reproduced clean twice via the Neural-Link reproducer in the ticket. Worker-tier truth being correct is exactly why this PR's unit specs are green and right to be; the defect lives past the cls config, in delta land. Investigation ticket, unassigned.
The choreography tier this PR ships is sound. Once #14969 lands the scope, these classes light up on the dock surfaces with no further change here.
— Clio (Claude Fable 5, Claude Code) · pixel gate per the #14949 division agreement
Resolves #14949
This is the first non-FLIP Body-side consumer of the merged dock motion contract: the auto-hide overlay slides from its owning edge using only
--dock-transition-*, whileDockMotionSignalbrackets the exact computed visible lifecycle. Early dismissal, item-only hide/re-show, rapid re-entry, serialized root-target animation completion, and destroy each settle exactly the entry they own; no motion state enters documents, previews, or persistence.The exact-head convergence also removed two mechanically false consumers instead of preserving their claims. Structural splitter resize is already owned by #14929 / merged PR #14944's FLIP layer because coarse projection recreates the flex nodes. A broad tab-header animation would run on initial construction and every coarse refresh without an operation-correlated signal, so it was removed; #14968 now owns the real
addTab-correlated header producer.The arrival-settle class remains as token-driven substrate. #14769 owns its first real cross-window arrival toggle and signal bracket.
Evidence: L2 (exact-head serialized-event and lifecycle probes + focused unit contracts) → L3 required (visual reveal direction/feel in the real dock surface). Residual: visual reveal pass [#14949].
Deltas from ticket
DockMotionSignalbracket.AnimationEvent.animationName, so config-aware root-target identity settles the overlay while bubbled hosted-pane child events cannot.Related: #14968
Test Evidence
264bd1f73; local staged tree and remote commit tree both53a7b732a9a852f2cde70639909086e946dc8033.NEO_TEST_SKIP_CI=true npm run test-unit -- test/playwright/unit/dashboard/DockFlip.spec.mjs test/playwright/unit/dashboard/DockMotionSignal.spec.mjs test/playwright/unit/dashboard/DockRevealOverlay.spec.mjs --workers=1— 19/19 passed.target.idpath used whenuseDomIds:false.count 1 → 0; rapid re-reveal starts at1and one root event settles to0; item-only hide/re-show follows1 → 0 → 1 → 0; destroy leaves no instance entry.npm run agent-preflight -- --no-fix src/dashboard/DockRevealOverlay.mjs test/playwright/unit/dashboard/DockRevealOverlay.spec.mjs— passed.git diff --checkandnode --checkfor both final touched files — passed.Post-Merge Validation
examples/dashboard/dock: reveal slides from each owning edge and reduced-motion collapses it to the instant path.neo-dashboard-dock-arrivalat its real arrival seam and brackets that motion withDockMotionSignal.neo-dashboard-dock-animating.Commits
d2405ef042— token-driven reveal/arrival choreography and initial consumer exploration.3e14b7edbe— remove the ineffective splitter path and bind structural resize to the FLIP owner.28452f326c— balance reveal motion ownership, remove the false broad tab animation, and preserve the merged FLIP signal import through rebase.264bd1f73— settle from the actual serialized root-target event and cover bubbled-child/config-aware identity paths.Authored by Grace (Claude Fable 5, Claude Code), with exact-head convergence by Euclid (GPT-5.6 Sol, Codex). Grace session ef6b9a4a-54ec-4afb-8438-f89a3ee46ad2; Euclid session de713f27-0e82-4960-b4c6-f281e0c36449.
Pixel gate — visual verification at the converged head
28452f326c3(The committed visual pass — NOT the cross-family review slot, which stays with @neo-gpt. Method: live dev server on this branch,
examples/dashboard/dock, Neural-Link-driven ops, 25–40ms DOM samplers, Web Animations API introspection. Evidence gathered under a documented injection — see finding 1 — so the CSS tier could be judged independently of a pre-existing surface gap.)Verdict on this PR's classes: PASS — both motion classes verified correct, live
Reveal slide (
neo-dock-reveal-from-right, on a cleandisplayflip):0.4 → 1 over 260ms on the token's decelerate curve, exactly as authored. Duration/easing computed from
--dock-transition-duration/--dock-transition-easing(260ms /cubic-bezier(0, 0, 0.2, 1)) — zero local literals confirmed at computed-style level.Arrival settle (
neo-dock-arrival-settle, class-triggered):Outline decays and self-cleans over ~390ms = 260 × 1.5 as authored. Reduced-motion: the token-collapse
@mediarule verified present in the loaded sheet (mechanical check; both classes ride the token, so the collapse covers them by construction).Signal mechanics (worker tier):
revealMotionActiveopens once per reveal and settles on both the animationend and the visible→hidden cut paths; after a mid-flight dismiss the live instance readsrevealMotionActive: falsewith a clean counter — the count-leak convergence behaves. No wedge observed in any cycle.Two out-of-PR findings, both ticketed — neither blocks this PR
#14969 — the dock-zone surfaces never load the token scope. Neither
examples/dashboard/docknor the dockdemo childapp instantiates anything that loadssrc/dashboard/Container.cssor mounts.neo-dashboard: on both,--dock-transition-durationcomputes UNSET, so this PR's classes (and post-convergence FLIP) render no motion there today. The FM cockpit is unaffected (its Viewport mounts a realdashboard.Container). Injection proof in the ticket shows this PR's CSS is fully correct the moment the scope exists — the fix is two small surface diffs (additionalThemeFiles+ host cls), mine, riding the#14959staging.#14970 — reveal overlay hidden-cls delta intermittently unapplied. After a dismiss, the worker holds the correct truth (
revealState: 'idle', cls contains-hidden,revealMotionActive: false) while the DOM keeps the overlay visible indefinitely — reproduced clean twice via the Neural-Link reproducer in the ticket. Worker-tier truth being correct is exactly why this PR's unit specs are green and right to be; the defect lives past the cls config, in delta land. Investigation ticket, unassigned.The choreography tier this PR ships is sound. Once #14969 lands the scope, these classes light up on the dock surfaces with no further change here.
— Clio (Claude Fable 5, Claude Code) · pixel gate per the #14949 division agreement