Conversation
WalkthroughThe changes implement optimistic updates for worktree creation by introducing a PendingWorktree model and isPending flag. When users create or select worktrees for tasks, pending entries are immediately added to state, merged into the worktree list via enrichWorktreesWithTasks, and displayed with spinner indicators. Pending entries are removed upon completion or failure. Changes
Sequence DiagramsequenceDiagram
participant User
participant UI as TaskTabs UI
participant Logic as NewLayoutMain
participant State as Worktree State
participant Backend
User->>Logic: Select/Create Task
Logic->>State: Add PendingWorktree (optimistic)
Logic->>Logic: enrichWorktreesWithTasks(worktrees, pendingWorktrees)
Logic->>UI: Pass enriched list with isPending=true
UI->>UI: Render Loader2 spinner, disable button
par Async Operation
Backend->>Backend: Process worktree creation
end
alt Success
Backend-->>Logic: Worktree created
Logic->>State: Remove PendingWorktree
Logic->>UI: Update with real worktree
UI->>UI: Hide spinner, enable button
else Failure
Backend-->>Logic: Creation failed
Logic->>State: Remove PendingWorktree
UI->>UI: Return to normal state
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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)
apps/desktop/src/renderer/screens/main/components/NewLayout/NewLayoutMain.tsx (1)
592-676: Prevent duplicate pending worktrees on repeated selections.If a user re-triggers task selection/creation while the first optimistic request is still pending, we enqueue another
PendingWorktreefor the same branch and fire a secondworktree-create. That leads to duplicate entries, redundant IPC traffic, and confusing UI updates. Guard both flows by short-circuiting when a pending entry already exists for the branch before appending to state.if (existingWorktree) { // Worktree already exists - switch to it … } else { + if (pendingWorktrees.some((wt) => wt.branch === task.branch)) { + handleCloseAddTaskModal(); + return; + } // Worktree doesn't exist - create it with optimistic update … }if (!currentWorkspace) return; + if (pendingWorktrees.some((wt) => wt.branch === taskData.branch)) { + handleCloseAddTaskModal(); + return; + } // Create pending worktree for optimistic update const pendingId = `pending-${Date.now()}`;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/desktop/src/renderer/screens/main/components/NewLayout/NewLayoutMain.tsx(10 hunks)apps/desktop/src/renderer/screens/main/components/NewLayout/TaskTabs.tsx(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/desktop/src/renderer/screens/main/components/NewLayout/TaskTabs.tsx (2)
apps/desktop/src/shared/types.ts (1)
Worktree(58-67)apps/desktop/src/renderer/screens/main/components/NewLayout/StatusIndicator.tsx (1)
StatusIndicator(53-113)
apps/desktop/src/renderer/screens/main/components/NewLayout/NewLayoutMain.tsx (3)
apps/desktop/src/renderer/screens/main/components/NewLayout/StatusIndicator.tsx (1)
TaskStatus(3-9)apps/desktop/src/shared/types.ts (1)
Worktree(58-67)apps/desktop/src/renderer/screens/main/components/NewLayout/TaskTabs.tsx (1)
WorktreeWithTask(15-29)
🪛 GitHub Actions: CI
apps/desktop/src/renderer/screens/main/components/NewLayout/NewLayoutMain.tsx
[error] 234-234: TS2322: Type '{ id: string; branch: string; path: string; tabs: never[]; isPending: true; task: { id: string; slug: string; title: string; status: TaskStatus; description: string; } | undefined; }[]' is not assignable to type 'WorktreeWithTask[]'. Property 'createdAt' is missing in type '{ id: string; branch: string; path: string; tabs: never[]; isPending: true; task: { id: string; slug: string; title: string; status: TaskStatus; description: string; } | undefined; }' but required in type 'WorktreeWithTask'.
| const pendingAsWorktrees: WorktreeWithTask[] = pendingWorktrees.map( | ||
| (pending) => ({ | ||
| id: pending.id, | ||
| branch: pending.branch, | ||
| path: "", // Pending worktrees don't have a path yet | ||
| tabs: [], | ||
| isPending: true, // Mark as pending for UI | ||
| task: pending.taskData | ||
| ? { | ||
| id: pending.id, | ||
| slug: pending.taskData.slug, | ||
| title: pending.taskData.name, | ||
| status: pending.taskData.status, | ||
| description: pending.description || "", | ||
| } | ||
| : undefined, | ||
| }), | ||
| ); | ||
|
|
||
| // Then, enrich real worktrees with task metadata |
There was a problem hiding this comment.
Build breaks: populate required Worktree fields for pending entries.
WorktreeWithTask extends Worktree, so every pending object you create here must satisfy the base interface. Right now the build fails with TS2322 because createdAt is missing, and title isn’t a known property on Worktree. Please supply the required fields and drop the extra property so pending entries compile like the real ones.
const pendingAsWorktrees: WorktreeWithTask[] = pendingWorktrees.map(
(pending) => ({
id: pending.id,
branch: pending.branch,
- path: "", // Pending worktrees don't have a path yet
- tabs: [],
- isPending: true, // Mark as pending for UI
- task: pending.taskData
+ path: "", // Pending worktrees don't have a path yet
+ createdAt: new Date().toISOString(),
+ tabs: [],
+ description: pending.description,
+ isPending: true, // Mark as pending for UI
+ task: pending.taskData
? {
id: pending.id,
slug: pending.taskData.slug,
title: pending.taskData.name,
status: pending.taskData.status,
description: pending.description || "",
}
: undefined,
}),
);📝 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.
| const pendingAsWorktrees: WorktreeWithTask[] = pendingWorktrees.map( | |
| (pending) => ({ | |
| id: pending.id, | |
| branch: pending.branch, | |
| path: "", // Pending worktrees don't have a path yet | |
| tabs: [], | |
| isPending: true, // Mark as pending for UI | |
| task: pending.taskData | |
| ? { | |
| id: pending.id, | |
| slug: pending.taskData.slug, | |
| title: pending.taskData.name, | |
| status: pending.taskData.status, | |
| description: pending.description || "", | |
| } | |
| : undefined, | |
| }), | |
| ); | |
| // Then, enrich real worktrees with task metadata | |
| const pendingAsWorktrees: WorktreeWithTask[] = pendingWorktrees.map( | |
| (pending) => ({ | |
| id: pending.id, | |
| branch: pending.branch, | |
| path: "", // Pending worktrees don't have a path yet | |
| createdAt: new Date().toISOString(), | |
| tabs: [], | |
| description: pending.description, | |
| isPending: true, // Mark as pending for UI | |
| task: pending.taskData | |
| ? { | |
| id: pending.id, | |
| slug: pending.taskData.slug, | |
| title: pending.taskData.name, | |
| status: pending.taskData.status, | |
| description: pending.description || "", | |
| } | |
| : undefined, | |
| }), | |
| ); |
🧰 Tools
🪛 GitHub Actions: CI
[error] 234-234: TS2322: Type '{ id: string; branch: string; path: string; tabs: never[]; isPending: true; task: { id: string; slug: string; title: string; status: TaskStatus; description: string; } | undefined; }[]' is not assignable to type 'WorktreeWithTask[]'. Property 'createdAt' is missing in type '{ id: string; branch: string; path: string; tabs: never[]; isPending: true; task: { id: string; slug: string; title: string; status: TaskStatus; description: string; } | undefined; }' but required in type 'WorktreeWithTask'.
🤖 Prompt for AI Agents
In apps/desktop/src/renderer/screens/main/components/NewLayout/NewLayoutMain.tsx
around lines 234 to 253, the temporary pending worktree objects are missing
required Worktree fields and include an extra property that breaks typing; add a
createdAt field on each pending worktree (e.g. use pending.createdAt if present
or set to a current ISO timestamp) so the object satisfies the Worktree base
interface, and remove the non-existent title property from the nested task
object (keep slug/name/status/description as before) so the pending entries
compile like the real ones.
Description
Related Issues
Type of Change
Testing
Screenshots (if applicable)
Additional Notes
Summary by CodeRabbit
Release Notes