Skip to content

[codex] Preserve local worktree terminal state - #1582

Merged
qdaxb merged 1 commit into
mainfrom
codex/fix-wework-local-worktree-terminal
Jun 27, 2026
Merged

qdaxb merged 1 commit into
mainfrom
codex/fix-wework-local-worktree-terminal

Conversation

@qdaxb

@qdaxb qdaxb commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Keep bottom and right workspace add menus independent, with the bottom panel limited to terminal tabs.
  • Preserve task-scoped terminal state and route local terminals to the selected local project or LocalTask workspace instead of falling back to cloud devices or $HOME.
  • Fix local runtime worktree detection so runtime.tasks.list groups Codex worktrees under the project root while each LocalTask keeps its real worktree path, workspaceKind: worktree, and worktreeId.
  • Normalize local app runtime responses, update sidebar worktree icon behavior, and document the task-level worktree contract.
  • Remove a flaky turn-file-change temp index race by adding a process-local temp path sequence.

Root Cause

The executor response builder was overwriting each LocalTask workspacePath with the parent workspace group path. As a result, the Wework sidebar received task records as regular workspaces instead of worktrees, so the worktree icon and terminal cwd could not be restored correctly.

Conflict Resolution

Rebased onto latest main and kept the pinned runtime task behavior from main while preserving task address matching by workspacePath from this branch.

Validation

  • cargo test -p wegent-executor --test app_runtime_work_workspace_contract
  • cargo test -p wegent-executor runtime_work
  • cargo test -p wegent-executor --all-features --test turn_file_changes_contract
  • pnpm --dir wework exec tsc --noEmit
  • pnpm --dir wework lint
  • pnpm --dir wework exec vitest run src/api/local/localServices.test.ts src/components/layout/DesktopSidebar.test.tsx src/features/workbench/WorkbenchProvider.test.tsx src/components/layout/DesktopWorkbenchLayout.test.tsx src/components/layout/MobileWorkbenchLayout.test.tsx src/components/layout/workspace-panels/WorkspacePanelCards.test.tsx src/lib/workspace-target.test.ts src/lib/device-capabilities.test.ts src/lib/navigation.test.ts
  • Conflict-resolution focused vitest: 5 files / 166 tests passed
  • Pre-push hook after rebase: Wework tests 96 files / 872 tests, executor cargo fmt --check, cargo test --all-features, and cargo clippy all passed.

Summary by CodeRabbit

  • New Features

    • Added support for local worktree-aware runtime tasks and improved task/workspace switching.
    • Introduced a richer bottom terminal experience with tabbed terminal sessions and per-workspace state.
    • Added a new terminal option in the right-side workspace tools menu.
  • Bug Fixes

    • Preserved terminal context when switching between tasks and restored the previous state when returning.
    • Prevented terminal paths from incorrectly falling back to unrelated locations in local mode.
    • Improved workspace and task matching so notifications and routes stay tied to the correct workspace.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR extends git worktree support across the full stack: the executor gains path-based and .git-file-based worktree ID detection, emitting worktreeId and task-scoped workspacePath in runtime task responses. The frontend propagates workspacePath through runtime task identity, routing, and address matching. Workspace panels are refactored to maintain per-task terminal state (keyed bottom panels, multi-tab BottomWorkspacePanel, new WorkspaceAddMenu), and the right panel gains a terminal tab. Local terminal fallback to $HOME and cloud-device prompts are removed.

Changes

Worktree identity, workspace target routing, and per-task terminal UI

