fix: ensure rig beads init targets rig DB

Retry bd init without --no-agents when the flag is unsupported, and ensure agent bead creation uses the rig .beads directory to avoid prefix mismatches.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Dan Shapiro
2026-01-01 16:06:24 -08:00
parent 3672e659d5
commit b22b86d31b
2 changed files with 137 additions and 1 deletions

View File

@@ -418,7 +418,19 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
// Run bd init if available, with --no-agents to skip AGENTS.md creation
cmd := exec.Command("bd", "init", "--prefix", prefix, "--no-agents")
cmd.Dir = rigPath
if err := cmd.Run(); err != nil {
output, err := cmd.CombinedOutput()
if err != nil {
lower := strings.ToLower(string(output))
if strings.Contains(lower, "no-agents") &&
(strings.Contains(lower, "unknown flag") ||
strings.Contains(lower, "unknown option") ||
strings.Contains(lower, "flag provided but not defined")) {
retry := exec.Command("bd", "init", "--prefix", prefix)
retry.Dir = rigPath
if retryErr := retry.Run(); retryErr == nil {
return nil
}
}
// bd might not be installed or --no-agents not supported, create minimal structure
// Note: beads currently expects YAML format for config
configPath := filepath.Join(beadsDir, "config.yaml")
@@ -438,6 +450,18 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
func (m *Manager) initAgentBeads(rigPath, rigName, prefix string, isFirstRig bool) error {
// Run bd commands from mayor/rig which has the beads database
mayorRigPath := filepath.Join(rigPath, "mayor", "rig")
beadsDir := filepath.Join(rigPath, ".beads")
prevBeadsDir, hadBeadsDir := os.LookupEnv("BEADS_DIR")
if err := os.Setenv("BEADS_DIR", beadsDir); err != nil {
return fmt.Errorf("setting BEADS_DIR: %w", err)
}
defer func() {
if hadBeadsDir {
_ = os.Setenv("BEADS_DIR", prevBeadsDir)
} else {
_ = os.Unsetenv("BEADS_DIR")
}
}()
bd := beads.New(mayorRigPath)
// Define agents to create

View File

@@ -21,6 +21,16 @@ func setupTestTown(t *testing.T) (string, *config.RigsConfig) {
return root, rigsConfig
}
func writeFakeBD(t *testing.T, script string) string {
t.Helper()
binDir := t.TempDir()
scriptPath := filepath.Join(binDir, "bd")
if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
t.Fatalf("write fake bd: %v", err)
}
return binDir
}
func createTestRig(t *testing.T, root, name string) {
t.Helper()
@@ -251,3 +261,105 @@ func TestEnsureGitignoreEntry_AppendsToExisting(t *testing.T) {
t.Errorf("content = %q, want %q", string(content), expected)
}
}
func TestInitBeadsRetriesWithoutNoAgentsFlag(t *testing.T) {
rigPath := t.TempDir()
beadsDir := filepath.Join(rigPath, ".beads")
script := `#!/usr/bin/env bash
set -e
cmd="$1"
shift
if [[ "$cmd" == "init" ]]; then
for arg in "$@"; do
if [[ "$arg" == "--no-agents" ]]; then
echo "unknown flag: --no-agents" >&2
exit 1
fi
done
touch "$EXPECT_BEADS_DIR/created.db"
exit 0
fi
echo "unexpected command: $cmd" >&2
exit 1
`
binDir := writeFakeBD(t, script)
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("EXPECT_BEADS_DIR", beadsDir)
manager := &Manager{}
if err := manager.initBeads(rigPath, "gt"); err != nil {
t.Fatalf("initBeads: %v", err)
}
if _, err := os.Stat(filepath.Join(beadsDir, "created.db")); err != nil {
t.Fatalf("expected bd init to create db file: %v", err)
}
}
func TestInitAgentBeadsUsesRigBeadsDir(t *testing.T) {
rigPath := t.TempDir()
beadsDir := filepath.Join(rigPath, ".beads")
mayorRigPath := filepath.Join(rigPath, "mayor", "rig")
if err := os.MkdirAll(beadsDir, 0755); err != nil {
t.Fatalf("mkdir beads dir: %v", err)
}
if err := os.MkdirAll(mayorRigPath, 0755); err != nil {
t.Fatalf("mkdir mayor rig: %v", err)
}
script := `#!/usr/bin/env bash
set -e
if [[ "$1" == "--no-daemon" ]]; then
shift
fi
cmd="$1"
shift
case "$cmd" in
show)
if [[ "$BEADS_DIR" != "$EXPECT_BEADS_DIR" ]]; then
echo "BEADS_DIR mismatch" >&2
exit 1
fi
echo "[]"
;;
create)
if [[ "$BEADS_DIR" != "$EXPECT_BEADS_DIR" ]]; then
echo "BEADS_DIR mismatch" >&2
exit 1
fi
id=""
title=""
for arg in "$@"; do
case "$arg" in
--id=*) id="${arg#--id=}" ;;
--title=*) title="${arg#--title=}" ;;
esac
done
printf '{"id":"%s","title":"%s","description":"","issue_type":"agent"}' "$id" "$title"
;;
slot)
if [[ "$BEADS_DIR" != "$EXPECT_BEADS_DIR" ]]; then
echo "BEADS_DIR mismatch" >&2
exit 1
fi
;;
*)
echo "unexpected command: $cmd" >&2
exit 1
;;
esac
`
binDir := writeFakeBD(t, script)
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("EXPECT_BEADS_DIR", beadsDir)
t.Setenv("BEADS_DIR", "")
manager := &Manager{}
if err := manager.initAgentBeads(rigPath, "demo", "gt", false); err != nil {
t.Fatalf("initAgentBeads: %v", err)
}
}