feat: add All Worktrees overview option#767
feat: add All Worktrees overview option#767Questler wants to merge 4 commits intoAutoMaker-Org:v0.14.0rcfrom
Conversation
Adds an "All" option to the worktree selector that shows features from all worktrees and main combined. Uses a sentinel value ALL_WORKTREES_BRANCH to bypass worktree filtering. Supports dropdown (3+ worktrees), tab (1-2 worktrees), and mobile layouts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use aggregated running tasks from all worktrees when ALL_WORKTREES_BRANCH is selected, so feature cards correctly show Logs/Stop instead of Resume. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds an "All Worktrees" virtual mode via a new exported sentinel Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as Worktree Panel UI
participant Store as App Store
participant Board as Board View
participant Hooks as Board Hooks
User->>UI: Click "All Worktrees"
UI->>Store: setCurrentWorktree({ branch: ALL_WORKTREES_BRANCH })
Store->>Board: emit currentWorktree change
Board->>Hooks: derive currentWorktreeBranch / selectedWorktree
Hooks->>Hooks: if branch == ALL_WORKTREES_BRANCH -> selectedWorktree = undefined
Hooks->>Hooks: aggregate running tasks and card counts across worktrees
Hooks-->>Board: return aggregated features, counts, undefined selection
Board->>UI: render "All" label, aggregated counts, hide per-worktree controls
UI-->>User: display unified All Worktrees view
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello @Questler, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the user experience by introducing a consolidated 'All Worktrees' view. This new feature allows developers to gain a comprehensive overview of all active features across different worktrees and the main branch from a single interface. It streamlines the management of multiple development contexts by providing a unified board, eliminating the need to switch between individual worktrees to track progress. Additionally, it resolves a critical bug related to the display of running agent states, ensuring accurate operational feedback within this new aggregated view. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request successfully adds the "All Worktrees" overview option, which is a great enhancement for managing features across multiple worktrees. The implementation is thorough, touching all the necessary components from the data store to the UI panels. The logic to handle the virtual "All" selection, especially for aggregating running tasks, is well-handled. I've left one suggestion regarding centralizing a piece of duplicated logic to improve maintainability. Overall, this is a solid feature addition.
| // Compute total card count across all branches for "All" tab display | ||
| const totalCardCount = useMemo(() => { | ||
| if (!branchCardCounts) return 0; | ||
| return Object.values(branchCardCounts).reduce((sum, count) => sum + count, 0); | ||
| }, [branchCardCounts]); |
There was a problem hiding this comment.
You're calculating totalCardCount here, which is great. However, the same calculation is also performed inside WorktreeDropdown and WorktreeMobileDropdown. To avoid code duplication and redundant calculations, you can pass this totalCardCount down as a prop to those child components.
This would involve:
- Adding a
totalCardCountprop toWorktreeDropdownPropsandWorktreeMobileDropdownProps. - Passing this
totalCardCountto<WorktreeDropdown ... />and<WorktreeMobileDropdown ... />. - Removing the
useMemocalculation fortotalCardCountfrom the child components and using the prop instead.
There was a problem hiding this comment.
Pull request overview
Adds an “All Worktrees” virtual selection to the Board worktree selector so the board can display features from all branches/worktrees together, and adjusts running-agent state aggregation so cards show correct running status in that view.
Changes:
- Introduces
ALL_WORKTREES_BRANCHsentinel branch value in the app store. - Adds “All / All Worktrees” option across tab, dropdown, and mobile worktree selectors.
- Updates board filtering + running-task aggregation to support the ALL view.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/ui/src/store/app-store.ts | Adds ALL_WORKTREES_BRANCH sentinel constant exported from the store module. |
| apps/ui/src/components/views/board-view.tsx | Uses sentinel to bypass filtering and aggregates running tasks across worktrees in ALL mode. |
| apps/ui/src/components/views/board-view/hooks/use-board-column-features.ts | Bypasses branch/worktree filtering when ALL_WORKTREES_BRANCH is active. |
| apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx | Adds “All” tab and wires ALL selection into desktop/mobile selectors; hides worktree-specific controls in ALL mode. |
| apps/ui/src/components/views/board-view/worktree-panel/hooks/use-worktrees.ts | Treats ALL selection as virtual (no selected worktree) and skips selection validation. |
| apps/ui/src/components/views/board-view/worktree-panel/components/worktree-dropdown.tsx | Adds “All Worktrees” dropdown option + total card count; adjusts trigger indicators for ALL mode. |
| apps/ui/src/components/views/board-view/worktree-panel/components/worktree-mobile-dropdown.tsx | Adds “All Worktrees” option + total card count in mobile dropdown. |
| apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx | Hides branch switch/actions/dev server/auto-mode indicators when ALL is selected. |
Comments suppressed due to low confidence (1)
apps/ui/src/components/views/board-view.tsx:522
selectedWorktreeBranchis derived fromcurrentWorktreeBranch, so when the "All Worktrees" sentinel is selected it becomes__all_worktrees__. This value is later passed asdefaultBranch/defaultBaseBranchand can cause newly created plans/features to be assigned to the sentinel instead of a real git branch. Treat ALL mode as "no single branch" when computing defaults (e.g., fall back to primary/main branch whencurrentWorktreeBranch === ALL_WORKTREES_BRANCH).
// Get the branch for the currently selected worktree (for defaulting new features)
// Use the branch from selectedWorktree, or fall back to main worktree's branch
const selectedWorktreeBranch =
currentWorktreeBranch || worktrees.find((w) => w.isMain)?.branch || 'main';
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| getTestSessionInfo={getTestSessionInfo} | ||
| onSelectWorktree={handleSelectWorktree} | ||
| isAllWorktreesSelected={isAllWorktreesSelected} | ||
| onSelectAllWorktrees={handleSelectAllWorktrees} |
There was a problem hiding this comment.
In dropdown layout, onSelectAllWorktrees is passed unconditionally. If useWorktreesEnabled can be false (it’s a user setting), this will still render the "All Worktrees" option even though worktrees are disabled. Pass undefined unless worktrees are enabled (and ideally only when there is at least one non-main worktree).
| onSelectAllWorktrees={handleSelectAllWorktrees} | |
| onSelectAllWorktrees={useWorktreesEnabled ? handleSelectAllWorktrees : undefined} |
| {/* "All" tab - shown when worktrees are enabled */} | ||
| {useWorktreesEnabled && ( | ||
| <Button | ||
| variant={isAllWorktreesSelected ? 'default' : 'outline'} | ||
| size="sm" | ||
| className="h-7 px-3 text-xs font-mono gap-1.5" |
There was a problem hiding this comment.
The "All" tab is shown whenever useWorktreesEnabled is true, even if there are no non-main worktrees. This diverges from the PR description/test plan (“All tab appears when at least 1 non-main worktree exists”) and makes the selector redundant on single-branch projects. Consider gating this on nonMainWorktrees.length > 0 (and similarly for the mobile/dropdown "All Worktrees" option).
| isActivating={isActivating} | ||
| branchCardCounts={branchCardCounts} | ||
| onSelectWorktree={handleSelectWorktree} | ||
| isAllWorktreesSelected={isAllWorktreesSelected} | ||
| onSelectAllWorktrees={useWorktreesEnabled ? handleSelectAllWorktrees : undefined} | ||
| /> |
There was a problem hiding this comment.
Mobile dropdown enables the "All Worktrees" option based only on useWorktreesEnabled. If the intended behavior is to show "All" only when at least one non-main worktree exists, also gate onSelectAllWorktrees on nonMainWorktrees.length > 0 to match the desktop tab behavior.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/ui/src/components/views/board-view.tsx (1)
512-521:⚠️ Potential issue | 🟠 MajorAvoid using
ALL_WORKTREES_BRANCHas a real branch for feature defaults.
In All mode,currentWorktreeBranchbecomes the sentinel and can flow into branch defaults/updates, which risks assigning features to"__all_worktrees__"and making them disappear from normal branch views.🔧 Suggested fix (sanitize the branch for defaults)
- const currentWorktreeBranch = selectedWorktree?.branch ?? currentWorktreeInfo?.branch ?? null; + const currentWorktreeBranch = selectedWorktree?.branch ?? currentWorktreeInfo?.branch ?? null; + const effectiveWorktreeBranch = + currentWorktreeBranch === ALL_WORKTREES_BRANCH ? null : currentWorktreeBranch; - const selectedWorktreeBranch = - currentWorktreeBranch || worktrees.find((w) => w.isMain)?.branch || 'main'; + const selectedWorktreeBranch = + effectiveWorktreeBranch || worktrees.find((w) => w.isMain)?.branch || 'main';Use
effectiveWorktreeBranchanywhere a real branch is required (bulk updates, dialogs, defaults).
- Sanitize sentinel branch value so it never leaks into feature defaults - Pass totalCardCount as prop from parent instead of recalculating in each child - Only show "All" option when at least 1 non-main worktree exists Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/ui/src/components/views/board-view.tsx (2)
640-665:⚠️ Potential issue | 🟠 MajorSentinel value can leak into feature
branchNamevia bulk update.In
handleBulkUpdate, whenworkMode === 'current'(Line 652-654),finalBranchNameis set tocurrentWorktreeBranch, which equals'__all_worktrees__'in All mode. This sentinel would be persisted as a realbranchNameon features.Suggested fix
if (workMode === 'current') { // If a worktree is selected, use its branch; otherwise work on main (undefined = no branch assignment) - finalBranchName = currentWorktreeBranch || undefined; + finalBranchName = effectiveWorktreeBranch || undefined;
1630-1632:⚠️ Potential issue | 🟠 MajorReplace
currentWorktreeBranchwitheffectiveWorktreeBranchin dialog props to prevent sentinel value leakage.The sentinel value
'__all_worktrees__'can appear in the UI through thecurrentBranchprop. When in All mode,currentWorktreeBranchis'__all_worktrees__', which is truthy and passes through the|| undefinedcheck. TheWorkModeSelectorcomponent then displays this sentinel directly to the user in work mode descriptions like "Work will be done directly on all_worktrees".Use
effectiveWorktreeBranchinstead, which correctly maps the sentinel tonull:Suggested fix for all three dialog props
- currentBranch={currentWorktreeBranch || undefined} + currentBranch={effectiveWorktreeBranch || undefined}Applies to lines 1583–1587 (MassEditDialog), 1630–1632 (AddFeatureDialog), and 1662–1665 (EditFeatureDialog).
🧹 Nitpick comments (4)
apps/ui/src/components/views/board-view/worktree-panel/components/worktree-mobile-dropdown.tsx (2)
58-68: Badge styling is duplicated inline across multiple locations.The badge class string
"inline-flex items-center justify-center h-4 min-w-[1rem] px-1 text-[10px] font-medium rounded bg-background/80 text-foreground border border-border"is repeated in the trigger (Line 65) and the dropdown item (Line 101), and also appears identically inworktree-dropdown.tsx. Consider extracting a shared constant or utility for this badge style to reduce duplication.Also applies to: 99-104
78-109: Minor:onSelectvsonClickhandler inconsistency.The "All Worktrees" item uses
onSelect(Line 81) while individual worktree items useonClick(Line 124). Both work for RadixDropdownMenuItem, but using the same handler prop throughout would be more consistent.apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx (2)
417-425: Redundant double-check inisWorktreeSelected.Both
isAllWorktreesSelected(Line 421) andcurrentWorktree?.branch === ALL_WORKTREES_BRANCHare derived from the same state in the same render cycle. SinceisWorktreeSelectedis an inline function (not a stale callback), it always captures the current value ofisAllWorktreesSelected. The second check adds no safety.Not blocking — the intent is clear and it's harmless.
770-776: Minor: MissinguseWorktreesEnabledguard in dropdown layout path.Mobile (Line 581) guards
onSelectAllWorktreeswithuseWorktreesEnabled && nonMainWorktrees.length > 0, but the desktop dropdown layout (Line 774) only checksnonMainWorktrees.length > 0. While the dropdown path inherently requires 3+ worktrees (implying worktrees are enabled), aligning the conditions would be more defensive.Suggested alignment
onSelectAllWorktrees={ - nonMainWorktrees.length > 0 ? handleSelectAllWorktrees : undefined + useWorktreesEnabled && nonMainWorktrees.length > 0 ? handleSelectAllWorktrees : undefined }
When 3+ worktrees use the dropdown layout, temporary worktree pills appear during card drag to serve as drop targets. Reuses existing worktree-drop handler from use-board-drag-drop.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/ui/src/components/views/board-view.tsx (2)
640-654:⚠️ Potential issue | 🔴 CriticalSentinel
ALL_WORKTREES_BRANCHcan leak as a real branch name during bulk update.When the "All Worktrees" view is active,
currentWorktreeBranchis'__all_worktrees__'. InworkMode === 'current'(line 654), this truthy sentinel string becomesfinalBranchNameand is persisted as the feature'sbranchNameon line 709. This corrupts feature data with a non-existent branch.🐛 Proposed fix — guard against the sentinel in 'current' mode
if (workMode === 'current') { // If a worktree is selected, use its branch; otherwise work on main (undefined = no branch assignment) - finalBranchName = currentWorktreeBranch || undefined; + finalBranchName = + currentWorktreeBranch && currentWorktreeBranch !== ALL_WORKTREES_BRANCH + ? currentWorktreeBranch + : undefined;
1586-1586:⚠️ Potential issue | 🟡 MinorSentinel value may leak into dialog
currentBranchprops.
currentWorktreeBranch || undefinedevaluates to'__all_worktrees__'in ALL mode since the sentinel is truthy. This passes through toMassEditDialog(line 1586),AddFeatureDialog(line 1633), andEditFeatureDialog(line 1665) ascurrentBranch. Depending on how these dialogs render the value, users may see__all_worktrees__in the branch selector or it could affect branch-defaulting logic.Consider using
effectiveWorktreeBranch(which maps the sentinel tonull) instead:🛡️ Suggested fix
<MassEditDialog ... - currentBranch={currentWorktreeBranch || undefined} + currentBranch={effectiveWorktreeBranch || undefined} ... />Apply the same pattern at lines 1633 and 1665.
🧹 Nitpick comments (1)
apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx (1)
448-456:isWorktreeSelectedALL-mode guard is correct.The early return when ALL is selected properly prevents any individual worktree from appearing selected. Minor nit: the double check on line 452 (
isAllWorktreesSelected || currentWorktree?.branch === ALL_WORKTREES_BRANCH) is redundant sinceisAllWorktreesSelectedis defined as exactly that comparison (line 102), but it's harmless.
Summary
Closes #681
Closes #683
Changes
ALL_WORKTREES_BRANCHconstant inapp-store.ts— when selected, bypasses worktree filtering to show all featureseffectiveRunningAutoTasksfrom all worktrees when "All" is selected, so cards correctly show running stateFiles Modified
apps/ui/src/store/app-store.ts— ALL_WORKTREES_BRANCH constantapps/ui/src/components/views/board-view.tsx— Board view integration, effectiveWorktreeBranch, effectiveRunningAutoTasks, isDragging propapps/ui/src/components/views/board-view/hooks/use-board-column-features.ts— Branch bypass logicapps/ui/src/components/views/board-view/worktree-panel/types.ts— isDragging prop on WorktreePanelPropsapps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx— WorktreeDropPill component, drag drop targets, tab + dropdown integrationapps/ui/src/components/views/board-view/worktree-panel/components/worktree-dropdown.tsx— Dropdown "All" optionapps/ui/src/components/views/board-view/worktree-panel/components/worktree-mobile-dropdown.tsx— Mobile "All" optionapps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx— Deselection supportTest plan
🤖 Generated with Claude Code