Layer / File(s) Summary
Executor worktree detection and task path utilities
executor/src/runtime_work/util.rs, executor/src/services/turn_file_changes.rs
Adds workspace_task_path, infer_worktree_id, git_worktree_root_and_id, worktree_id_from_git_dir, path_worktree_root_and_id; updates infer_workspace_kind to return "worktree"; fixes temp-path uniqueness with an atomic sequence counter.
Executor runtime response: worktreeId emission and path preservation
executor/src/runtime_work/handler.rs, executor/src/runtime_work/response.rs, executor/tests/app_runtime_work_workspace_contract.rs
Handler stops overwriting workspace_path on matched links; workspace_response uses workspace_task_path per link; local_task_json conditionally emits "worktreeId"; contract test asserts new per-task worktree fields.
Frontend data contracts: routes, WorkspaceTarget, task normalization
wework/src/lib/navigation.ts, wework/src/types/workspace-files.ts, wework/src/api/local/localServices.ts, wework/src/api/local/localServices.test.ts
RuntimeTaskRoute gains workspacePath; WorkspaceTarget gains workspaceSource; adds normalizeRuntimeTaskSummary/normalizeRuntimeTaskSummaries for worktree field normalization from snake_case API responses; tests updated for worktree fixtures.
WorkspaceTarget resolution: project runtime and worktree path
wework/src/lib/workspace-target.ts, wework/src/lib/workspace-target.test.ts
Adds resolveProjectRuntimeWorkspaceTarget; updates workspaceTargetFromRuntimeTask to prefer workspace path for worktree-typed workspaces; adds two new test cases.
Runtime task identity: workspacePath in routing and address matching
wework/src/features/workbench/WorkbenchProvider.tsx, wework/src/features/workbench/WorkbenchProvider.test.tsx, wework/src/components/layout/runtimeTaskSidebarHelpers.ts, wework/src/components/layout/DesktopSidebar.tsx, wework/src/components/layout/DesktopSidebar.test.tsx, wework/src/components/layout/MobileWorkbenchLayout.test.tsx, wework/src/lib/device-capabilities.ts, wework/src/lib/device-capabilities.test.ts
getRuntimeTaskRouteKey, identity/address comparison, workspaceTaskAddresses, and notification key all include workspacePath; isRuntimeWorktreeTask uses worktreeId; isRuntimeTaskSelected matches workspacePath; supportsRemoteTerminalSessions requires cloud or remote device_type; optimistic and final RuntimeTaskAddress carry workspacePath.
DesktopWorkbenchLayout: activeWorkspaceTarget and project runtime target
wework/src/components/layout/DesktopWorkbenchLayout.tsx, wework/src/components/layout/DesktopWorkbenchMain.tsx
Introduces projectRuntimeWorkspaceTarget and activeWorkspaceTarget; environment operations use activeWorkspaceTarget; workbenchSessionKey includes workspacePath; DesktopWorkbenchMain receives workspaceProject; bottomPanelWorkspaceKey computed from runtime/project identity plus execution-mode preference.
WorkspaceAddMenu: new portal dropdown
wework/src/components/layout/workspace-panels/WorkspaceAddMenu.tsx
New component with WorkspaceAddMenuItem interface, portal dropdown, DOM-measured positioning, outside-click/Escape dismissal, and async onSelect.
RightWorkspacePanel: terminal tab and WorkspaceAddMenu
wework/src/components/layout/workspace-panels/RightWorkspacePanel.tsx
Adds terminal to view/tab unions; removes native Tauri new-tab menu; replaces with WorkspaceAddMenu; adds terminal render branch; extends props with currentProject, devices, preferLocalTerminal, onSelectTerminal.
WorkspacePanelCards: local terminal availability refactor and WorkspaceAddMenu
wework/src/components/layout/workspace-panels/WorkspacePanelCards.tsx, wework/src/components/layout/workspace-panels/WorkspacePanelCards.test.tsx
Extends props with preferLocalTerminal, hideTerminalChrome, panelActive, testIdsEnabled; refactors local terminal check into ready/pending state; removes remote terminal fallback when local path unavailable; replaces plus launcher with WorkspaceAddMenu; card test IDs use conditional testId helper.
BottomWorkspacePanel: multi-tab and per-workspace keyed state
wework/src/components/layout/workspace-panels/BottomWorkspacePanel.tsx, wework/src/components/layout/workspace-panels/EmbeddedLocalTerminal.tsx, wework/src/components/layout/workspace-panels/RemoteTerminal.tsx, wework/src/components/layout/DesktopWorkbenchMain.tsx
BottomWorkspacePanel gains tab management and WorkspaceAddMenu; DesktopWorkbenchMain switches to keyed bottomPanelOpenByKey/bottomPanelContexts; inactive contexts preserved for rendering; EmbeddedLocalTerminal and RemoteTerminal gain testIdsEnabled.
Layout and workbench tests: local terminal, per-task state, right panel
wework/src/components/layout/DesktopWorkbenchLayout.test.tsx, wework/src/components/layout/DesktopWorkbenchMain.tsx
Adds local-terminal mocks; new tests for local project/git project terminal cwd, runtime workspace path (no $HOME), per-task bottom terminal state preservation across switches, and add-menu tab addition.
Docs and i18n
docs/en/developer-guide/runtime-local-work.md, docs/zh/developer-guide/runtime-local-work.md, wework/src/i18n/locales/en/common.json, wework/src/i18n/locales/zh-CN/common.json
Documents two-level workspace semantics, worktree LocalTask requirements, and terminal state scoping per task; updates limited-tools strings to reflect no-terminal-available messaging.

