Skip to content

fix(wework): support project task round-trip navigation - #2415

Merged
qdaxb merged 3 commits into
mainfrom
agent/wework-project-task-roundtrip
Aug 4, 2026
Merged

fix(wework): support project task round-trip navigation#2415
qdaxb merged 3 commits into
mainfrom
agent/wework-project-task-roundtrip

Conversation

@qdaxb

@qdaxb qdaxb commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What changed

  • Environment 的项目空间关联任务现在会打开或复用对应的看板标签页,并定位到目标任务详情。
  • 项目空间任务详情中的“本地执行”记录现在会返回对应的 Wework runtime task,并复用已有任务标签页。
  • 增加中英文工作台文档,以及正向、反向跳转的回归测试。

Why

项目空间任务与本地运行任务之间原先只有单向跳转,用户在项目空间任务详情中点击“本地执行”后无法回到对应的 Wework 任务。此次补齐双向导航,并保留项目、任务和标签页路由状态,避免重复打开标签页。

Validation

  • pnpm --filter wework test — 268 个测试文件、2664 个测试通过
  • pnpm --filter wework exec tsc --noEmit
  • 变更文件的 Prettier、ESLint 和 git diff --check
  • 独立 Tauri 实例真实验证:从当前项目 WegentBug修复 的任务 WEGENTBUB4E7A6-2 打开“本地执行”,成功回到 runtime task runtime-969548342

Summary by CodeRabbit

  • New Features

    • Open linked runtime tasks directly from project-space task details.
    • Navigate between project tasks and their running-task views while preserving tabs, routes, and project context.
    • Automatically focus the requested task item when opening a project-space view.
    • Update workspace tab titles and routes when selecting linked tasks.
  • Documentation

    • Added guidance for navigating between project spaces and running tasks in English and Chinese.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds bidirectional navigation between project-space board tasks and runtime tasks. WorkspaceTabsContext.selectTab accepts optional title/route updates. DesktopWorkbenchLayout and DesktopWorkbenchMain open or reuse workspace tabs for bound tasks. CloudTodoWorkspace handles focused-item routing, and TodoEditor exposes a runtime-task open action. Documentation describes the flow.

Changes

Project-space and runtime task navigation

Layer / File(s) Summary
Workspace tab selection with route updates
wework/src/features/workspace-tabs/WorkspaceTabsContext.tsx, wework/src/features/workspace-tabs/workspaceTabsContextValue.ts, wework/src/features/workspace-tabs/WorkspaceTabsContext.test.tsx
selectTab and the internal reducer action now accept optional title/contentRoute updates, merged into the matching tab on activation, with navigation using the updated route. Tests cover updating an existing board tab.
DesktopWorkbenchLayout runtime-task navigation
wework/src/components/layout/DesktopWorkbenchLayout.tsx
Adds a reusable boardRouteParam helper and openProjectSpaceRuntimeTask, which opens a runtime task and selects or creates a workspace tab. CloudTodoWorkspace wiring derives project and focused item IDs from board routes.
DesktopWorkbenchMain bound-task navigation
wework/src/components/layout/DesktopWorkbenchMain.tsx
Adds openBoundProjectSpaceTask, which selects or opens a board tab for a bound task, falling back to direct navigation. The Manage Todo action opens bound tasks in the board workspace.
CloudTodoWorkspace focused-item and runtime-task handling
wework/src/features/todo/CloudTodoWorkspace.tsx, wework/src/features/todo/CloudTodoWorkspace.test.tsx
New props (focusedItemId, onFocusedItemHandled, onOpenRuntimeTask) drive an effect that waits for project items, selects the focused item, and notifies the caller. onOpenRuntimeTask is forwarded to TodoEditor. Tests verify the routed flow.
TodoEditor runtime-task open action
wework/src/features/todo/TodoEditor.tsx
Adds onOpenRuntimeTask prop; local execution entries render as buttons invoking the callback with device and task IDs, disabled without a callback.
Navigation documentation
docs/en/wework/workbench.md, docs/zh/wework/workbench.md
Documents navigating between linked project-space and runtime tasks with tab reuse and route preservation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TodoEditor
  participant CloudTodoWorkspace
  participant DesktopWorkbenchLayout
  participant WorkspaceTabsContext

  User->>TodoEditor: click local execution entry
  TodoEditor->>CloudTodoWorkspace: onOpenRuntimeTask(deviceId, taskId)
  CloudTodoWorkspace->>DesktopWorkbenchLayout: openProjectSpaceRuntimeTask(address)
  DesktopWorkbenchLayout->>WorkspaceTabsContext: selectTab(tabId, updates)
  WorkspaceTabsContext-->>DesktopWorkbenchLayout: tab activated with runtime task route
  DesktopWorkbenchLayout-->>User: runtime task tab opened

  User->>DesktopWorkbenchLayout: click linked project-space task
  DesktopWorkbenchLayout->>WorkspaceTabsContext: selectTab(boardTabId, {contentRoute})
  WorkspaceTabsContext-->>CloudTodoWorkspace: focusedItemId set via route
  CloudTodoWorkspace->>CloudTodoWorkspace: wait for items, select item
  CloudTodoWorkspace-->>DesktopWorkbenchLayout: onFocusedItemHandled()
