feat: gt doctor checks for branch hygiene
Add two new doctor checks: 1. persistent-role-branches: Detects crew/*, witness/rig, refinery/rig directories not on main branch. Persistent roles should work directly on main to avoid orphaned work. 2. beads-sync-orphans: Detects code changes on beads-sync branch that weren't merged to main, catching cases where merges lose code changes. Also adds ensureMainBranch() to crew attach to auto-switch persistent roles to main at session start. Closes gt-p9zh 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -482,6 +482,9 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("getting crew worker: %w", err)
|
||||
}
|
||||
|
||||
// Ensure crew workspace is on main branch (persistent roles should not use feature branches)
|
||||
ensureMainBranch(worker.ClonePath, fmt.Sprintf("Crew workspace %s/%s", r.Name, name))
|
||||
|
||||
// If --no-tmux, just print the path
|
||||
if crewNoTmux {
|
||||
fmt.Println(worker.ClonePath)
|
||||
@@ -1137,3 +1140,45 @@ func runCrewPristine(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureMainBranch checks if a git directory is on main branch.
|
||||
// If not, warns the user and offers to switch.
|
||||
// Returns true if on main (or switched to main), false if user declined.
|
||||
func ensureMainBranch(dir, roleName string) bool {
|
||||
g := git.NewGit(dir)
|
||||
|
||||
branch, err := g.CurrentBranch()
|
||||
if err != nil {
|
||||
// Not a git repo or other error, skip check
|
||||
return true
|
||||
}
|
||||
|
||||
if branch == "main" || branch == "master" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Warn about wrong branch
|
||||
fmt.Printf("\n%s %s is on branch '%s', not main\n",
|
||||
style.Warning.Render("⚠"),
|
||||
roleName,
|
||||
branch)
|
||||
fmt.Println(" Persistent roles should work on main to avoid orphaned work.")
|
||||
fmt.Println()
|
||||
|
||||
// Auto-switch to main
|
||||
fmt.Printf(" Switching to main...\n")
|
||||
if err := g.Checkout("main"); err != nil {
|
||||
fmt.Printf(" %s Could not switch to main: %v\n", style.Error.Render("✗"), err)
|
||||
fmt.Println(" Please manually run: git checkout main && git pull")
|
||||
return false
|
||||
}
|
||||
|
||||
// Pull latest
|
||||
if err := g.Pull("origin", "main"); err != nil {
|
||||
fmt.Printf(" %s Pull failed (continuing anyway): %v\n", style.Warning.Render("⚠"), err)
|
||||
} else {
|
||||
fmt.Printf(" %s Switched to main and pulled latest\n", style.Success.Render("✓"))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ func runDoctor(cmd *cobra.Command, args []string) error {
|
||||
d.Register(doctor.NewBeadsDatabaseCheck())
|
||||
d.Register(doctor.NewOrphanSessionCheck())
|
||||
d.Register(doctor.NewOrphanProcessCheck())
|
||||
d.Register(doctor.NewBranchCheck())
|
||||
d.Register(doctor.NewBeadsSyncOrphanCheck())
|
||||
|
||||
// Run checks
|
||||
var report *doctor.Report
|
||||
|
||||
Reference in New Issue
Block a user