fix(ccw): handle prunable worktrees in picker and clean-up flows#46
Conversation
ccw 起動時に git worktree list --porcelain の prunable エントリで git status が exit 128 を返し起動失敗する問題への対応方針を spec 化。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
設計 spec を bite-sized タスクに展開。gitx → worktree → picker → cmd/ccw の順で TDD で実装し、最後に terraform-github での手動受け入れまで含める。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
git worktree list --porcelain lists prunable entries (working directory gone but admin files remain). ParsePorcelain now records this on WorktreeEntry.Prunable, and the new Prune helper wraps git worktree prune for callers that want to clean them up. Also fix pre-existing picker test failures from bubbletea v2 upgrade: tea.View is now a struct (use .Content for string), and lipgloss v2 removed ColorProfile/SetColorProfile from the top-level API.
When git worktree list reports a prunable entry, surface it as StatusPrunable instead of running git status on a missing path (which fails with exit 128 and broke ccw startup). The new Prune helper wraps gitx.Prune so the picker can clean these up.
Selection.IsPrunable and BulkDeletion.RunPrune let the caller decide when to invoke worktree.Prune instead of (or in addition to) worktree.Remove. Bulk paths now exclude prunable entries since git worktree remove cannot act on them.
Adds the prunable badge ([prune]/PRUNE) and the 🧹 icon in the legacy Icon API. Prunable rows replace ahead/behind/dirty indicators with a (missing on disk) hint since the working directory is gone.
Selecting a prunable row and pressing 'd' now shows a Prune prompt that runs git worktree prune. When more than one prunable exists, the confirm view enumerates all affected entries so the user knows the prune is global, not just the selected one.
Bulk confirm view notes when a prune step will follow the removals, and the existing flow lets users mix prunable + normal targets without hitting the dirty-confirmation branch.
Selecting a prunable row in the picker now runs worktree.Prune, and bulk delete invocations follow the removals with a single prune call when prunable targets were selected.
runCleanAll built BulkDeletion directly without honoring the prunable short-circuit added to picker.Bulk(). With Tasks 1-2 making prunable entries visible to the worktree List, --clean-all would otherwise try to git worktree remove on missing paths and emit per-entry errors. Now prunable rows are excluded from Paths and a single worktree.Prune call runs at the end via RunPrune. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR implements comprehensive support for handling Git worktrees marked Changes
Sequence DiagramsequenceDiagram
participant User
participant Picker UI
participant Main CLI
participant Git Worktree
User->>Picker UI: Select prunable worktree for deletion
Picker UI->>Picker UI: Detect StatusPrunable status
Picker UI->>User: Show "Prune worktree...?" confirmation
User->>Picker UI: Confirm prune action
Picker UI->>Main CLI: Return Selection with IsPrunable=true
Main CLI->>Git Worktree: Call worktree.Prune(mainRepo)
Git Worktree->>Git Worktree: Execute `git worktree prune`
Git Worktree-->>Main CLI: Success/Error
Main CLI->>User: Resume picker or return result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
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 docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
cmd/ccw/main.go (1)
219-242: Minor:confirmCleanAlland the dry-run output use "remove" wording that isn't accurate for prunable targets.When
--clean-allincludes prunable entries, the user is shownwill remove N worktree(s)and the dry-run printswould remove N worktree(s):— but prunable targets won't actually be removed viagit worktree remove; they'll be cleaned bygit worktree pruneinstead. Consider adding a small note (similar to the picker'sbulkConfirmViewinfo line atinternal/picker/view.go:124) when any target is prunable so the prompt matches the actual operation.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/ccw/main.go` around lines 219 - 242, Update the confirmCleanAll prompt and the dry-run output to distinguish prunable targets from removable ones: detect when any selected target has StatusPrunable (use the same logic as the loop that sets BulkDeletion.RunPrune and bulk.Paths in main.go) and change the message from "will remove N worktree(s)" / "would remove N worktree(s):" to reflect mixed actions (e.g. "will remove X worktree(s) and prune Y prunable worktree(s)") or append a short note that prunable entries will be handled by git worktree prune; modify confirmCleanAll (and any dry-run printing code) to include this note when any prunable target is present, mirroring the explanatory line used in picker.bulkConfirmView.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/superpowers/specs/2026-04-25-prunable-worktree-handling-design.md`:
- Around line 105-106: Summary: The bulk deletion confirmation prompt is missing
an explicit warning that git worktree prune may remove prunable entries that are
not selected. Fix: Update the bulk deletion confirmation copy (the bulk deletion
confirmation prompt / confirmation text displayed before running git worktree
prune) to include a clear, concise warning sentence stating that "git worktree
prune may remove prunable entries that are not currently selected; proceed only
if you understand this may delete additional worktrees." Place this sentence
prominently near the top of the confirmation message so users see it before the
confirm action; ensure the text references git worktree prune explicitly and
appears in the same UI string or function that builds the bulk deletion
confirmation prompt.
- Line 142: The statement claiming “no breaking API change” is too strong
because adding the StatusPrunable member to the exported Status enum can break
consumers that rely on exhaustive switch/case handling; update the wording to
say there is “no signature-level breaking change” (i.e., no change to
function/class/type signatures) and add a short caveat explaining that enum
expansion is a potential source of breaking behavior for exhaustive
pattern-matching in downstream code, recommend consumers handle unknown/new
Status values (or include a default branch) and document the change and
mitigation in the design note alongside references to Status, StatusPrunable,
and WorktreeEntry.
---
Nitpick comments:
In `@cmd/ccw/main.go`:
- Around line 219-242: Update the confirmCleanAll prompt and the dry-run output
to distinguish prunable targets from removable ones: detect when any selected
target has StatusPrunable (use the same logic as the loop that sets
BulkDeletion.RunPrune and bulk.Paths in main.go) and change the message from
"will remove N worktree(s)" / "would remove N worktree(s):" to reflect mixed
actions (e.g. "will remove X worktree(s) and prune Y prunable worktree(s)") or
append a short note that prunable entries will be handled by git worktree prune;
modify confirmCleanAll (and any dry-run printing code) to include this note when
any prunable target is present, mirroring the explanatory line used in
picker.bulkConfirmView.
🪄 Autofix (Beta)
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
Run ID: 2a732afe-6358-4161-9928-4560b8271455
📒 Files selected for processing (17)
cmd/ccw/main.godocs/superpowers/plans/2026-04-25-prunable-worktree-handling.mddocs/superpowers/specs/2026-04-25-prunable-worktree-handling-design.mdinternal/gitx/worktree.gointernal/gitx/worktree_test.gointernal/picker/bulk.gointernal/picker/bulk_test.gointernal/picker/delegate.gointernal/picker/model.gointernal/picker/model_test.gointernal/picker/style.gointernal/picker/style_test.gointernal/picker/update.gointernal/picker/view.gointernal/picker/view_test.gointernal/worktree/worktree.gointernal/worktree/worktree_test.go
| - `git worktree prune` は全 prunable をまとめて掃除するため、選択していない prunable も巻き込まれる可能性があるが、bulk 削除確認画面には全選択 prunable が並んでいる前提で許容する (将来必要なら警告文を追加)。 | ||
|
|
There was a problem hiding this comment.
Add an explicit warning in the current bulk confirmation copy
Line 105 acknowledges that git worktree prune can remove unselected prunable entries, but defers warning text to “future.” This should be surfaced now in the confirmation prompt to avoid surprising destructive side effects.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/superpowers/specs/2026-04-25-prunable-worktree-handling-design.md`
around lines 105 - 106, Summary: The bulk deletion confirmation prompt is
missing an explicit warning that git worktree prune may remove prunable entries
that are not selected. Fix: Update the bulk deletion confirmation copy (the bulk
deletion confirmation prompt / confirmation text displayed before running git
worktree prune) to include a clear, concise warning sentence stating that "git
worktree prune may remove prunable entries that are not currently selected;
proceed only if you understand this may delete additional worktrees." Place this
sentence prominently near the top of the confirmation message so users see it
before the confirm action; ensure the text references git worktree prune
explicitly and appears in the same UI string or function that builds the bulk
deletion confirmation prompt.
| ## 影響範囲 | ||
|
|
||
| - 変更ファイル: `internal/gitx/worktree.go`, `internal/worktree/worktree.go`, `internal/picker/{style,delegate,update,model}.go` (および対応するテスト)。 | ||
| - 公開 API への破壊的変更なし (`WorktreeEntry` / `Status` への追加のみ)。 |
There was a problem hiding this comment.
Soften the “no breaking API change” statement for Status enum expansion
Line 142 says no breaking API change, but adding StatusPrunable can still break downstream exhaustive switch logic in consumers of exported Status. Recommend clarifying this as “no signature-level breaking change” and documenting the enum expansion caveat.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/superpowers/specs/2026-04-25-prunable-worktree-handling-design.md` at
line 142, The statement claiming “no breaking API change” is too strong because
adding the StatusPrunable member to the exported Status enum can break consumers
that rely on exhaustive switch/case handling; update the wording to say there is
“no signature-level breaking change” (i.e., no change to function/class/type
signatures) and add a short caveat explaining that enum expansion is a potential
source of breaking behavior for exhaustive pattern-matching in downstream code,
recommend consumers handle unknown/new Status values (or include a default
branch) and document the change and mitigation in the design note alongside
references to Status, StatusPrunable, and WorktreeEntry.
…-9951 # Conflicts: # internal/picker/style_test.go # internal/picker/view_test.go
Summary
git worktree list --porcelainのprunable行をパースし、worktree.StatusPrunableを新設。worktree.Listがディスクへ触らずに分類することで、ディレクトリ消失済み worktree が混在してもccwがgit status --porcelain: exit status 128でクラッシュしなくなる。[prune]バッジを追加し、単独削除では 1 件 / 複数件で確認文言を出し分け、bulk 削除と--clean-allでも prunable を含めてgit worktree pruneを最後に 1 回呼ぶ。docs/superpowers/specs/2026-04-25-prunable-worktree-handling-design.md/ 計画:docs/superpowers/plans/2026-04-25-prunable-worktree-handling.md。Test Plan
go test ./...(178 / 14 packages)~/workspace/tqer39/terraform-githubで再現確認: 起動時クラッシュが解消し、picker にsynchronous-finding-wave (prunable)が表示されるgit worktree prune実行で一覧から消えることを TUI で目視確認--clean-allで prunable を含む worktree がまとめて掃除されることを確認🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
git worktree prunecleanup functionalityDocumentation