fix(beads): fix agent bead creation during rig add
Three issues were causing errors when running `gt rig add`: 1. **bd init flag**: Removed non-existent `--no-agents` flag from bd init command that was causing silent failures. 2. **BEADS_DIR for init**: Added explicit BEADS_DIR to bd init and migrate commands to prevent bd from finding parent directory databases. 3. **Agent beads location**: Agent beads now go in town beads (gt-* prefix) instead of rig beads. This is necessary because: - Agent IDs use canonical gt-* prefix (e.g., gt-tribal-witness) - Rig beads use rig-specific prefixes (e.g., tr-*) - bd strictly validates ID prefix against database prefix - Town beads must be initialized with `gt` prefix 4. **beads.run() BEADS_DIR**: Modified to explicitly pass BEADS_DIR in child process environment to ensure bd uses the correct database. 5. **Agent ID prefix**: Use WitnessBeadID/RefineryBeadID (canonical gt-*) instead of WithPrefix variants. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -225,6 +225,21 @@ func (b *Beads) run(args ...string) ([]byte, error) {
|
||||
cmd := exec.Command("bd", fullArgs...)
|
||||
cmd.Dir = b.workDir
|
||||
|
||||
// Explicitly set BEADS_DIR for child process to ensure bd uses the correct
|
||||
// database. Without this, bd may search parent directories and find a different
|
||||
// .beads/ directory with a different prefix, causing "prefix mismatch" errors.
|
||||
beadsDir := filepath.Join(b.workDir, ".beads")
|
||||
env := os.Environ()
|
||||
// Filter out any existing BEADS_DIR to avoid conflicts
|
||||
filteredEnv := make([]string, 0, len(env)+1)
|
||||
for _, e := range env {
|
||||
if !strings.HasPrefix(e, "BEADS_DIR=") {
|
||||
filteredEnv = append(filteredEnv, e)
|
||||
}
|
||||
}
|
||||
filteredEnv = append(filteredEnv, "BEADS_DIR="+beadsDir)
|
||||
cmd.Env = filteredEnv
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
@@ -422,9 +422,21 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Run bd init if available, with --no-agents to skip AGENTS.md creation
|
||||
cmd := exec.Command("bd", "init", "--prefix", prefix, "--no-agents")
|
||||
// Build environment with explicit BEADS_DIR to prevent bd from
|
||||
// finding a parent directory's .beads/ database
|
||||
env := os.Environ()
|
||||
filteredEnv := make([]string, 0, len(env)+1)
|
||||
for _, e := range env {
|
||||
if !strings.HasPrefix(e, "BEADS_DIR=") {
|
||||
filteredEnv = append(filteredEnv, e)
|
||||
}
|
||||
}
|
||||
filteredEnv = append(filteredEnv, "BEADS_DIR="+beadsDir)
|
||||
|
||||
// Run bd init if available
|
||||
cmd := exec.Command("bd", "init", "--prefix", prefix)
|
||||
cmd.Dir = rigPath
|
||||
cmd.Env = filteredEnv
|
||||
_, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
// bd might not be installed or failed, create minimal structure
|
||||
@@ -441,6 +453,7 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
|
||||
// Without fingerprint, the bd daemon fails to start silently.
|
||||
migrateCmd := exec.Command("bd", "migrate", "--update-repo-id")
|
||||
migrateCmd.Dir = rigPath
|
||||
migrateCmd.Env = filteredEnv
|
||||
// Ignore errors - fingerprint is optional for functionality
|
||||
_, _ = migrateCmd.CombinedOutput()
|
||||
|
||||
@@ -448,26 +461,18 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
|
||||
}
|
||||
|
||||
// initAgentBeads creates agent beads for this rig and optionally global agents.
|
||||
// - Always creates: <prefix>-witness-<rig>, <prefix>-refinery-<rig>
|
||||
// - First rig only: <prefix>-deacon, <prefix>-mayor
|
||||
// - Always creates: gt-<rig>-witness, gt-<rig>-refinery
|
||||
// - First rig only: gt-deacon, gt-mayor
|
||||
//
|
||||
// Agent beads are stored in the TOWN beads (not rig beads) because they use
|
||||
// the canonical gt-* prefix for cross-rig coordination. The town beads must
|
||||
// be initialized with 'gt' prefix for this to work.
|
||||
//
|
||||
// Agent beads track lifecycle state for ZFC compliance (gt-h3hak, gt-pinkq).
|
||||
func (m *Manager) initAgentBeads(rigPath, rigName, prefix string, isFirstRig bool) error {
|
||||
// Run bd commands from rig root where .beads/ was initialized
|
||||
// Set BEADS_DIR explicitly to ensure bd finds the database
|
||||
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(rigPath)
|
||||
// Agent beads go in town beads (gt-* prefix), not rig beads
|
||||
// This enables cross-rig agent coordination via canonical IDs
|
||||
bd := beads.New(m.townRoot)
|
||||
|
||||
// Define agents to create
|
||||
type agentDef struct {
|
||||
@@ -479,16 +484,18 @@ func (m *Manager) initAgentBeads(rigPath, rigName, prefix string, isFirstRig boo
|
||||
|
||||
var agents []agentDef
|
||||
|
||||
// Always create rig-specific agents (using canonical naming: prefix-rig-role-name)
|
||||
// Always create rig-specific agents using canonical gt- prefix.
|
||||
// Agent bead IDs use the gastown namespace (gt-) regardless of the rig's
|
||||
// beads prefix. Format: gt-<rig>-<role> (e.g., gt-tribal-witness)
|
||||
agents = append(agents,
|
||||
agentDef{
|
||||
id: beads.WitnessBeadIDWithPrefix(prefix, rigName),
|
||||
id: beads.WitnessBeadID(rigName),
|
||||
roleType: "witness",
|
||||
rig: rigName,
|
||||
desc: fmt.Sprintf("Witness for %s - monitors polecat health and progress.", rigName),
|
||||
},
|
||||
agentDef{
|
||||
id: beads.RefineryBeadIDWithPrefix(prefix, rigName),
|
||||
id: beads.RefineryBeadID(rigName),
|
||||
roleType: "refinery",
|
||||
rig: rigName,
|
||||
desc: fmt.Sprintf("Refinery for %s - processes merge queue.", rigName),
|
||||
|
||||
Reference in New Issue
Block a user