Skip to content

Commit 4c16c68

Browse files
committed
Add worktree management surface spec
1 parent 2662060 commit 4c16c68

1 file changed

Lines changed: 271 additions & 0 deletions

File tree

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
---
2+
name: Worktree Management Surface Design
3+
description: Replace the dormant worktree button with a visible Git-panel worktree summary and manager across desktop and mobile
4+
type: project
5+
---
6+
7+
# Worktree Management Surface Design
8+
9+
## Overview
10+
11+
The repository already has most of the hard worktree plumbing: server commands for `list/status/diff/tree/create/remove`, a front-end `worktreeListAtomFamily`, live refresh wiring in `providers.tsx`, and a detail viewer (`WorktreeModal`). The problem is discoverability and placement. The original header button was both redundant and badly placed, so it was removed. That left the capability effectively hidden even though the data and modal still exist.
12+
13+
This spec replaces the orphaned header button with a visible but scoped worktree management surface inside the existing Git panel. The first visible layer should show basic facts at a glance; the second layer should support viewing details and managing worktrees.
14+
15+
## Goals
16+
17+
1. Make worktree information visible in the Git workflow on both desktop and mobile.
18+
2. Show basic worktree state at a glance: total count, dirty count, and current worktree.
19+
3. Provide a management flow for list, details, create, and delete.
20+
4. Reuse the existing worktree commands, atoms, and detail-loading logic instead of creating a parallel subsystem.
21+
5. Remove the dormant `WorktreeListButton` entry path and its tests once the replacement surface exists.
22+
23+
## Non-Goals
24+
25+
- Folding worktree management into the branch quick-pick main flow.
26+
- Opening another worktree as the current workspace in this first version.
27+
- Worktree rename, prune, repair, or advanced git maintenance actions.
28+
- Editing files or staging changes from the worktree detail viewer.
29+
30+
## Product Decision
31+
32+
### Why not the branch switcher
33+
34+
The branch switcher has a narrow job: change branches quickly. The requested capability is broader: inspect multiple worktrees and manage their lifecycle. Mixing those concerns would make the branch surface heavier, harder to scan, and harder to reason about. The entry point should live near Git management, not near quick branch selection.
35+
36+
### Chosen location
37+
38+
Place the worktree entry at the top of `GitPanel`, above the commit box and file change groups. This has three advantages:
39+
40+
1. It is visible without crowding the global Git status bar.
41+
2. `GitPanel` is already shared by desktop and mobile, so one placement decision serves both layouts.
42+
3. The feature stays inside the Git context, which matches the user’s mental model for “view/manage multiple worktrees.”
43+
44+
## User Experience
45+
46+
### 1. Summary card in `GitPanel`
47+
48+
Add a `WorktreesSummaryCard` as the first section inside `GitPanel`.
49+
50+
Displayed information:
51+
52+
- `Worktrees`: total number of worktrees in the repo.
53+
- `Dirty`: number of worktrees whose status is not clean.
54+
- `Current`: the worktree whose `path` matches the active workspace path.
55+
56+
Primary actions:
57+
58+
- `Manage`: opens the full worktree manager.
59+
- `New`: opens the create-worktree flow directly.
60+
61+
The card should stay compact. It is a summary and launch surface, not a full list. If loading fails, show a small inline error state and keep `Manage` available for retry.
62+
63+
### 2. Manager surface
64+
65+
Open a dedicated manager overlay from `Manage`.
66+
67+
- Desktop: modal card.
68+
- Mobile: sheet.
69+
70+
The manager should have two internal views instead of stacking multiple overlays:
71+
72+
- `list` view
73+
- `detail` view
74+
75+
This avoids modal-on-modal behavior and keeps navigation predictable on mobile.
76+
77+
`list` view contents:
78+
79+
- Header with title and close/back control.
80+
- Primary `New` action.
81+
- Worktree rows showing:
82+
- `name`
83+
- `branch`
84+
- `path`
85+
- `clean/dirty`
86+
- `current` badge when the row matches the active workspace path
87+
- Row tap/click opens `detail` view for that worktree.
88+
- Row-level delete affordance for non-current worktrees.
89+
90+
### 3. Detail view
91+
92+
The current `WorktreeModal` already supports `status / diff / tree`. That capability should remain, but the content should be reused inside the new manager instead of only being reachable from the old button flow.
93+
94+
Detail view should show:
95+
96+
- path
97+
- branch
98+
- latest commit sha/subject
99+
- clean/dirty state
100+
- tabbed content:
101+
- `Status`
102+
- `Diff`
103+
- `Tree`
104+
105+
If the selected worktree disappears externally while detail view is open, return to the list view and show a transient error or empty-state message.
106+
107+
### 4. Create flow
108+
109+
The first version must support creation, but it should stay simple.
110+
111+
Fields:
112+
113+
- `Branch` (required)
114+
- `Path` (required, prefilled with a suggested absolute path, editable)
115+
116+
Path behavior:
117+
118+
- Use the active workspace path to derive a default sibling path.
119+
- Suggestion format: `<workspace-parent>/<workspace-name>-<slugified-branch>`.
120+
- The user may edit the path before submission.
121+
122+
Validation:
123+
124+
- branch is required
125+
- path is required
126+
- path should be absolute before enabling submit
127+
128+
On success:
129+
130+
- close the create dialog/sheet
131+
- refresh the worktree list immediately
132+
- return the manager to list mode
133+
- surface a success toast
134+
135+
### 5. Delete flow
136+
137+
Delete must be guarded.
138+
139+
Rules:
140+
141+
- The current worktree cannot be deleted from this UI.
142+
- Clean, non-current worktrees require a standard destructive confirmation.
143+
- Dirty, non-current worktrees require an explicit `Force remove` confirmation path.
144+
145+
On success:
146+
147+
- refresh the worktree list immediately
148+
- if the deleted row was open in detail view, return to the list view
149+
- surface a success toast
150+
151+
## Architecture
152+
153+
### Web reuse
154+
155+
Keep and reuse:
156+
157+
- `worktreeListAtomFamily` in `packages/web/src/features/workspace/atoms/git.ts`
158+
- provider-driven refresh logic in `packages/web/src/app/providers.tsx`
159+
- `useWorktreeActions` data loading for `status/diff/tree`
160+
- existing worktree commands exposed by the server
161+
162+
Remove as an entry point:
163+
164+
- `packages/web/src/features/workspace/views/shared/worktree-list-button.tsx`
165+
- its tests once the replacement surface is covered
166+
167+
### Web component structure
168+
169+
Recommended structure:
170+
171+
- `GitPanel`
172+
- renders `WorktreesSummaryCard`
173+
- renders existing commit + change UI
174+
- `WorktreesSummaryCard`
175+
- loads `worktree.list` on first visible use if atom is empty/stale
176+
- computes summary metrics
177+
- opens manager or create flow
178+
- `WorktreeManagerSurface`
179+
- owns `list/detail/create/delete-confirm` local view state
180+
- adapts to desktop modal vs mobile sheet chrome
181+
- `WorktreeDetailPanel`
182+
- extracted from `WorktreeModal` so detail content can be embedded in the manager
183+
184+
`WorktreeModal` should either be removed entirely or reduced to a very thin wrapper around `WorktreeDetailPanel` if any caller still needs it during migration. The important part is that detail rendering must stop depending on the deleted header button flow.
185+
186+
### Current worktree detection
187+
188+
No core type change is required for the first version.
189+
190+
The UI can determine the current worktree by comparing:
191+
192+
- active workspace `path`
193+
- `WorktreeInfo.path`
194+
195+
This keeps the change localized to the web layer.
196+
197+
## Server-side adjustments
198+
199+
The existing server commands are almost sufficient, but create/remove should integrate with the same refresh loop as the rest of the workspace Git state.
200+
201+
Required change:
202+
203+
- `worktree.create` should emit `git.state.changed { worktreeChanged: true }`
204+
- `worktree.remove` should emit `git.state.changed { worktreeChanged: true }`
205+
206+
Why:
207+
208+
- external `git worktree add/remove` is already picked up by metadata refresh
209+
- UI-triggered create/remove should be equally observable without requiring ad hoc reload logic everywhere
210+
211+
Even with the event emission, the web manager should still refresh the list immediately after a successful create/remove so the user sees deterministic feedback without waiting for the debounce window.
212+
213+
## Data Flow
214+
215+
### Initial load
216+
217+
1. User opens the Git tab.
218+
2. `GitPanel` renders `WorktreesSummaryCard`.
219+
3. If `worktreeListAtomFamily(workspaceId)` has never loaded, dispatch `worktree.list`.
220+
4. The card renders loading, then summary metrics.
221+
222+
### Ongoing refresh
223+
224+
After initial load:
225+
226+
- provider refresh keeps the list up to date when `git_metadata` or `worktreeChanged` events arrive
227+
- create/remove success paths also trigger immediate local reload
228+
229+
### Detail loading
230+
231+
Selecting a row in the manager:
232+
233+
- sets the selected `WorktreeInfo`
234+
- reuses `useWorktreeActions` to load `status/diff/tree`
235+
- refetches when the selected tab changes or the selected worktree changes
236+
237+
## Error Handling
238+
239+
- `worktree.list` failure: show inline error in summary card and full manager retry state.
240+
- `worktree.status/diff/tree` failure: show inline error in detail view without closing the manager.
241+
- `worktree.create` failure: keep the create form open and show the error inline.
242+
- `worktree.remove` failure: keep the confirmation open and show the error inline.
243+
- stale selection after external removal: bounce from detail view back to list with a notice.
244+
245+
## Testing Strategy
246+
247+
### Server
248+
249+
- extend worktree command tests to assert that `worktree.create/remove` emit `worktreeChanged`
250+
251+
### Web
252+
253+
- summary card loads and displays total/dirty/current
254+
- summary card appears inside `GitPanel` on both desktop and mobile
255+
- manager list shows row metadata and current badge
256+
- manager opens detail view and reuses `status/diff/tree`
257+
- create success refreshes the list and shows the new row
258+
- delete is disabled/hidden for the current worktree
259+
- dirty delete requires force confirmation
260+
- old desktop header entry does not return
261+
262+
## Migration Notes
263+
264+
This is a replacement, not an additive entry point. The final state should have exactly one visible worktree management surface:
265+
266+
- visible summary in `GitPanel`
267+
- manager overlay behind that summary
268+
- no duplicate status-bar chip
269+
- no duplicate branch-header button
270+
271+
That keeps the feature discoverable without repeating the same action in multiple places.

0 commit comments

Comments
 (0)