Loading

Possibly related PRs

  • wecode-ai/Wegent#2346: Directly overlaps in DesktopWorkbenchLayout, DesktopWorkbenchMain, CloudTodoWorkspace, and TodoEditor, both changing board/task navigation and runtime-task interactions.
  • wecode-ai/Wegent#2359: Extends workspace-tab and project-route behavior in DesktopWorkbenchLayout, CloudTodoWorkspace, and WorkspaceTabsContext for runtime-task navigation.
  • wecode-ai/Wegent#2409: Modifies project-space task/runtime-task binding and navigation flows in DesktopWorkbenchLayout.tsx, DesktopWorkbenchMain.tsx, and CloudTodoWorkspace.tsx.

Suggested reviewers: micro66, ficohu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's main change: round-trip navigation for Wework project tasks.
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 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/wework-project-task-roundtrip

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 marked this pull request as ready for review August 4, 2026 10:09

@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/features/todo/CloudTodoWorkspace.tsx`:
- Around line 1326-1338: Move the focusedItemRequestRef.current assignment in
the focused-item effect so it occurs inside the queued microtask, immediately
after the active guard. Preserve the existing requestKey deduplication and state
updates, ensuring Strict Mode’s second setup can process the request and invoke
onFocusedItemHandled.

In `@wework/src/features/todo/TodoEditor.tsx`:
- Around line 1029-1041: Update the button rendered in the cloud todo execution
list, identified by the `data-testid` value `cloud-todo-execution-${task.id}`,
to use a minimum 44px height on screens at or below 767px. Keep its current
compact sizing for desktop through an appropriate responsive class override,
without changing its click behavior or other styling.
🪄 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: 5ea44877-e120-4819-b7b1-56db5114a1c8

📥 Commits

Reviewing files that changed from the base of the PR and between 76758c6 and 4ebb5a5.

📒 Files selected for processing (10)
  • docs/en/wework/workbench.md
  • docs/zh/wework/workbench.md
  • wework/src/components/layout/DesktopWorkbenchLayout.tsx
  • wework/src/components/layout/DesktopWorkbenchMain.tsx
  • wework/src/features/todo/CloudTodoWorkspace.test.tsx
  • wework/src/features/todo/CloudTodoWorkspace.tsx
  • wework/src/features/todo/TodoEditor.tsx
  • wework/src/features/workspace-tabs/WorkspaceTabsContext.test.tsx
  • wework/src/features/workspace-tabs/WorkspaceTabsContext.tsx
  • wework/src/features/workspace-tabs/workspaceTabsContextValue.ts

Comment on lines +1326 to +1338
focusedItemRequestRef.current = requestKey
let active = true
queueMicrotask(() => {
if (!active) return
setRootView('projects')
setProjectView('board')
setBoardParentId(focusedItem.parent_id)
setSelectedItem(focusedItem)
onFocusedItemHandled?.()
})
return () => {
active = false
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Locate file"
fd -a 'CloudTodoWorkspace\.tsx$' . || true

echo "## File excerpt around referenced lines"
file="$(fd 'CloudTodoWorkspace\.tsx$' . | head -n 1)"
if [ -n "${file:-}" ]; then
  sed -n '1290,1365p' "$file" | cat -n
  echo "## Search focusedItemRequestRef usages"
  rg -n "focusedItemRequestRef|onFocusedItemHandled|queueMicrotask" "$file" || true
fi

echo "## Behavioral model for StrictMode-like setup-cleanup setup"
python3 - <<'PY'
# Standalone model of the reported Race in React Strict Mode:
# effect mounts => sets ref and active => cleanup runs => second mount runs.
request_key = "k"
focused_item_request_ref_current = None
active = None
opened = False
called_handler = False

def old_effect():
    global focused_item_request_ref_current, active, opened, called_handler
    focused_item_request_ref_current = request_key
    active = True
    def cleanup():
        global active
        active = False
    return cleanup

def strict_setup_cleanup_setup():
    cleanup1 = old_effect()
    # cleanup from first effect before second effect
    cleanup1()
    cleanup2 = old_effect()
    cleanup2()
    return focused_item_request_ref_current, active

ref_after, active_after = strict_setup_cleanup_setup()
print("old_effect_ref_after=", ref_after)
print("old_effect_active_after=", active_after)
print("old_effect_opens_task_after_2nd_cleanup=", not active_after)
print("old_effect_skips_onFocusedItemHandled_after_2nd_cleanup=", not active_after)

# Proposed model: ref set inside queued microtask only, after active test.
ref_after2 = None
active2 = True  # second effect's active local after cleanup of first effect?
def proposed_effect():
    global ref_after2, active2
    if not active2:
        return
    ref_after2 = request_key
    # microtask would run while active2 is true
    # then active2 would become false during cleanup before second effect, but ref isn't set
def proposed_cleanup():
    global active2
    active2 = False
cleanup_prop = proposed_effect()
proposed_cleanup()
proposed_effect()
print("proposed_effect_ref_after=", ref_after2)
PY

Repository: wecode-ai/Wegent

Length of output: 4401


🌐 Web query:

React Strict Mode double invokes effects setup cleanup before second setup documentation

💡 Result:

In React Strict Mode (development only), React intentionally performs an extra mount-unmount-remount cycle to verify that your components and effects are resilient and properly handle setup and cleanup [1][2][3]. The specific sequence of execution in Strict Mode for a component mount is: 1. Setup (First mount) [3] 2. Cleanup (First unmount) [3] 3. Setup (Second mount) [3] This behavior was introduced in React 18 to help developers identify bugs caused by missing cleanup functions or impure logic [2][4]. Because Effects are expected to be synchronized with the component's lifecycle, they should always have a cleanup function if they perform side effects (like subscriptions, network requests, or timers) [1][2]. When your component mounts in development, this sequence runs: - React calls your Effect's setup code [1]. - React immediately runs your Effect's cleanup function [1][3]. - React calls your Effect's setup code again [1]. This cycle ensures that if your code has a bug—such as a missing cleanup function that leaves an event listener or a WebSocket connection open—you will notice the issue immediately in development [1][2]. In production builds, Strict Mode checks are stripped out, and the component mounts exactly once [2][3]. If you are concerned about side effects occurring twice (e.g., duplicate API requests), the recommended approach is to implement proper cleanup (such as using an AbortController to cancel fetches or a boolean flag to ignore results) rather than disabling Strict Mode [4][5][3]. Top results: [1][2][3]

Citations:


Set focusedItemRequestRef after the active microtask guard.

React Strict Mode can run setup, cleanup, then setup again before the queued microtask. The first cleanup sets active to false, and the second setup exits at focusedItemRequestRef.current === requestKey, so the focused task does not open and onFocusedItemHandled is not called. Move the ref update into the microtask after the !active return.

Proposed fix
-    focusedItemRequestRef.current = requestKey
     let active = true
     queueMicrotask(() => {
       if (!active) return
+      focusedItemRequestRef.current = requestKey
       setRootView('projects')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
focusedItemRequestRef.current = requestKey
let active = true
queueMicrotask(() => {
if (!active) return
setRootView('projects')
setProjectView('board')
setBoardParentId(focusedItem.parent_id)
setSelectedItem(focusedItem)
onFocusedItemHandled?.()
})
return () => {
active = false
}
let active = true
queueMicrotask(() => {
if (!active) return
focusedItemRequestRef.current = requestKey
setRootView('projects')
setProjectView('board')
setBoardParentId(focusedItem.parent_id)
setSelectedItem(focusedItem)
onFocusedItemHandled?.()
})
return () => {
active = false
}
🤖 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/features/todo/CloudTodoWorkspace.tsx` around lines 1326 - 1338,
Move the focusedItemRequestRef.current assignment in the focused-item effect so
it occurs inside the queued microtask, immediately after the active guard.
Preserve the existing requestKey deduplication and state updates, ensuring
Strict Mode’s second setup can process the request and invoke
onFocusedItemHandled.