Sequence Diagram(s)

sequenceDiagram
    participant Executor
    participant localServices
    participant WorkbenchProvider
    participant DesktopWorkbenchLayout
    participant DesktopWorkbenchMain
    participant BottomWorkspacePanel
    participant WorkspacePanelCards

    Executor->>localServices: runtime.tasks.list (workspace_path, workspace_kind: worktree, worktree_id)
    localServices->>WorkbenchProvider: normalizeRuntimeTaskSummaries → LocalTaskSummary (workspacePath, worktreeId)
    WorkbenchProvider->>WorkbenchProvider: getRuntimeTaskRouteKey(deviceId, localTaskId, workspacePath)
    WorkbenchProvider->>DesktopWorkbenchLayout: runtimeTaskTarget with workspacePath
    DesktopWorkbenchLayout->>DesktopWorkbenchLayout: resolveProjectRuntimeWorkspaceTarget → activeWorkspaceTarget
    DesktopWorkbenchLayout->>DesktopWorkbenchMain: workspaceProject + activeWorkspaceTarget
    DesktopWorkbenchMain->>DesktopWorkbenchMain: bottomPanelWorkspaceKey (deviceId + localTaskId + workspacePath)
    DesktopWorkbenchMain->>BottomWorkspacePanel: active=true, preserveContent, preferLocalTerminal
    BottomWorkspacePanel->>WorkspacePanelCards: defaultOpenTool=terminal, hideTerminalChrome, panelActive
    WorkspacePanelCards->>WorkspacePanelCards: canUseLocalTerminalCheck → startLocalTerminal(cwd=workspacePath)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • wecode-ai/Wegent#1530: Directly related — both PRs extend runtime work task normalization to propagate workspaceKind/worktreeId from executor backend through the UI.
  • wecode-ai/Wegent#1544: Directly related — that PR stabilizes localTaskId generation/forwarding during task creation, which intersects with this PR's expansion of runtime task identity to include workspacePath in address/route keys.
  • wecode-ai/Wegent#1517: Related — both modify DesktopWorkbenchMain.tsx runtime session key derivation and runtime-task identity logic.

Poem

🐇 A worktree blooms in the .git file's light,
Each task remembers its terminal at night.
No $HOME fallback, no cloud-device confuse —
The right path is chosen; the rabbit approves!
Tab by tab, each workspace stands alone,
Like burrows dug deep, each task has its home. 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.25% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately highlights the main change: preserving local worktree terminal state.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-wework-local-worktree-terminal

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 force-pushed the codex/fix-wework-local-worktree-terminal branch from 11f7443 to 33d7770 Compare June 27, 2026 19:54
@qdaxb
qdaxb marked this pull request as ready for review June 27, 2026 19:56
@qdaxb
qdaxb merged commit 99a4dbf into main Jun 27, 2026
23 of 24 checks passed
@qdaxb
qdaxb deleted the codex/fix-wework-local-worktree-terminal branch June 27, 2026 20:04
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