fix(sling): Add --no-daemon and BEADS_DIR for reliable bd calls

- Add --no-daemon to all 17 bd exec calls to bypass daemon socket timing issues
- Set BEADS_DIR in verifyBeadExists() so bd can find beads from any directory

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Greg Hughes
2026-01-04 23:28:13 -08:00
parent e0ba057821
commit afe5cab0ad

View File

@@ -376,7 +376,7 @@ func runSling(cmd *cobra.Command, args []string) error {
fmt.Printf(" Instantiating formula %s...\n", formulaName) fmt.Printf(" Instantiating formula %s...\n", formulaName)
// Step 1: Cook the formula (ensures proto exists) // Step 1: Cook the formula (ensures proto exists)
cookCmd := exec.Command("bd", "cook", formulaName) cookCmd := exec.Command("bd", "--no-daemon", "cook", formulaName)
cookCmd.Stderr = os.Stderr cookCmd.Stderr = os.Stderr
if err := cookCmd.Run(); err != nil { if err := cookCmd.Run(); err != nil {
return fmt.Errorf("cooking formula %s: %w", formulaName, err) return fmt.Errorf("cooking formula %s: %w", formulaName, err)
@@ -384,7 +384,7 @@ func runSling(cmd *cobra.Command, args []string) error {
// Step 2: Create wisp with feature variable from bead title // Step 2: Create wisp with feature variable from bead title
featureVar := fmt.Sprintf("feature=%s", info.Title) featureVar := fmt.Sprintf("feature=%s", info.Title)
wispArgs := []string{"mol", "wisp", formulaName, "--var", featureVar, "--json"} wispArgs := []string{"--no-daemon", "mol", "wisp", formulaName, "--var", featureVar, "--json"}
wispCmd := exec.Command("bd", wispArgs...) wispCmd := exec.Command("bd", wispArgs...)
wispCmd.Stderr = os.Stderr wispCmd.Stderr = os.Stderr
wispOut, err := wispCmd.Output() wispOut, err := wispCmd.Output()
@@ -433,7 +433,7 @@ func runSling(cmd *cobra.Command, args []string) error {
// Hook the bead using bd update // Hook the bead using bd update
// Set BEADS_DIR to town-level beads so hq-* beads are accessible // Set BEADS_DIR to town-level beads so hq-* beads are accessible
// even when running from polecat worktree (which only sees gt-* via redirect) // even when running from polecat worktree (which only sees gt-* via redirect)
hookCmd := exec.Command("bd", "update", beadID, "--status=hooked", "--assignee="+targetAgent) hookCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--status=hooked", "--assignee="+targetAgent)
hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir) hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir)
if hookWorkDir != "" { if hookWorkDir != "" {
hookCmd.Dir = hookWorkDir hookCmd.Dir = hookWorkDir
@@ -488,7 +488,7 @@ func runSling(cmd *cobra.Command, args []string) error {
// This enables no-tmux mode where agents discover args via gt prime / bd show. // This enables no-tmux mode where agents discover args via gt prime / bd show.
func storeArgsInBead(beadID, args string) error { func storeArgsInBead(beadID, args string) error {
// Get the bead to preserve existing description content // Get the bead to preserve existing description content
showCmd := exec.Command("bd", "show", beadID, "--json") showCmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json")
out, err := showCmd.Output() out, err := showCmd.Output()
if err != nil { if err != nil {
return fmt.Errorf("fetching bead: %w", err) return fmt.Errorf("fetching bead: %w", err)
@@ -517,7 +517,7 @@ func storeArgsInBead(beadID, args string) error {
newDesc := beads.SetAttachmentFields(issue, fields) newDesc := beads.SetAttachmentFields(issue, fields)
// Update the bead // Update the bead
updateCmd := exec.Command("bd", "update", beadID, "--description="+newDesc) updateCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--description="+newDesc)
updateCmd.Stderr = os.Stderr updateCmd.Stderr = os.Stderr
if err := updateCmd.Run(); err != nil { if err := updateCmd.Run(); err != nil {
return fmt.Errorf("updating bead description: %w", err) return fmt.Errorf("updating bead description: %w", err)
@@ -645,7 +645,12 @@ func sessionToAgentID(sessionName string) string {
// verifyBeadExists checks that the bead exists using bd show. // verifyBeadExists checks that the bead exists using bd show.
func verifyBeadExists(beadID string) error { func verifyBeadExists(beadID string) error {
cmd := exec.Command("bd", "show", beadID, "--json") cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json")
// Set BEADS_DIR to town root so hq-* beads are accessible
if townRoot, err := workspace.FindFromCwd(); err == nil {
cmd.Env = append(os.Environ(), "BEADS_DIR="+filepath.Join(townRoot, ".beads"))
cmd.Dir = townRoot
}
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
return fmt.Errorf("bead '%s' not found (bd show failed)", beadID) return fmt.Errorf("bead '%s' not found (bd show failed)", beadID)
} }
@@ -661,7 +666,7 @@ type beadInfo struct {
// getBeadInfo returns status and assignee for a bead. // getBeadInfo returns status and assignee for a bead.
func getBeadInfo(beadID string) (*beadInfo, error) { func getBeadInfo(beadID string) (*beadInfo, error) {
cmd := exec.Command("bd", "show", beadID, "--json") cmd := exec.Command("bd", "--no-daemon", "show", beadID, "--json")
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
return nil, fmt.Errorf("bead '%s' not found", beadID) return nil, fmt.Errorf("bead '%s' not found", beadID)
@@ -730,13 +735,13 @@ func resolveSelfTarget() (agentID string, pane string, hookRoot string, err erro
// Formulas are TOML files (.formula.toml). // Formulas are TOML files (.formula.toml).
func verifyFormulaExists(formulaName string) error { func verifyFormulaExists(formulaName string) error {
// Try bd formula show (handles all formula file formats) // Try bd formula show (handles all formula file formats)
cmd := exec.Command("bd", "formula", "show", formulaName) cmd := exec.Command("bd", "--no-daemon", "formula", "show", formulaName)
if err := cmd.Run(); err == nil { if err := cmd.Run(); err == nil {
return nil return nil
} }
// Try with mol- prefix // Try with mol- prefix
cmd = exec.Command("bd", "formula", "show", "mol-"+formulaName) cmd = exec.Command("bd", "--no-daemon", "formula", "show", "mol-"+formulaName)
if err := cmd.Run(); err == nil { if err := cmd.Run(); err == nil {
return nil return nil
} }
@@ -859,7 +864,7 @@ func runSlingFormula(args []string) error {
// Step 1: Cook the formula (ensures proto exists) // Step 1: Cook the formula (ensures proto exists)
fmt.Printf(" Cooking formula...\n") fmt.Printf(" Cooking formula...\n")
cookArgs := []string{"cook", formulaName} cookArgs := []string{"--no-daemon", "cook", formulaName}
cookCmd := exec.Command("bd", cookArgs...) cookCmd := exec.Command("bd", cookArgs...)
cookCmd.Stderr = os.Stderr cookCmd.Stderr = os.Stderr
if err := cookCmd.Run(); err != nil { if err := cookCmd.Run(); err != nil {
@@ -868,7 +873,7 @@ func runSlingFormula(args []string) error {
// Step 2: Create wisp instance (ephemeral) // Step 2: Create wisp instance (ephemeral)
fmt.Printf(" Creating wisp...\n") fmt.Printf(" Creating wisp...\n")
wispArgs := []string{"mol", "wisp", formulaName} wispArgs := []string{"--no-daemon", "mol", "wisp", formulaName}
for _, v := range slingVars { for _, v := range slingVars {
wispArgs = append(wispArgs, "--var", v) wispArgs = append(wispArgs, "--var", v)
} }
@@ -895,7 +900,7 @@ func runSlingFormula(args []string) error {
// Step 3: Hook the wisp bead using bd update (discovery-based approach) // Step 3: Hook the wisp bead using bd update (discovery-based approach)
// Set BEADS_DIR to town-level beads so hq-* beads are accessible // Set BEADS_DIR to town-level beads so hq-* beads are accessible
hookCmd := exec.Command("bd", "update", wispResult.RootID, "--status=hooked", "--assignee="+targetAgent) hookCmd := exec.Command("bd", "--no-daemon", "update", wispResult.RootID, "--status=hooked", "--assignee="+targetAgent)
hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir) hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir)
hookCmd.Dir = townRoot hookCmd.Dir = townRoot
hookCmd.Stderr = os.Stderr hookCmd.Stderr = os.Stderr
@@ -1291,7 +1296,7 @@ func createAutoConvoy(beadID, beadTitle string) (string, error) {
"--description=" + description, "--description=" + description,
} }
createCmd := exec.Command("bd", createArgs...) createCmd := exec.Command("bd", append([]string{"--no-daemon"}, createArgs...)...)
createCmd.Dir = townBeads createCmd.Dir = townBeads
createCmd.Stderr = os.Stderr createCmd.Stderr = os.Stderr
@@ -1301,7 +1306,7 @@ func createAutoConvoy(beadID, beadTitle string) (string, error) {
// Add tracking relation: convoy tracks the issue // Add tracking relation: convoy tracks the issue
trackBeadID := formatTrackBeadID(beadID) trackBeadID := formatTrackBeadID(beadID)
depArgs := []string{"dep", "add", convoyID, trackBeadID, "--type=tracks"} depArgs := []string{"--no-daemon", "dep", "add", convoyID, trackBeadID, "--type=tracks"}
depCmd := exec.Command("bd", depArgs...) depCmd := exec.Command("bd", depArgs...)
depCmd.Dir = townBeads depCmd.Dir = townBeads
depCmd.Stderr = os.Stderr depCmd.Stderr = os.Stderr
@@ -1398,7 +1403,7 @@ func runBatchSling(beadIDs []string, rigName string, townBeadsDir string) error
} }
// Hook the bead // Hook the bead
hookCmd := exec.Command("bd", "update", beadID, "--status=hooked", "--assignee="+targetAgent) hookCmd := exec.Command("bd", "--no-daemon", "update", beadID, "--status=hooked", "--assignee="+targetAgent)
hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir) hookCmd.Env = append(os.Environ(), "BEADS_DIR="+townBeadsDir)
if hookWorkDir != "" { if hookWorkDir != "" {
hookCmd.Dir = hookWorkDir hookCmd.Dir = hookWorkDir