From 871410f15773bda26cd5f6bfa9c028d9db79ccc6 Mon Sep 17 00:00:00 2001 From: dinki Date: Sun, 4 Jan 2026 14:25:53 -0800 Subject: [PATCH] refactor: Rename RecreateWithOptions to RepairWorktreeWithOptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify that this operation is for stale state recovery, not normal recycling: - Recreate → RepairWorktree - RecreateWithOptions → RepairWorktreeWithOptions - Updated comments to explain this handles reconciliation when AllocateName returns a name that already exists (stale state needing repair) - Updated polecat_spawn.go output: Recreating → Repairing stale - Updated gc command help text for consistency The function is useful for atomic hook_bead setting during repair, so kept rather than replacing with Remove + Add. Fixes gt-l0lok 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/cmd/polecat.go | 4 ++-- internal/cmd/polecat_spawn.go | 10 +++++----- internal/polecat/manager.go | 22 +++++++++++++--------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/internal/cmd/polecat.go b/internal/cmd/polecat.go index cf381d34..c5a844df 100644 --- a/internal/cmd/polecat.go +++ b/internal/cmd/polecat.go @@ -147,8 +147,8 @@ var polecatGCCmd = &cobra.Command{ Long: `Garbage collect stale polecat branches in a rig. Polecats use unique timestamped branches (polecat/-) to -prevent drift issues. Over time, these branches accumulate as polecats -are recreated. +prevent drift issues. Over time, these branches accumulate when stale +polecats are repaired. This command removes orphaned branches: - Branches for polecats that no longer exist diff --git a/internal/cmd/polecat_spawn.go b/internal/cmd/polecat_spawn.go index 9d25f17b..879e34a4 100644 --- a/internal/cmd/polecat_spawn.go +++ b/internal/cmd/polecat_spawn.go @@ -76,7 +76,7 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec } fmt.Printf("Allocated polecat: %s\n", polecatName) - // Check if polecat already exists (shouldn't, since we allocated fresh) + // Check if polecat already exists (shouldn't happen - indicates stale state needing repair) existingPolecat, err := polecatMgr.Get(polecatName) // Build add options with hook_bead set atomically at spawn time @@ -85,7 +85,7 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec } if err == nil { - // Exists - recreate with fresh worktree + // Stale state: polecat exists despite fresh name allocation - repair it // Check for uncommitted work first if !opts.Force { pGit := git.NewGit(existingPolecat.ClonePath) @@ -95,9 +95,9 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec polecatName, workStatus.String()) } } - fmt.Printf("Recreating polecat %s with fresh worktree...\n", polecatName) - if _, err = polecatMgr.RecreateWithOptions(polecatName, opts.Force, addOpts); err != nil { - return nil, fmt.Errorf("recreating polecat: %w", err) + fmt.Printf("Repairing stale polecat %s with fresh worktree...\n", polecatName) + if _, err = polecatMgr.RepairWorktreeWithOptions(polecatName, opts.Force, addOpts); err != nil { + return nil, fmt.Errorf("repairing stale polecat: %w", err) } } else if err == polecat.ErrPolecatNotFound { // Create new polecat diff --git a/internal/polecat/manager.go b/internal/polecat/manager.go index 0d0b5cc8..de6e109a 100644 --- a/internal/polecat/manager.go +++ b/internal/polecat/manager.go @@ -385,20 +385,24 @@ func (m *Manager) ReleaseName(name string) { _ = m.namePool.Save() // non-fatal: state file update } -// Recreate removes an existing polecat and creates a fresh worktree. -// This ensures the polecat starts with the latest code from the base branch. -// The name is preserved (not released to pool) since we're recreating immediately. +// RepairWorktree repairs a stale polecat by removing it and creating a fresh worktree. +// This is NOT for normal operation - it handles reconciliation when AllocateName +// returns a name that unexpectedly already exists (stale state recovery). +// +// The polecat starts with the latest code from origin/. +// The name is preserved (not released to pool) since we're repairing immediately. // force controls whether to bypass uncommitted changes check. // -// Branch naming: Each recreation gets a unique branch (polecat/-). +// Branch naming: Each repair gets a unique branch (polecat/-). // Old branches are left for garbage collection - they're never pushed to origin. -func (m *Manager) Recreate(name string, force bool) (*Polecat, error) { - return m.RecreateWithOptions(name, force, AddOptions{}) +func (m *Manager) RepairWorktree(name string, force bool) (*Polecat, error) { + return m.RepairWorktreeWithOptions(name, force, AddOptions{}) } -// RecreateWithOptions removes an existing polecat and creates a fresh worktree with options. -// This allows setting hook_bead atomically at recreation time. -func (m *Manager) RecreateWithOptions(name string, force bool, opts AddOptions) (*Polecat, error) { +// RepairWorktreeWithOptions repairs a stale polecat and creates a fresh worktree with options. +// This is NOT for normal operation - see RepairWorktree for context. +// Allows setting hook_bead atomically at repair time. +func (m *Manager) RepairWorktreeWithOptions(name string, force bool, opts AddOptions) (*Polecat, error) { if !m.exists(name) { return nil, ErrPolecatNotFound }