Skip to content

feat(wework): redesign split task workbench - #2611

Merged
qdaxb merged 4 commits into
mainfrom
feature/wework-split-workbench
Aug 12, 2026
Merged

qdaxb merged 4 commits into
mainfrom
feature/wework-split-workbench

Conversation

@qdaxb

@qdaxb qdaxb commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

变更概述

  • 将桌面任务区重构为单任务叶节点的分屏树,每个窗格只承载一个任务,移除分屏内嵌套会话标签的旧路径
  • 支持从左侧任务列表拖入当前窗格的左、右、上、下创建分屏;中央落点更大,用于替换当前窗格任务
  • 每个窗格拥有独立标题栏、打开位置、环境、底部终端、右侧面板、聚焦与关闭操作
  • 支持拖动分隔线调整尺寸、单独查看任务并通过按钮或 Escape 返回分屏
  • 某个窗格的会话全部关闭后自动回收窗格;布局按工作区标签持久化并在任务删除后自动修剪
  • 复用稳定任务宿主与 portal,分屏创建只更新布局和挂载目标,保留终端、浏览器和会话实例
  • 将任务草稿统一到 Provider 的按任务作用域状态,避免分屏草稿、插件试用和工作区迁移出现多份状态源

性能

  • 用户录制中拖拽完成曾出现约 570 ms pointerup 和约 2.1 s 长帧,主要成本来自任务页重新挂载
  • 最终真实桌面 E2E 中,分屏创建耗时 670 ms;任务内容、终端和面板状态保持,不再重建完整任务页

验证

  • pre-push:Wework ESLint、TypeScript、3589 项单测全部通过
  • WorkbenchProvider.test.tsx:159/159
  • DesktopWorkbenchLayout.test.tsx:184/184
  • 分屏布局与窗格栈聚焦测试:23/23
  • 真实 Tauri ai:verify:创建两个真实 Codex 任务并完成拖入分屏、独立标题栏、环境隔离、单任务聚焦、恢复与关闭回收验证
  • 桌面 E2E:完整通过,11 个核心阶段均生成截图;分屏创建、面板隔离、尺寸调整、重载恢复和关闭回单屏均有断言
  • 截图链已逐张审查:未发现标题栏共享、状态串屏、布局遮挡、空任务或关闭后残留

核心交互结果

  • 单屏保持完整任务宽度和原有操作
  • 分屏后每个任务都有自己的标题栏与任务级操作
  • 环境、底栏和右侧栏只影响所属窗格
  • 支持临时单独查看任一任务并恢复原分屏
  • 最后一个会话关闭后对应窗格自动关闭
  • 重载后恢复分屏结构、比例与任务归属

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds split-pane workbench state, rendering, drag-and-drop, persistence, pane-specific actions, visibility-aware sessions, updated desktop automation, and end-to-end coverage.

Changes

Split workbench

