fix: auto-configure sync-branch for rig beads
New rigs now get sync-branch: beads-sync in their .beads/config.yaml automatically. This enables multi-clone coordination for polecats, crew members, and refinery. Also added gt doctor check (beads-sync-branch) to verify existing rigs have sync-branch configured, with --fix support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,7 @@ func runDoctor(cmd *cobra.Command, args []string) error {
|
|||||||
// Register built-in checks
|
// Register built-in checks
|
||||||
d.Register(doctor.NewDaemonCheck())
|
d.Register(doctor.NewDaemonCheck())
|
||||||
d.Register(doctor.NewBeadsDatabaseCheck())
|
d.Register(doctor.NewBeadsDatabaseCheck())
|
||||||
|
d.Register(doctor.NewBeadsSyncBranchCheck())
|
||||||
|
|
||||||
// Run checks
|
// Run checks
|
||||||
var report *doctor.Report
|
var report *doctor.Report
|
||||||
|
|||||||
110
internal/doctor/beads_sync_check.go
Normal file
110
internal/doctor/beads_sync_check.go
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
package doctor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BeadsSyncBranchCheck verifies that rig-level beads have sync-branch configured.
|
||||||
|
// Rig beads need sync-branch for multi-clone coordination (polecats, crew, etc.)
|
||||||
|
// Town-level beads should NOT have sync-branch (single clone, commits to main).
|
||||||
|
type BeadsSyncBranchCheck struct {
|
||||||
|
FixableCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBeadsSyncBranchCheck creates a new sync-branch configuration check.
|
||||||
|
func NewBeadsSyncBranchCheck() *BeadsSyncBranchCheck {
|
||||||
|
return &BeadsSyncBranchCheck{
|
||||||
|
FixableCheck: FixableCheck{
|
||||||
|
BaseCheck: BaseCheck{
|
||||||
|
CheckName: "beads-sync-branch",
|
||||||
|
CheckDescription: "Verify rig beads have sync-branch configured",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run checks if rig-level beads have sync-branch properly configured.
|
||||||
|
func (c *BeadsSyncBranchCheck) Run(ctx *CheckContext) *CheckResult {
|
||||||
|
// Only check if a rig is specified
|
||||||
|
if ctx.RigName == "" {
|
||||||
|
return &CheckResult{
|
||||||
|
Name: c.Name(),
|
||||||
|
Status: StatusOK,
|
||||||
|
Message: "No rig specified, skipping rig beads sync-branch check",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check rig-level beads config
|
||||||
|
rigBeadsDir := filepath.Join(ctx.RigPath(), ".beads")
|
||||||
|
configPath := filepath.Join(rigBeadsDir, "config.yaml")
|
||||||
|
|
||||||
|
content, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return &CheckResult{
|
||||||
|
Name: c.Name(),
|
||||||
|
Status: StatusWarning,
|
||||||
|
Message: "No .beads/config.yaml in rig",
|
||||||
|
FixHint: "Run 'bd init' in the rig directory",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &CheckResult{
|
||||||
|
Name: c.Name(),
|
||||||
|
Status: StatusError,
|
||||||
|
Message: "Could not read .beads/config.yaml: " + err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for sync-branch setting
|
||||||
|
if !strings.Contains(string(content), "sync-branch:") {
|
||||||
|
return &CheckResult{
|
||||||
|
Name: c.Name(),
|
||||||
|
Status: StatusWarning,
|
||||||
|
Message: "Rig beads missing sync-branch configuration",
|
||||||
|
Details: []string{
|
||||||
|
"Rig: " + ctx.RigName,
|
||||||
|
"Rig beads need sync-branch for multi-clone coordination",
|
||||||
|
"Without this, polecats and crew members can't share beads",
|
||||||
|
},
|
||||||
|
FixHint: "Run 'gt doctor --fix' or add 'sync-branch: beads-sync' to .beads/config.yaml",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CheckResult{
|
||||||
|
Name: c.Name(),
|
||||||
|
Status: StatusOK,
|
||||||
|
Message: "Rig beads sync-branch is configured",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix adds sync-branch to the rig beads config.
|
||||||
|
func (c *BeadsSyncBranchCheck) Fix(ctx *CheckContext) error {
|
||||||
|
if ctx.RigName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rigBeadsDir := filepath.Join(ctx.RigPath(), ".beads")
|
||||||
|
configPath := filepath.Join(rigBeadsDir, "config.yaml")
|
||||||
|
|
||||||
|
content, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if already configured
|
||||||
|
if strings.Contains(string(content), "sync-branch:") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append sync-branch setting
|
||||||
|
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = f.WriteString("sync-branch: beads-sync\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -329,6 +329,7 @@ func (m *Manager) initAgentStates(rigPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initBeads initializes the beads database at rig level.
|
// initBeads initializes the beads database at rig level.
|
||||||
|
// Rig beads use sync-branch for multi-clone coordination (polecats, crew, etc.)
|
||||||
func (m *Manager) initBeads(rigPath, prefix string) error {
|
func (m *Manager) initBeads(rigPath, prefix string) error {
|
||||||
beadsDir := filepath.Join(rigPath, ".beads")
|
beadsDir := filepath.Join(rigPath, ".beads")
|
||||||
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
||||||
@@ -341,10 +342,20 @@ func (m *Manager) initBeads(rigPath, prefix string) error {
|
|||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
// bd might not be installed or --no-agents not supported, create minimal structure
|
// bd might not be installed or --no-agents not supported, create minimal structure
|
||||||
configPath := filepath.Join(beadsDir, "config.yaml")
|
configPath := filepath.Join(beadsDir, "config.yaml")
|
||||||
configContent := fmt.Sprintf("prefix: %s\n", prefix)
|
// Rig beads need sync-branch for multi-clone coordination
|
||||||
|
configContent := fmt.Sprintf("prefix: %s\nsync-branch: beads-sync\n", prefix)
|
||||||
if writeErr := os.WriteFile(configPath, []byte(configContent), 0644); writeErr != nil {
|
if writeErr := os.WriteFile(configPath, []byte(configContent), 0644); writeErr != nil {
|
||||||
return writeErr
|
return writeErr
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// bd init succeeded, but we still need to add sync-branch
|
||||||
|
// Append to config.yaml (bd init doesn't set sync-branch by default)
|
||||||
|
configPath := filepath.Join(beadsDir, "config.yaml")
|
||||||
|
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err == nil {
|
||||||
|
defer f.Close()
|
||||||
|
f.WriteString("sync-branch: beads-sync\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user