📋 Work Assignment: Add bd doctor --fix flag to automatically repair issues

Issue: bd-ykd9
Title: Add bd doctor --fix flag to automatically repair issues
Priority: P2
Type: feature

Description:
Add bd doctor --fix flag to automatically repair detected issues.

## Current State
- Doctor checks return issues with "Fix" field containing fix instructions
- No automatic fix execution
- User must manually follow fix instructions

## Implementation

### 1. Add --fix flag to doctor.go
```go
// In cmd/bd/doctor.go init()
doctorCmd.Flags().Bool("fix", false, "Automatically fix detected issues")
doctorCmd.Flags().Bool("yes", false, "Skip confirmation prompts (use with --fix)")
```

### 2. Create fix registry (cmd/bd/doctor/fix/registry.go)
```go
package fix

// Fixer can automatically repair an issue
type Fixer interface {
    // CanFix returns true if this fixer handles the given check name
    CanFix(checkName string) bool
    // Fix attempts to repair the issue, returns error if failed
    Fix(ctx context.Context, issue *CheckResult) error
    // Description returns human-readable description of what will be fixed
    Description() string
}

var registry []Fixer

func Register(f Fixer) {
    registry = append(registry, f)
}

func GetFixer(checkName string) Fixer {
    for _, f := range registry {
        if f.CanFix(checkName) {
            return f
        }
    }
    return nil
}
```

### 3. Implement fixers (one per file)

**cmd/bd/doctor/fix/hooks.go**
```go
type HooksFixer struct{}

func (f *HooksFixer) CanFix(name string) bool {
    return name == "git-hooks" || name == "hooks-outdated"
}

func (f *HooksFixer) Fix(ctx context.Context, issue *CheckResult) error {
    return hooks.Install(".", true) // force reinstall
}

func (f *HooksFixer) Description() string {
    return "Reinstall git hooks"
}

func init() {
    Register(&HooksFixer{})
}
```

**cmd/bd/doctor/fix/sync_branch.go**
```go
type SyncBranchFixer struct{}

func (f *SyncBranchFixer) CanFix(name string) bool {
    return name == "sync-branch-missing" || name == "sync-branch-diverged"
}

func (f *SyncBranchFixer) Fix(ctx context.Context, issue *CheckResult) error {
    // Reset to remote or create branch
    return syncbranch.ResetToRemote(ctx, repoRoot, branch, jsonlPath)
}
```

**cmd/bd/doctor/fix/merge_driver.go**
```go
type MergeDriverFixer struct{}

func (f *MergeDriverFixer) CanFix(name string) bool {
    return name == "merge-driver-missing" || name == "merge-driver-outdated"
}

func (f *MergeDriverFixer) Fix(ctx context.Context, issue *CheckResult) error {
    return setupMergeDriver()
}
```

### 4. Update doctor run logic

```go
func runDoctor(cmd *cobra.Command, args []string) {
    issues := runAllChecks()

    if \!fixFlag {
        // Existing behavior - just display issues
        displayIssues(issues)
        return
    }

    // Collect fixable issues
    var fixable []FixableIssue
    for _, issue := range issues {
        if fixer := fix.GetFixer(issue.CheckName); fixer \!= nil {
            fixable = append(fixable, FixableIssue{issue, fixer})
        }
    }

    if len(fixable) == 0 {
        fmt.Println("No automatically fixable issues found")
        return
    }

    // Show what will be fixed
    fmt.Printf("Found %d fixable issues:\n", len(fixable))
    for i, f := range fixable {
        fmt.Printf("  %d. [%s] %s\n", i+1, f.Issue.CheckName, f.Fixer.Description())
    }

    // Confirm unless --yes
    if \!yesFlag {
        fmt.Print("\nProceed with fixes? [Y/n] ")
        // ... read confirmation
    }

    // Apply fixes
    for _, f := range fixable {
        fmt.Printf("Fixing %s... ", f.Issue.CheckName)
        if err := f.Fixer.Fix(ctx, f.Issue); err \!= nil {
            fmt.Printf("FAILED: %v\n", err)
        } else {
            fmt.Println("OK")
        }
    }
}
```

## Fixable Checks (Initial Set)

| Check | Fixer | Action |
|-------|-------|--------|
| git-hooks | HooksFixer | Reinstall hooks |
| hooks-outdated | HooksFixer | Update hooks |
| merge-driver-missing | MergeDriverFixer | Configure merge driver |
| sync-branch-diverged | SyncBranchFixer | Reset to remote |
| daemon-version-mismatch | DaemonFixer | Restart daemon |

## Testing
```bash
# Test with broken hooks
rm .git/hooks/pre-commit
bd doctor --fix --yes

# Verify fix applied
bd doctor  # Should pass now
```

## Success Criteria
- --fix flag triggers automatic repair
- User prompted for confirmation (unless --yes)
- Clear output showing what was fixed
- Graceful handling of fix failures
- At least 5 common issues auto-fixable

## Workflow
1. Run `gt prime` to load polecat context
2. Work on your task, commit changes regularly
3. Run `bd close <issue-id>` when done
4. Run `bd sync` to push beads changes
5. Push code: `git push origin HEAD`
6. Run `gt done` to signal completion

## Handoff Protocol
Before signaling done, ensure:
- Git status is clean (no uncommitted changes)
- Issue is closed with `bd close`
- Beads are synced with `bd sync`
- Code is pushed to origin

The `gt done` command verifies these and signals the Witness.


Digest: mol-deacon-patrol

Patrol cycle 3: All agents healthy, routine check


Digest: mol-deacon-patrol

Patrol #4: routine, all healthy


Digest: mol-deacon-patrol

Patrol 8: all nominal


Digest: mol-deacon-patrol

