feat(doctor): add safeguards for town root branch protection

Add three layers of protection to prevent accidental branch switches in
the town root (~/gt), which should always stay on main:

1. Doctor check `town-root-branch`: Verifies town root is on main/master.
   Fixable via `gt doctor --fix` to switch back to main.

2. Doctor check `pre-checkout-hook`: Verifies git pre-checkout hook is
   installed. The hook blocks checkout from main to any other branch.
   Fixable via `gt doctor --fix` or `gt git-init`.

3. Runtime warning in all gt commands: Non-blocking warning if town root
   is on wrong branch, with fix instructions.

The root cause of this issue was git commands running in the wrong
directory, switching the town root to a polecat branch. This broke gt
commands because rigs.json and other configs were on main, not the
polecat branch.

Closes: hq-1kwuj

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
slit
2026-01-09 13:16:37 -08:00
committed by beads/crew/giles
parent 692d6819f2
commit ba76bf1232
5 changed files with 460 additions and 1 deletions
+7
View File
@@ -32,6 +32,11 @@ Workspace checks:
- rigs-registry-valid Check registered rigs exist (fixable)
- mayor-exists Check mayor/ directory structure
Town root protection:
- town-git Verify town root is under version control
- town-root-branch Verify town root is on main branch (fixable)
- pre-checkout-hook Verify pre-checkout hook prevents branch switches (fixable)
Infrastructure checks:
- daemon Check if daemon is running (fixable)
- repo-fingerprint Check database has valid repo fingerprint (fixable)
@@ -112,6 +117,8 @@ func runDoctor(cmd *cobra.Command, args []string) error {
// Register built-in checks
d.Register(doctor.NewTownGitCheck())
d.Register(doctor.NewTownRootBranchCheck())
d.Register(doctor.NewPreCheckoutHookCheck())
d.Register(doctor.NewDaemonCheck())
d.Register(doctor.NewRepoFingerprintCheck())
d.Register(doctor.NewBootHealthCheck())