Skip to content

Commit 526927c

Browse files
furiosaclaude
andcommitted
fix(sling): use polecat path from creation instead of re-computing
When spawning a polecat via `gt sling`, the code was discarding the return value from AddWithOptions()/RepairWorktreeWithOptions() and then calling Get() to retrieve the polecat object. This caused Get() to re-compute the clone path using os.Stat() checks, which fails for remote rigs where the worktree exists on a remote machine but not locally. This fix: 1. Uses the return value from AddWithOptions()/RepairWorktreeWithOptions() directly instead of calling Get() afterwards 2. Passes the correct ClonePath to the session manager via WorkDir option, ensuring the session starts in the right directory This ensures consistency between worktree creation and session startup, fixing the issue where polecats would get "not a git repository" errors when the os.Stat() fallback logic chose the wrong path. Fixes: gt-job89 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d78e70c commit 526927c

1 file changed

Lines changed: 16 additions & 8 deletions

File tree

internal/cmd/polecat_spawn.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec
8484
HookBead: opts.HookBead,
8585
}
8686

87+
// polecatObj will hold the polecat returned from Add or Repair.
88+
// We use this directly instead of calling Get() afterwards, because Get()
89+
// re-computes the path using os.Stat() which can fail for remote rigs.
90+
// See: gt-job89 - "gt sling creates worktree in nested subdirectory"
91+
var polecatObj *polecat.Polecat
92+
8793
if err == nil {
8894
// Stale state: polecat exists despite fresh name allocation - repair it
8995
// Check for uncommitted work first
@@ -96,25 +102,21 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec
96102
}
97103
}
98104
fmt.Printf("Repairing stale polecat %s with fresh worktree...\n", polecatName)
99-
if _, err = polecatMgr.RepairWorktreeWithOptions(polecatName, opts.Force, addOpts); err != nil {
105+
polecatObj, err = polecatMgr.RepairWorktreeWithOptions(polecatName, opts.Force, addOpts)
106+
if err != nil {
100107
return nil, fmt.Errorf("repairing stale polecat: %w", err)
101108
}
102109
} else if err == polecat.ErrPolecatNotFound {
103110
// Create new polecat
104111
fmt.Printf("Creating polecat %s...\n", polecatName)
105-
if _, err = polecatMgr.AddWithOptions(polecatName, addOpts); err != nil {
112+
polecatObj, err = polecatMgr.AddWithOptions(polecatName, addOpts)
113+
if err != nil {
106114
return nil, fmt.Errorf("creating polecat: %w", err)
107115
}
108116
} else {
109117
return nil, fmt.Errorf("getting polecat: %w", err)
110118
}
111119

112-
// Get polecat object for path info
113-
polecatObj, err := polecatMgr.Get(polecatName)
114-
if err != nil {
115-
return nil, fmt.Errorf("getting polecat after creation: %w", err)
116-
}
117-
118120
// Resolve account for runtime config
119121
accountsPath := constants.MayorAccountsPath(townRoot)
120122
claudeConfigDir, accountHandle, err := config.ResolveAccountConfigDir(accountsPath, opts.Account)
@@ -134,6 +136,12 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec
134136
fmt.Printf("Starting session for %s/%s...\n", rigName, polecatName)
135137
startOpts := polecat.SessionStartOptions{
136138
RuntimeConfigDir: claudeConfigDir,
139+
// Use the ClonePath from the polecat object directly, rather than
140+
// letting the session manager re-compute it via clonePath() which
141+
// uses os.Stat(). This ensures consistency for remote rigs where
142+
// the local filesystem check would fail.
143+
// See: gt-job89 - "gt sling creates worktree in nested subdirectory"
144+
WorkDir: polecatObj.ClonePath,
137145
}
138146
if opts.Agent != "" {
139147
cmd, err := config.BuildPolecatStartupCommandWithAgentOverride(rigName, polecatName, r.Path, "", opts.Agent)

0 commit comments

Comments
 (0)