Layer / File(s) Summary
Split layout model
wework/src/components/layout/workbenchSplitLayout.ts, wework/src/components/layout/workbenchSplitLayout.test.ts
Adds typed split-tree state, pane operations, persistence validation, pruning, and layout tests.
Pane stack and sidebar drag
wework/src/components/layout/workbenchPaneStack.tsx, wework/src/components/layout/SidebarSortableList.tsx, wework/src/components/layout/DesktopSidebar.tsx, wework/src/components/layout/workbenchPaneDrag.ts, wework/src/components/layout/workbenchPaneIdentity.ts, wework/src/components/layout/workbenchPaneStack.module.css, wework/src/components/layout/workbenchPaneStack.test.tsx
Adds pane rendering, focus, resizing, drag-and-drop, compact layouts, runtime pane resolution, and sidebar drag payloads.
Workbench integration and portals
wework/src/components/layout/DesktopWorkbenchMain.tsx, wework/src/components/topnav/TitlebarActionsPortal.tsx, wework/src/components/layout/workspace-panels/*, wework/src/features/workbench/*, wework/src/i18n/locales/*, wework/src/components/layout/DesktopWorkbenchLayout.test.tsx, wework/package.json
Connects split panes to workbench state, grouped environment visibility, pane-specific title-bar actions, workspace panels, contexts, localization, dependency wiring, and updated read-count tests.
Pane visibility and conversation state
wework/src/components/layout/useWorkbenchPaneSession.ts, wework/src/components/chat/ScrollableMessageArea.tsx, wework/src/components/chat/ScrollableMessageArea.test.tsx, wework/src/features/workbench/WorkbenchProvider.test.tsx, wework/src/components/chat/MessageList.tsx, wework/src/components/chat/MessageList.virtualization.test.tsx, wework/src/components/chat/composer/ModelSelector.tsx
Refreshes hidden runtime transcripts, preserves conversation scroll state during suspended auto-scroll, controls measurement persistence, and closes disabled model selectors.
Desktop automation and scenario coverage
wework/src/e2e/automation.ts, wework/e2e/desktop/*
Scopes automation to rendered active panes, adds explicit drag commands, updates active-pane scroll checks, and registers a split-workbench end-to-end scenario.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Sidebar
  participant PaneStack
  participant WorkbenchLayout
  participant WorkbenchPane
  Sidebar->>PaneStack: Dispatch sidebar pane drag data
  PaneStack->>WorkbenchLayout: Split or move pane
  WorkbenchLayout-->>PaneStack: Persist layout state
  PaneStack->>WorkbenchPane: Render focused and visible pane
  WorkbenchPane-->>PaneStack: Render pane-specific header actions
Loading

Possibly related PRs

Suggested labels: ci:all

Suggested reviewers: micro66, icycrystal4

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: redesigning the Wework split task workbench.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/wework-split-workbench

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qdaxb
qdaxb enabled auto-merge August 12, 2026 06:27

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wework/src/components/layout/DesktopWorkbenchMain.tsx (1)

3936-3952: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Apply paneVisible to the panel root visibility.

When open is true and paneVisible is false, the root remains aria-hidden="false", uses pointer-events-auto, and keeps its height. Apply the hidden, non-interactive state at the BottomWorkspacePanel root while preserving cached content.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/DesktopWorkbenchMain.tsx` around lines 3936 -
3952, Update BottomWorkspacePanel’s root visibility handling so
paneVisible=false applies the hidden, non-interactive state even when open=true:
set the root’s aria-hidden, pointer-events, and height behavior from paneVisible
while preserving the mounted/cached content. Ensure the caller’s paneVisible
prop from DesktopWorkbenchMain continues to drive this behavior.
🧹 Nitpick comments (9)
wework/src/e2e/automation.ts (1)

365-383: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Align interaction targeting with snapshot filtering.

Inactive split panes remain rendered and can contain duplicate controls. Filter them from findRenderedDesktopControlElements so interaction commands target the same surface that desktopControlSnapshot exposes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/e2e/automation.ts` around lines 365 - 383, Update
findRenderedDesktopControlElements to exclude elements where
desktopControlElementInInactiveSurface returns true, so interaction targeting
matches the filtering used by desktopControlSnapshot. Preserve the existing
selector lookup and rendered-element filtering while removing controls from
inactive split panes.
wework/src/components/layout/workbenchSplitLayout.test.ts (1)

95-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a size assertion when a group closes from a three-way split.

This test asserts only the child count after closeWorkbenchGroup. It does not assert the resulting sizes. A size-index defect in removeGroup therefore passes unnoticed. Assert the normalized sizes array here.

💚 Proposed assertion
     const closed = closeWorkbenchGroup(third, third.focusedGroupId)
     expect(closed.root.type === 'split' ? closed.root.children : []).toHaveLength(2)
+    expect(closed.root.type === 'split' ? closed.root.sizes : []).toEqual([50, 50])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchSplitLayout.test.ts` around lines 95 -
106, Add an assertion in the “flattens same-orientation splits and closes groups
cleanly” test after closeWorkbenchGroup verifies the resulting normalized sizes
array, alongside the existing child-count assertion, so removeGroup size-index
defects are detected.
wework/src/components/layout/workbenchPaneStack.tsx (4)

445-527: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated labels object.

The same 17-key labels object is written twice, at Lines 450-471 and Lines 505-526. The two copies must stay in sync manually. The object is also rebuilt on every render.

Build it once with useMemo keyed on t, then pass the same value to both consumers.

As per coding guidelines: "Before adding code, search for and reuse existing components, services, utilities, and patterns; extract shared logic instead of duplicating it."

♻️ Proposed change
+  const labels = useMemo<WorkbenchLayoutLabels>(
+    () => ({
+      paneMenu: t('workbench.split_pane_menu', '分屏操作'),
+      splitLeft: t('workbench.split_left', '向左分屏'),
+      // ...remaining keys
+    }),
+    [t]
+  )

Then replace both inline labels={{ ... }} props with labels={labels}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.tsx` around lines 445 - 527,
Extract the duplicated 17-key labels object into a useMemo value keyed by t
within the component containing WorkbenchSplitActionsPortal and
WorkbenchLayoutRenderer. Replace both inline labels props with the shared labels
value, preserving all existing translation keys and fallback text.

Source: Coding guidelines


91-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Split the oversized components.

SplitWorkbenchPaneStack spans roughly 440 lines and WorkbenchPaneGroup spans roughly 218 lines. WorkbenchLayoutRenderer also carries 20 props. This exceeds the project limit and makes the drag, focus, persistence, and rendering concerns hard to change independently.

Extract the sidebar drag listeners and the layout mutation callbacks into dedicated hooks, for example useWorkbenchSidebarPaneDrop and useWorkbenchLayoutActions. Group the renderer props into a single context or options object.

As per coding guidelines: "functions should remain focused, preferably under 50 lines."

Also applies to: 784-825

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.tsx` around lines 91 - 103,
Refactor SplitWorkbenchPaneStack and WorkbenchPaneGroup into focused units under
the project’s function-size guideline by extracting sidebar drag listeners into
a useWorkbenchSidebarPaneDrop hook and layout mutation callbacks into a
useWorkbenchLayoutActions hook. Consolidate WorkbenchLayoutRenderer’s large prop
list into a single context or options object, while preserving existing drag,
focus, persistence, and rendering behavior.

Source: Coding guidelines


336-386: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Move onPaneFocus out of the setLayout updaters.

closePane, closeGroup, and focusGroup call queueMicrotask(() => onPaneFocus(...)) inside the state updater. React treats updaters as pure functions and may invoke them more than once, including in StrictMode development. onPaneFocus triggers openRuntimeTask, so a double invocation issues a duplicate navigation.

Compute the next state first, then schedule the callback outside the updater.

♻️ Proposed shape for `closeGroup`
   const closeGroup = useCallback(
     (groupId: string) => {
       if (focusedViewGroupId === groupId) setFocusedViewGroupId(null)
+      const next = closeWorkbenchGroup(layout, groupId)
+      const nextPane = next.focusedPaneKey ? resolveCachedPane(next.focusedPaneKey) : null
+      setLayout(next)
+      if (nextPane) queueMicrotask(() => onPaneFocus(nextPane))
-      setLayout(current => {
-        const next = closeWorkbenchGroup(current, groupId)
-        const nextPaneKey = next.focusedPaneKey
-        const nextPane = nextPaneKey ? resolveCachedPane(nextPaneKey) : null
-        if (nextPane) queueMicrotask(() => onPaneFocus(nextPane))
-        return next
-      })
     },
-    [focusedViewGroupId, onPaneFocus, resolveCachedPane, setLayout]
+    [focusedViewGroupId, layout, onPaneFocus, resolveCachedPane]
   )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.tsx` around lines 336 - 386,
Move the onPaneFocus scheduling out of the setLayout updater in closePane,
closeGroup, and focusGroup. Compute and retain the resulting state and focused
pane from the updater, then queue the callback once after setLayout completes,
preserving the existing pane-selection behavior without triggering side effects
from the pure updater.

159-172: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Return the existing layout when pruning makes no changes. DesktopWorkbenchMain memoizes runtimePaneKeys, so validRuntimeKeys is not recreated on every render and this effect does not loop from prop identity. pruneWorkbenchLayout still allocates new state and node objects for a no-op prune, causing an unnecessary render and localStorage write when the runtime-key list changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.tsx` around lines 159 - 172,
The runtime-key pruning effect in DesktopWorkbenchMain should preserve the
existing layout when pruneWorkbenchLayout makes no changes. Update
pruneWorkbenchLayout to return the original layout object and node references
for a no-op prune, so the setLayout call avoids unnecessary renders and
localStorage writes while still returning the fallback layout when pruning
yields no valid layout.
wework/src/components/layout/SidebarSortableList.tsx (1)

105-139: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Confirm the synchronous handled mutation contract.

handleDragEnd reads dragEndData.handled immediately after dispatchWorkbenchSidebarPaneDragEnd. This only works because window.dispatchEvent runs listeners synchronously and SplitWorkbenchPaneStack mutates the same detail object. Any future listener that defers its decision (for example inside queueMicrotask or setTimeout) will silently fall through to internal reordering and produce a duplicate move.

Add a short comment that documents this requirement so the contract survives refactoring.

♻️ Proposed comment
+        // Listeners run synchronously, so a split drop target can claim this drag by
+        // setting `handled` on the shared detail object before dispatch returns.
         dispatchWorkbenchSidebarPaneDragEnd(dragEndData)
         if (dragEndData.handled) return
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/SidebarSortableList.tsx` around lines 105 - 139,
Document the synchronous handled-mutation contract at the
dispatchWorkbenchSidebarPaneDragEnd call in handleDragEnd: explain that
listeners must mutate the shared dragEndData.handled value during synchronous
window.dispatchEvent processing, because the immediate check determines whether
internal reordering proceeds. Keep the comment short and do not change behavior.
wework/src/components/layout/workbenchPaneStack.module.css (1)

5-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Do not drive production styling from data-testid values.

These four rules select elements by their test identifiers. Test ids are non-semantic hooks. A test refactor that renames open-code-server-titlebar-button or open-local-workspace-picker-button silently breaks the compact split header without failing any test.

Add a dedicated attribute for this purpose, for example data-pane-header-control="workspace-picker", and select on that instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.module.css` around lines 5 -
22, Replace the data-testid selectors in the compact-header rules within the
stylesheet with a dedicated semantic pane-header control attribute, such as
data-pane-header-control, using distinct values for the workspace titlebar,
code-server button, workspace location label, and local workspace picker. Update
the corresponding component markup to add these attributes while preserving the
existing responsive styling behavior.
wework/src/components/layout/workbenchPaneStack.test.tsx (1)

288-326: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Restore the document.elementsFromPoint spy after this test.

vi.spyOn(document, 'elementsFromPoint') at Line 300 is never restored. The stub persists for every later test in this file and returns a detached element from a finished test. The stub is currently inert because handleSidebarDragMove checks sidebarDragActiveRef first, but a future change to the drag path makes the later tests depend on stale state.

Capture the spy and restore it, or restore it in an afterEach.

♻️ Proposed change
     const target = await screen.findByTestId(/^drop:.+:right$/)
-    vi.spyOn(document, 'elementsFromPoint').mockReturnValue([target])
+    const elementsFromPoint = vi.spyOn(document, 'elementsFromPoint').mockReturnValue([target])
+    onTestFinished(() => elementsFromPoint.mockRestore())

Import onTestFinished from vitest, or add an afterEach(() => vi.restoreAllMocks()) and move the beforeAll stubs into beforeEach.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workbenchPaneStack.test.tsx` around lines 288 -
326, Restore the document.elementsFromPoint spy created in the “accepts a task
dragged from the sidebar onto a split edge” test after that test completes,
using a captured spy restore or the file’s test cleanup mechanism. Ensure later
tests do not retain the detached target element while preserving the existing
drag behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/e2e/desktop/scenarios/split-workbench.scenario.mjs`:
- Around line 361-368: Remove the localized text constraint from the right
drop-target wait in wework/e2e/desktop/scenarios/split-workbench.scenario.mjs
lines 361-368, relying on the right-position and data-over selectors. Also
remove the localized aria-label constraint at lines 506-512 and rely on
aria-pressed="true" instead.

In `@wework/src/components/layout/DesktopSidebar.tsx`:
- Around line 2590-2593: Replace the duplicated runtime pane-key template
literal with getWorkbenchPaneKey in all three DesktopSidebar.tsx sites: lines
2590-2593, 3719-3722, and 4120-4123. Pass currentRuntimeTask with
workspace.deviceId and task.taskId, and currentProject: null, preserving each
callback’s existing title handling.

In `@wework/src/components/layout/workbenchPaneStack.tsx`:
- Around line 387-404: Update handleDragEnd to notify the parent via onPaneFocus
after moving the pane, matching the sidebar drop handler’s behavior. Use the
dragged pane key or resulting pane identity as required by the existing
callback, and preserve the current layout update and focus-group handling.

In `@wework/src/components/layout/workbenchSplitLayout.ts`:
- Around line 413-425: Update removeGroup to preserve each child’s original size
before filtering removes the target group, matching the approach used by
pruneNode and removeEmptyGroups. Build the surviving children together with
their corresponding node.sizes entries, then normalize those captured sizes
after recursive removal so later siblings retain their original pane sizes.

In `@wework/src/e2e/automation.ts`:
- Around line 1422-1426: Update the select-control handling around
findRenderedDesktopControlElement to first detect an undefined result and throw
a missing-element error for command.selector; only perform the HTMLSelectElement
type check after an element is found, preserving the existing wrong-type error
for non-select elements.

---

Outside diff comments:
In `@wework/src/components/layout/DesktopWorkbenchMain.tsx`:
- Around line 3936-3952: Update BottomWorkspacePanel’s root visibility handling
so paneVisible=false applies the hidden, non-interactive state even when
open=true: set the root’s aria-hidden, pointer-events, and height behavior from
paneVisible while preserving the mounted/cached content. Ensure the caller’s
paneVisible prop from DesktopWorkbenchMain continues to drive this behavior.

---

Nitpick comments:
In `@wework/src/components/layout/SidebarSortableList.tsx`:
- Around line 105-139: Document the synchronous handled-mutation contract at the
dispatchWorkbenchSidebarPaneDragEnd call in handleDragEnd: explain that
listeners must mutate the shared dragEndData.handled value during synchronous
window.dispatchEvent processing, because the immediate check determines whether
internal reordering proceeds. Keep the comment short and do not change behavior.

In `@wework/src/components/layout/workbenchPaneStack.module.css`:
- Around line 5-22: Replace the data-testid selectors in the compact-header
rules within the stylesheet with a dedicated semantic pane-header control
attribute, such as data-pane-header-control, using distinct values for the
workspace titlebar, code-server button, workspace location label, and local
workspace picker. Update the corresponding component markup to add these
attributes while preserving the existing responsive styling behavior.

In `@wework/src/components/layout/workbenchPaneStack.test.tsx`:
- Around line 288-326: Restore the document.elementsFromPoint spy created in the
“accepts a task dragged from the sidebar onto a split edge” test after that test
completes, using a captured spy restore or the file’s test cleanup mechanism.
Ensure later tests do not retain the detached target element while preserving
the existing drag behavior.

In `@wework/src/components/layout/workbenchPaneStack.tsx`:
- Around line 445-527: Extract the duplicated 17-key labels object into a
useMemo value keyed by t within the component containing
WorkbenchSplitActionsPortal and WorkbenchLayoutRenderer. Replace both inline
labels props with the shared labels value, preserving all existing translation
keys and fallback text.
- Around line 91-103: Refactor SplitWorkbenchPaneStack and WorkbenchPaneGroup
into focused units under the project’s function-size guideline by extracting
sidebar drag listeners into a useWorkbenchSidebarPaneDrop hook and layout
mutation callbacks into a useWorkbenchLayoutActions hook. Consolidate
WorkbenchLayoutRenderer’s large prop list into a single context or options
object, while preserving existing drag, focus, persistence, and rendering
behavior.
- Around line 336-386: Move the onPaneFocus scheduling out of the setLayout
updater in closePane, closeGroup, and focusGroup. Compute and retain the
resulting state and focused pane from the updater, then queue the callback once
after setLayout completes, preserving the existing pane-selection behavior
without triggering side effects from the pure updater.
- Around line 159-172: The runtime-key pruning effect in DesktopWorkbenchMain
should preserve the existing layout when pruneWorkbenchLayout makes no changes.
Update pruneWorkbenchLayout to return the original layout object and node
references for a no-op prune, so the setLayout call avoids unnecessary renders
and localStorage writes while still returning the fallback layout when pruning
yields no valid layout.

In `@wework/src/components/layout/workbenchSplitLayout.test.ts`:
- Around line 95-106: Add an assertion in the “flattens same-orientation splits
and closes groups cleanly” test after closeWorkbenchGroup verifies the resulting
normalized sizes array, alongside the existing child-count assertion, so
removeGroup size-index defects are detected.

In `@wework/src/e2e/automation.ts`:
- Around line 365-383: Update findRenderedDesktopControlElements to exclude
elements where desktopControlElementInInactiveSurface returns true, so
interaction targeting matches the filtering used by desktopControlSnapshot.
Preserve the existing selector lookup and rendered-element filtering while
removing controls from inactive split panes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 93339214-493b-4a8f-86b4-0cf1594cf4d2

📥 Commits

Reviewing files that changed from the base of the PR and between cf8aff9 and d7b39d0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (26)
  • wework/e2e/desktop/checkpoints.mjs
  • wework/e2e/desktop/modules/shared.mjs
  • wework/e2e/desktop/modules/window-attachment-flows.mjs
  • wework/e2e/desktop/run-checkpoints.mjs
  • wework/e2e/desktop/scenarios/split-workbench.scenario.mjs
  • wework/package.json
  • wework/src/components/layout/DesktopSidebar.tsx
  • wework/src/components/layout/DesktopWorkbenchLayout.test.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/SidebarSortableList.tsx
  • wework/src/components/layout/workbenchPaneDrag.ts
  • wework/src/components/layout/workbenchPaneIdentity.ts
  • wework/src/components/layout/workbenchPaneStack.module.css
  • wework/src/components/layout/workbenchPaneStack.test.tsx
  • wework/src/components/layout/workbenchPaneStack.tsx
  • wework/src/components/layout/workbenchSplitLayout.test.ts
  • wework/src/components/layout/workbenchSplitLayout.ts
  • wework/src/components/layout/workspace-panels/BottomWorkspacePanel.tsx
  • wework/src/components/layout/workspace-panels/RightWorkspacePanel.tsx
  • wework/src/components/layout/workspace-panels/WorkspacePanelActions.tsx
  • wework/src/components/topnav/TitlebarActionsPortal.tsx
  • wework/src/e2e/automation.ts
  • wework/src/features/workbench/WorkbenchProvider.tsx
  • wework/src/features/workbench/workbenchContextTypes.ts
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/zh-CN/common.json

Comment thread wework/src/e2e/automation.ts Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/e2e/automation.ts`:
- Around line 369-380: Update findActiveDesktopControlElements to return only
elements that pass desktopControlElementInInactiveSurface, removing the fallback
to the original elements when no active matches exist. Also update
desktopControlElementInInactiveSurface so a workspace-tab root matching
[data-workspace-tab-content][aria-hidden="true"] is treated as inactive, not
only its descendants.
- Around line 358-368: Update desktopControlElementInInactiveSurface and its use
in findActiveDesktopControlElements to treat elements inside inactive
data-workspace-tab-portal-owner wrappers as inactive, before applying the
existing surface checks and fallback selection. Preserve active portal controls
and existing inactive workbench behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cc61e536-1a59-437d-955c-b2dceed4a065

📥 Commits

Reviewing files that changed from the base of the PR and between d7b39d0 and 30f0ed6.

📒 Files selected for processing (10)
  • wework/e2e/desktop/checkpoints.mjs
  • wework/e2e/desktop/modules/shared.mjs
  • wework/package.json
  • wework/src/components/layout/DesktopSidebar.tsx
  • wework/src/components/layout/DesktopWorkbenchLayout.test.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/workspace-panels/RightWorkspacePanel.tsx
  • wework/src/e2e/automation.ts
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/zh-CN/common.json
🚧 Files skipped from review as they are similar to previous changes (9)
  • wework/e2e/desktop/checkpoints.mjs
  • wework/e2e/desktop/modules/shared.mjs
  • wework/src/i18n/locales/en/common.json
  • wework/package.json
  • wework/src/components/layout/DesktopWorkbenchLayout.test.tsx
  • wework/src/components/layout/workspace-panels/RightWorkspacePanel.tsx
  • wework/src/components/layout/DesktopSidebar.tsx
  • wework/src/i18n/locales/zh-CN/common.json
  • wework/src/components/layout/DesktopWorkbenchMain.tsx

Comment thread wework/src/e2e/automation.ts Resolved
Comment thread wework/src/e2e/automation.ts Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/components/chat/composer/ModelSelector.tsx`:
- Around line 152-156: Update the useEffect that handles disabled and open state
to call closeMenu() synchronously instead of scheduling it with
window.setTimeout. Preserve the existing guard and dependency array so the menu
closes immediately when disabled becomes true, preventing its actions from
remaining available.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5668c910-f5e0-4f21-99e3-7f806acba4a6

📥 Commits

Reviewing files that changed from the base of the PR and between 30f0ed6 and 7289fb5.

📒 Files selected for processing (3)
  • wework/src/components/chat/composer/ModelSelector.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/workbenchPaneStack.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • wework/src/components/layout/DesktopWorkbenchMain.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wework/src/components/layout/DesktopWorkbenchMain.tsx (1)

714-814: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Split these oversized modified files into cohesive modules.

These modified files exceed the 1000-line limit. Extract the independent responsibilities before merge.

  • wework/src/components/layout/DesktopWorkbenchMain.tsx#L714-L814: extract pane header, workspace-panel, and pane-session integration.
  • wework/src/components/layout/useWorkbenchPaneSession.ts#L151-L154: extract transcript hydration and refresh coordination from message and composer operations.
  • wework/src/features/workbench/WorkbenchProvider.test.tsx#L8116-L8167: move runtime-pane transcript tests into focused test files.
  • wework/src/components/chat/ScrollableMessageArea.tsx#L207-L268: extract scroll snapshot and suspension coordination into a dedicated hook.

As per coding guidelines: “Favor cohesive modules, explicit interfaces, and standard practices; split files over 1000 lines.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/DesktopWorkbenchMain.tsx` around lines 714 -
814, Split the oversized files into cohesive modules without changing behavior:
in wework/src/components/layout/DesktopWorkbenchMain.tsx#L714-L814, extract the
DesktopWorkbenchPane header, workspace-panel, and pane-session integration
responsibilities; in
wework/src/components/layout/useWorkbenchPaneSession.ts#L151-L154, extract
transcript hydration and refresh coordination from message/composer operations;
in wework/src/features/workbench/WorkbenchProvider.test.tsx#L8116-L8167, move
runtime-pane transcript tests into focused test files; and in
wework/src/components/chat/ScrollableMessageArea.tsx#L207-L268, extract scroll
snapshot and suspension coordination into a dedicated hook. Preserve existing
interfaces and behavior while keeping each module cohesive.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/components/layout/useWorkbenchPaneSession.ts`:
- Around line 642-695: Update the visible-pane refresh effect around
loadRuntimeTranscriptForPaneRef so cleanup aborts the active hydration and
releases rebuildingTranscriptRef/current state. Track each refresh with a
per-request generation token, and only allow the matching request to clear
rebuilding state so an older cancelled request cannot affect a newer refresh.
Preserve identity checks and add a regression test covering hide, show, hide,
and show before the first refresh resolves.

---

Outside diff comments:
In `@wework/src/components/layout/DesktopWorkbenchMain.tsx`:
- Around line 714-814: Split the oversized files into cohesive modules without
changing behavior: in
wework/src/components/layout/DesktopWorkbenchMain.tsx#L714-L814, extract the
DesktopWorkbenchPane header, workspace-panel, and pane-session integration
responsibilities; in
wework/src/components/layout/useWorkbenchPaneSession.ts#L151-L154, extract
transcript hydration and refresh coordination from message/composer operations;
in wework/src/features/workbench/WorkbenchProvider.test.tsx#L8116-L8167, move
runtime-pane transcript tests into focused test files; and in
wework/src/components/chat/ScrollableMessageArea.tsx#L207-L268, extract scroll
snapshot and suspension coordination into a dedicated hook. Preserve existing
interfaces and behavior while keeping each module cohesive.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ab5684d-ae52-43be-852b-58de3bbfa719

📥 Commits

Reviewing files that changed from the base of the PR and between 7289fb5 and 664d84d.

📒 Files selected for processing (6)
  • wework/src/components/chat/ScrollableMessageArea.test.tsx
  • wework/src/components/chat/ScrollableMessageArea.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/components/layout/useWorkbenchPaneSession.ts
  • wework/src/components/layout/workbenchPaneStack.tsx
  • wework/src/features/workbench/WorkbenchProvider.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • wework/src/components/layout/workbenchPaneStack.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/components/chat/MessageList.tsx`:
- Around line 375-389: Update the cleanup around messageVirtualizer and
cacheConversationVirtualMeasurements to read
virtualMeasurementPersistenceEnabled from a ref containing the latest prop
value, preventing a stale enabled closure from writing during a true-to-false
transition. Keep the existing guards and snapshot behavior, and add a regression
test covering rerendering with persistence enabled, disabling it, then
unmounting.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 49ea81e3-21a9-4546-990e-b06b714a0716

📥 Commits

Reviewing files that changed from the base of the PR and between 664d84d and 8c8800b.

📒 Files selected for processing (4)
  • wework/src/components/chat/MessageList.tsx
  • wework/src/components/chat/MessageList.virtualization.test.tsx
  • wework/src/components/chat/ScrollableMessageArea.tsx
  • wework/src/components/layout/useWorkbenchPaneSession.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • wework/src/components/chat/ScrollableMessageArea.tsx
  • wework/src/components/layout/useWorkbenchPaneSession.ts

@qdaxb
qdaxb force-pushed the feature/wework-split-workbench branch from 0221d3f to ae4c3d5 Compare August 12, 2026 18:08
@qdaxb qdaxb changed the title feat(wework): add split task workbench feat(wework): redesign split task workbench Aug 12, 2026
@qdaxb
qdaxb force-pushed the feature/wework-split-workbench branch 2 times, most recently from 4dce00c to c80d8ed Compare August 12, 2026 19:48
@qdaxb
qdaxb added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@qdaxb
qdaxb added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@qdaxb
qdaxb force-pushed the feature/wework-split-workbench branch from c80d8ed to f3364d5 Compare August 12, 2026 20:59
@qdaxb
qdaxb added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@qdaxb
qdaxb added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit c27d281 Aug 12, 2026
59 checks passed
@qdaxb
qdaxb deleted the feature/wework-split-workbench branch August 12, 2026 23:51
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.

1 participant