Skip to content

refactor(dashboard): remove the legacy layout engine (dockview-only) - #266

Merged
aterrylu merged 1 commit into
mainfrom
terry/remove-legacy-layout
Jun 28, 2026
Merged

refactor(dashboard): remove the legacy layout engine (dockview-only)#266
aterrylu merged 1 commit into
mainfrom
terry/remove-legacy-layout

Conversation

@aterrylu

Copy link
Copy Markdown
Owner

Summary

Removes the legacy layout engine now that dockview is the default (ADR-047 "delete legacy" phase; follows #263). This is the atomic deletion the ADR planned: ~3,500 LOC of fragile hand-rolled layout code comes out, leaving dockview as the only engine.

No user-facing behavior change — dockview already shipped on by default in #263 and is untouched here. This PR is pure subtraction + two small reconciliation fixes.

What's deleted

graph LR
  subgraph Gone["Deleted (~3.5k LOC)"]
    direction TB
    A["layoutTree.ts (+723-line test)"]
    B["SessionMountLayer<br/>(detached overlay)"]
    C["SplitLayout · PaneSlot<br/>DropZoneOverlay · TabBar · LayoutContext"]
    D["groups workspace-swap<br/>+ 11 split-pane store actions"]
    E["layoutEngine flag<br/>+ dual-engine branches"]
    F["react-resizable-panels dep"]
  end
  subgraph Kept["Remaining engine"]
    G["dockview-react<br/>(the only layout engine)"]
  end
  Gone -.retired.-> G
Loading
  • 8 files deleted: layoutTree.ts (+ its 723-line test), SplitLayout.tsx, PaneSlot.tsx, SessionMountLayer.tsx, LayoutContext.tsx, DropZoneOverlay.tsx, TabBar.tsx.
  • store.ts: removed the layout/focusedLeafId/groups/activeGroupId state + 11 binary-tree/group actions + their persist entries; the layoutEngine flag is gone (dual-path actions collapse to their dockview body).
  • DragContext.tsx: kept the drag serialization (DRAG_TYPE/encodeDragData/decodeDragData/DragData — dockview still uses these); removed the legacy React DragProvider/useDragContext.
  • react-resizable-panels removed from dependencies.
  • Legacy keyboard shortcuts (Ctrl+D / Ctrl+Shift+D / Ctrl+W) removed — they drove the legacy tree and were half-broken under dockview. dockview-native keybinds are a planned follow-up (Terry's call: drop now, port later).

Re-sourced: the sidebar's on-screen-agent indicator

The only behavioral wiring change. The sidebar marked which agent rows are currently on-screen via allTabPanes(layout) (the deleted tree). It now reads a new visiblePaneIds store field that DockviewLayout publishes from its live panel set (onDidLayoutChange + after restore/drop). Cleared on unmount so it doesn't go stale when the dock empties.

Review fixes

A code-reviewer pass on the diff caught two reconciliation gaps (both from removing the layout tree as the single reconcile source) — fixed:

  1. Closed-preview orphan: closing a preview while another pane was active left a blank "Preview" tab (the prune only ran on sessions changes). The prune effect now also triggers on previewPanes.
  2. Stale visiblePaneIds on unmount: killing the active pane left the sidebar highlighting a now-empty dock. visiblePaneIds is now cleared on DockviewLayout unmount.

Testing

  • make check green: biome + tsc --build + 613 server tests + 227 dashboard tests.
  • Two agent reviews: one mapped the full removal surface (what to delete vs preserve — caught that DragContext's serialization is still needed by dockview); one reviewed the diff and found the two reconciliation gaps above (fixed).
  • Runtime gate = CI e2e (real Playwright). dockview's interactive behavior — click=solo, drag=compose, workspace restore, cold-reload, hidden-panel visibility, overlay suppression — was exhaustively Playwright-verified in feat(dashboard): rebuild tabs + split-pane layout on dockview, default on #263 and is unchanged here, so this PR leans on CI e2e rather than re-running that suite locally.

Risks

🤖 Generated with Claude Code

https://claude.ai/code/session_01MGMW4cbhv5Le8wka7Th8bS

dockview shipped as the default in #263; this deletes the legacy binary-tree
layout, the detached-terminal overlay (SessionMountLayer), the `groups` system,
the `layoutEngine` flag, and react-resizable-panels (ADR-047 "delete legacy").

Removed: layoutTree(.ts/.test), SplitLayout, PaneSlot, SessionMountLayer,
LayoutContext, DropZoneOverlay, TabBar (8 files); the binary-tree/group slices of
the store (layout/focusedLeafId/groups/activeGroupId + 11 split-pane actions) and
their persist entries; the dual-engine branches (switchPane/open* collapse to
dockview, fetchSessions legacy prune dropped); the legacy keyboard shortcuts
(Ctrl+D/Ctrl+Shift+D/Ctrl+W — dockview-native keybinds are a follow-up); the
DragProvider/useDragContext React context (kept DRAG_TYPE/encode/decodeDragData).

Re-sourced the sidebar's on-screen-agent indicator from dockview: DockviewLayout
publishes its visible panel ids to a new `visiblePaneIds` store field (via
onDidLayoutChange) that the sidebar reads, replacing allTabPanes(layout).

Net ~3.5k LOC removed. dockview is now the only layout engine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGMW4cbhv5Le8wka7Th8bS
@aterrylu
aterrylu enabled auto-merge (squash) June 28, 2026 19:36

@nox-0x nox-0x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving — clean atomic deletion of the legacy layout engine; the two reconciliation fixes (prune effect now triggers on previewPanes change; visiblePaneIds cleared on DockviewLayout unmount) close the obvious gaps a tree-as-source-of-truth removal would have left. Sound reasoning throughout:

  • The visiblePaneIds round-trip (DockviewLayout's onDidLayoutChange → store → Sidebar memo'd Set) replaces allTabPanes(layout) cleanly. pushVisible is stable ([] deps) and fires on all add/remove/move events.
  • CreateAgentPanel no longer self-closes — verified spawnSession calls switchPane({type:'session',id}) on success (store.ts:574), which solo-replaces the create-agent panel via syncToActive.
  • Effect ordering safe: syncToActive (mount-restore) runs before pruneDead (declaration order), so newly-added previews/sessions never get pruned mid-add.
  • Removing the legacy-only pruneStaleSessionTabs branch in fetchSessions is correct — dockview owns topology and pruneDead handles dead-session panels.
  • Tests trimmed to the actual surface (switchPane semantics under dockview); legacy split/move/closeTab suites correctly gone with the code they exercised.

Minor follow-up (non-blocking): README.md:109 still lists react-resizable-panels in the tech-stack line — the dep is gone now, swap to dockview-react whenever convenient.

@aterrylu
aterrylu merged commit a2815cb into main Jun 28, 2026
4 of 5 checks passed
@aterrylu
aterrylu deleted the terry/remove-legacy-layout branch June 28, 2026 19:41
aterrylu added a commit that referenced this pull request Jun 28, 2026
The `Ctrl+D splits the focused leaf` e2e test (e2e/layout.spec.ts) read the
removed binary-tree `layout` via the store bridge (`leafCount`) and pressed the
removed Ctrl+D shortcut — both deleted with the legacy layout engine (#266), so
it failed on main (e2e isn't a required check, so #266 merged with it red).

Remove that test + its now-dead `leafCount` helper; keep the still-valid
tab-switching test (Org Chart → Templates) verbatim. dockview-native split
keybinds + their e2e coverage are a planned follow-up.


Claude-Session: https://claude.ai/code/session_01MGMW4cbhv5Le8wka7Th8bS

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants