From 91641b01a05d6be9569a0e1519a4ab402411a5fb Mon Sep 17 00:00:00 2001 From: Steve Brown Date: Sun, 11 Jan 2026 21:47:49 -0500 Subject: [PATCH] fix(done): auto-detect cleanup status to prevent premature nuke (#361) When polecats run 'gt done' without --cleanup-status, the witness may prematurely nuke the worktree before the refinery can merge. This fix auto-detects git state: - uncommitted: has uncommitted changes - stash: has stashed changes - unpushed: branch not pushed or has unpushed commits - clean: everything pushed Uses BranchPushedToRemote() which properly handles polecat branches that don't have upstream tracking (compares against origin/main). On error, defaults to 'unpushed' to prevent accidental data loss. Fixes: #342 Co-authored-by: mayor --- internal/cmd/done.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/internal/cmd/done.go b/internal/cmd/done.go index 9133707c..bf6b8bbc 100644 --- a/internal/cmd/done.go +++ b/internal/cmd/done.go @@ -119,6 +119,35 @@ func runDone(cmd *cobra.Command, args []string) error { return fmt.Errorf("getting current branch: %w", err) } + // Auto-detect cleanup status if not explicitly provided + // This prevents premature polecat cleanup by ensuring witness knows git state + if doneCleanupStatus == "" { + workStatus, err := g.CheckUncommittedWork() + if err != nil { + style.PrintWarning("could not auto-detect cleanup status: %v", err) + } else { + switch { + case workStatus.HasUncommittedChanges: + doneCleanupStatus = "uncommitted" + case workStatus.StashCount > 0: + doneCleanupStatus = "stash" + default: + // CheckUncommittedWork.UnpushedCommits doesn't work for branches + // without upstream tracking (common for polecats). Use the more + // robust BranchPushedToRemote which compares against origin/main. + pushed, unpushedCount, err := g.BranchPushedToRemote(branch, "origin") + if err != nil { + style.PrintWarning("could not check if branch is pushed: %v", err) + doneCleanupStatus = "unpushed" // err on side of caution + } else if !pushed || unpushedCount > 0 { + doneCleanupStatus = "unpushed" + } else { + doneCleanupStatus = "clean" + } + } + } + } + // Parse branch info info := parseBranchName(branch)