Comment on lines +1029 to +1041
<button
key={task.id}
className="flex items-center gap-2.5 rounded-lg px-2.5 py-2 text-xs transition-colors hover:bg-muted/60"
type="button"
data-testid={`cloud-todo-execution-${task.id}`}
onClick={() =>
void onOpenRuntimeTask?.({
deviceId: task.device_id,
taskId: task.task_id,
})
}
disabled={!onOpenRuntimeTask}
className="flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-xs transition-colors hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus disabled:cursor-default"
aria-label={`打开本地执行 ${task.task_title || task.task_id}`}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Provide a 44px mobile touch target.

This new local-execution button is about 32px high from its text and py-2 padding. It has no mobile override. On screens at or below 767px, it does not meet the required 44px × 44px minimum control size.

Add a 44px minimum height for mobile. Preserve the compact height at desktop only if needed.

🤖 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/features/todo/TodoEditor.tsx` around lines 1029 - 1041, Update the
button rendered in the cloud todo execution list, identified by the
`data-testid` value `cloud-todo-execution-${task.id}`, to use a minimum 44px
height on screens at or below 767px. Keep its current compact sizing for desktop
through an appropriate responsive class override, without changing its click
behavior or other styling.

Source: Coding guidelines

@qdaxb
qdaxb added this pull request to the merge queue Aug 4, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 4, 2026
@qdaxb
qdaxb added this pull request to the merge queue Aug 4, 2026
@qdaxb
qdaxb removed this pull request from the merge queue due to a manual request Aug 4, 2026
@qdaxb
qdaxb added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit ea73948 Aug 4, 2026
69 of 71 checks passed
@qdaxb
qdaxb deleted the agent/wework-project-task-roundtrip branch August 4, 2026 11:40
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