Patrol 1 complete: all agents healthy (gastown/wyvern), no callbacks, no pending gates, no orphans


Digest: mol-deacon-patrol

Patrol 1: All healthy (beads/gastown witness+refinery running). Deleted handoff mail. No convoys, gates, orphans, or abandoned work.


Digest: mol-deacon-patrol

Patrol cycle 6: All quiet


Digest: mol-deacon-patrol

Patrol cycle 14: healthy


Digest: mol-deacon-patrol

Patrol 9: Routine.


POLECAT_STARTED beads/mike

Issue: bd-0fvq
Session: gt-beads-mike


Digest: mol-deacon-patrol

Patrol #26: All healthy. Emma active 2h15m.


Digest: mol-deacon-patrol

Patrol 18: No callbacks, all healthy


Digest: mol-deacon-patrol

Patrol 20: final check - all healthy, MQ beads:8 gastown:13


Digest: mol-deacon-patrol

Patrol 10: Halfway point, all systems nominal


Digest: mol-deacon-patrol

Patrol 14: Town idle


Digest: mol-deacon-patrol

Patrol 3: All healthy.


Digest: mol-deacon-patrol

Patrol cycle 20: All healthy (3W/3R), gastown monitoring 2 polecats, routine handoff


Handoff mail not delivered to mayor inbox

Town log shows predecessor handed off at 12:59:33 with message about gt-7psb8, but gt mail inbox shows 0 messages. The handoff context was lost.

Reproduction:
1. Mayor runs gt handoff with -s 'context'
2. New mayor session starts
3. gt mail inbox shows empty

Expected: Handoff mail in inbox


POLECAT_STARTED golf

Issue: bd-de6
Session: gt-beads-golf


🤝 HANDOFF: GH#692 epic - continue with remaining tasks

## Context

Completed bd-u2sc.2 (sort.Slice → slices.SortFunc migration). Pushed to main.

## Work Completed

- **bd-u2sc.2** [CLOSED] - Migrated 19 instances of sort.Slice to slices.SortFunc
  - 16 files in cmd/bd/ updated
  - All tests pass
  - Commit: e67712dc

## Remaining Epic Work (bd-u2sc)

Check `bd show bd-u2sc` for full epic. Recommended order:

1. **bd-u2sc.1** [P2] - Replace map[string]interface{} with typed JSON response structs
   - ~20 instances in compact.go, cleanup.go, daemons.go, daemon_lifecycle.go
   - Good next step - improves type safety

2. **bd-u2sc.3** [P3] - Split large cmd/bd files into logical modules
   - sync.go (2201 lines), init.go (1742), show.go (1380)
   - Larger refactor

3. **bd-u2sc.4** [P3] - Introduce slog for structured daemon logging

4. **bd-bqcc** [P2] - Consolidate maintenance commands into `bd doctor --fix`

## Commands

```bash
bd show bd-u2sc           # View epic
bd update bd-u2sc.1 --status in_progress  # Claim next task
```


Digest: mol-deacon-patrol

Patrol 11: All healthy, no inbox


Digest: mol-deacon-patrol

Patrol cycle 5: All healthy, queues unchanged (beads 8, gastown 12, wyvern 0)


Digest: mol-deacon-patrol

Patrol 1: All agents healthy. 2 convoys in progress (PR #970 review, nudge docs). No incidents.


Digest: mol-deacon-patrol

Patrol 7: All healthy, refinery queue 13


ZFC violation: Branch pattern matching in doctor checks

Multiple files use branch name pattern matching to infer state:

1. **doctor/branch_check.go** (lines 31-87): Checks if persistent roles are on main branch
2. **doctor/rig_check.go** (line 745): `strings.HasPrefix(branch, "polecat/")`
3. **cmd/mq_integration.go** (lines 35, 88-98): Branch prefix matching for logic

Example:
```go
if strings.HasPrefix(branch, "polecat/") {
    // ... logic based on branch pattern
}
```

This is Go inferring state from branch name signals rather than reading agent-declared state from beads.

Replaced hardcoded 'polecat/' strings with constants.BranchPolecatPrefix for consistency. Full ZFC fix (declaring identity in beads) would require larger architectural changes.


Digest: mol-deacon-patrol

Patrol 169: All healthy, gastown/furiosa polecat working


📋 Work Assignment: gt done: Notify Witness with exit outcome

Issue: gt-jzot
Title: gt done: Notify Witness with exit outcome
Priority: P1
Type: task

Description:
When polecat runs gt done, it should send mail to Witness:

```
gt mail send <rig>/witness -s 'POLECAT_DONE <name>' -m 'Exit: COMPLETED
Issue: <issue-id>
MR: <mr-id>
Branch: <branch>'
```

Exit types:
- COMPLETED: Work done, MR submitted
- ESCALATED: Hit blocker, needs human
- DEFERRED: Work paused, issue still open

This enables Witness patrol to:
1. See completion in inbox-check step
2. Verify git state is clean
3. Kill session and prune worktree
4. Close the polecat lease in its patrol wisp

Paired with gt-r6td (spawn notification) - together they bracket polecat lifecycle.

## Workflow
1. Run `gt prime` to load polecat context
2. Work on your task, commit changes regularly
3. Run `bd close <issue-id>` when done
4. Run `bd sync` to push beads changes
5. Push code: `git push origin HEAD`
6. Run `gt done` to signal completion

## Handoff Protocol
Before signaling done, ensure:
- Git status is clean (no uncommitted changes)
- Issue is closed with `bd close`
- Beads are synced with `bd sync`
- Code is pushed to origin

The `gt done` command verifies these and signals the Witness.


Digest: mol-deacon-patrol

Patrol 4: routine, all clear


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff cycle