fix(sling): Set hook_bead atomically at polecat spawn time (gt-h46pk)
When slinging work to a rig (auto-spawning a polecat), the hook_bead is now set atomically during agent bead creation rather than in a separate updateAgentHookBead call after spawn. This fixes cross-beads routing issues when town beads (hq-*) are slung to rig polecats (gt-* agent beads). By setting hook_bead at creation time within the polecat manager context, the correct beads routing is used. Changes: - Add AddOptions struct with HookBead field to polecat.Manager - Add AddWithOptions() and RecreateWithOptions() functions - Pass HookBead through SlingSpawnOptions in cmd/polecat_spawn.go - Pass beadID as HookBead in cmd/sling.go for rig target spawns Note: updateAgentHookBead() is kept for non-spawn targets (existing agents) and formula-on-bead mode (updates hook to wisp root after creation). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
Steve Yegge
parent
a85fae73a5
commit
e159489edb
@@ -34,10 +34,11 @@ func (s *SpawnedPolecatInfo) AgentID() string {
|
||||
|
||||
// SlingSpawnOptions contains options for spawning a polecat via sling.
|
||||
type SlingSpawnOptions struct {
|
||||
Force bool // Force spawn even if polecat has uncommitted work
|
||||
Naked bool // No-tmux mode: skip session creation
|
||||
Account string // Claude Code account handle to use
|
||||
Create bool // Create polecat if it doesn't exist (currently always true for sling)
|
||||
Force bool // Force spawn even if polecat has uncommitted work
|
||||
Naked bool // No-tmux mode: skip session creation
|
||||
Account string // Claude Code account handle to use
|
||||
Create bool // Create polecat if it doesn't exist (currently always true for sling)
|
||||
HookBead string // Bead ID to set as hook_bead at spawn time (atomic assignment)
|
||||
}
|
||||
|
||||
// SpawnPolecatForSling creates a fresh polecat and optionally starts its session.
|
||||
@@ -77,6 +78,12 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec
|
||||
|
||||
// Check if polecat already exists (shouldn't, since we allocated fresh)
|
||||
existingPolecat, err := polecatMgr.Get(polecatName)
|
||||
|
||||
// Build add options with hook_bead set atomically at spawn time
|
||||
addOpts := polecat.AddOptions{
|
||||
HookBead: opts.HookBead,
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
// Exists - recreate with fresh worktree
|
||||
// Check for uncommitted work first
|
||||
@@ -89,13 +96,13 @@ func SpawnPolecatForSling(rigName string, opts SlingSpawnOptions) (*SpawnedPolec
|
||||
}
|
||||
}
|
||||
fmt.Printf("Recreating polecat %s with fresh worktree...\n", polecatName)
|
||||
if _, err = polecatMgr.Recreate(polecatName, opts.Force); err != nil {
|
||||
if _, err = polecatMgr.RecreateWithOptions(polecatName, opts.Force, addOpts); err != nil {
|
||||
return nil, fmt.Errorf("recreating polecat: %w", err)
|
||||
}
|
||||
} else if err == polecat.ErrPolecatNotFound {
|
||||
// Create new polecat
|
||||
fmt.Printf("Creating polecat %s...\n", polecatName)
|
||||
if _, err = polecatMgr.Add(polecatName); err != nil {
|
||||
if _, err = polecatMgr.AddWithOptions(polecatName, addOpts); err != nil {
|
||||
return nil, fmt.Errorf("creating polecat: %w", err)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -238,10 +238,11 @@ func runSling(cmd *cobra.Command, args []string) error {
|
||||
// Spawn a fresh polecat in the rig
|
||||
fmt.Printf("Target is rig '%s', spawning fresh polecat...\n", rigName)
|
||||
spawnOpts := SlingSpawnOptions{
|
||||
Force: slingForce,
|
||||
Naked: slingNaked,
|
||||
Account: slingAccount,
|
||||
Create: slingCreate,
|
||||
Force: slingForce,
|
||||
Naked: slingNaked,
|
||||
Account: slingAccount,
|
||||
Create: slingCreate,
|
||||
HookBead: beadID, // Set atomically at spawn time
|
||||
}
|
||||
spawnInfo, spawnErr := SpawnPolecatForSling(rigName, spawnOpts)
|
||||
if spawnErr != nil {
|
||||
|
||||
Reference in New Issue
Block a user