fix: Deacon propulsion - use town beads via redirect

The Deacon propulsion was broken because:
1. outputDeaconPatrolContext() created patrols in gastown/mayor/rig/.beads
2. checkSlungWork() looked in ~/gt/deacon/.beads/ (empty)
3. These were different locations - pinned work never found

Fix:
- Created redirect: ~/gt/deacon/.beads/redirect -> ../.beads (town beads)
- Changed outputDeaconPatrolContext() to use ctx.WorkDir instead of
  hardcoded gastown path
- Updated deacon template to remove hardcoded gastown references
- Updated wisp creation docs to use two-step pattern (create then pin)

Also cleaned up 14 stale patrol wisps that accumulated in rig beads
from repeated startup attempts.

Filed gt-0pdhj to track remaining hardcoded gastown dependencies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-26 18:23:25 -08:00
parent 0157857ee3
commit ff22c84cd6
2 changed files with 15 additions and 18 deletions

View File

@@ -803,14 +803,15 @@ func outputDeaconPatrolContext(ctx RoleContext) {
fmt.Println()
fmt.Printf("%s\n\n", style.Bold.Render("## 🔄 Patrol Status (Wisp-based)"))
// Check for active mol-deacon-patrol molecules in rig beads
// Check for active mol-deacon-patrol molecules in town beads
// A patrol is "active" if it has open wisp children (steps to execute)
// After squash, the root stays open but has no open children - that's "completed"
rigBeadsDir := filepath.Join(ctx.TownRoot, "gastown", "mayor", "rig")
// Deacon uses town beads (via redirect from ~/gt/deacon/.beads/ to ~/gt/.beads/)
beadsDir := ctx.WorkDir
// First find mol-deacon-patrol molecules (exclude template)
cmdList := exec.Command("bd", "list", "--status=open", "--type=epic")
cmdList.Dir = rigBeadsDir
cmdList.Dir = beadsDir
var stdoutList bytes.Buffer
cmdList.Stdout = &stdoutList
cmdList.Stderr = nil
@@ -830,7 +831,7 @@ func outputDeaconPatrolContext(ctx RoleContext) {
molID := parts[0]
// Check if this molecule has open children using bd show
cmdShow := exec.Command("bd", "show", molID)
cmdShow.Dir = rigBeadsDir
cmdShow.Dir = beadsDir
var stdoutShow bytes.Buffer
cmdShow.Stdout = &stdoutShow
cmdShow.Stderr = nil
@@ -856,7 +857,7 @@ func outputDeaconPatrolContext(ctx RoleContext) {
// Find the proto ID for mol-deacon-patrol
cmdCatalog := exec.Command("bd", "--no-daemon", "mol", "catalog")
cmdCatalog.Dir = rigBeadsDir
cmdCatalog.Dir = beadsDir
var stdoutCatalog bytes.Buffer
cmdCatalog.Stdout = &stdoutCatalog
cmdCatalog.Stderr = nil
@@ -887,7 +888,7 @@ func outputDeaconPatrolContext(ctx RoleContext) {
// Create the patrol wisp (step 1: create)
cmdSpawn := exec.Command("bd", "--no-daemon", "wisp", "create", protoID)
cmdSpawn.Dir = rigBeadsDir
cmdSpawn.Dir = beadsDir
var stdoutSpawn, stderrSpawn bytes.Buffer
cmdSpawn.Stdout = &stdoutSpawn
cmdSpawn.Stderr = &stderrSpawn
@@ -921,7 +922,7 @@ func outputDeaconPatrolContext(ctx RoleContext) {
// Pin the wisp to deacon (step 2: assign)
cmdPin := exec.Command("bd", "--no-daemon", "update", patrolID, "--status=pinned", "--assignee=deacon")
cmdPin.Dir = rigBeadsDir
cmdPin.Dir = beadsDir
if err := cmdPin.Run(); err != nil {
fmt.Printf("⚠ Created wisp %s but failed to pin to deacon\n", patrolID)
} else {
@@ -935,7 +936,6 @@ func outputDeaconPatrolContext(ctx RoleContext) {
// Show patrol work loop instructions
fmt.Println("**Deacon Patrol Work Loop:**")
fmt.Println("Run from gastown/mayor/rig/:")
fmt.Println("1. Check next step: `bd ready`")
fmt.Println("2. Execute the step (heartbeat, mail, health checks, etc.)")
fmt.Println("3. Close step: `bd close <step-id>`")

View File

@@ -13,13 +13,8 @@ handling lifecycle events.
**IMPORTANT**: Always work from `{{ .TownRoot }}/deacon/` directory.
Identity detection (for mail, mol status, etc.) depends on your current working
directory. If you need to run commands from another directory, return to
`{{ .TownRoot }}/deacon/` afterward.
```bash
# If you need to run bd commands from rig:
cd ~/gt/gastown/mayor/rig && bd list && cd ~/gt/deacon
```
directory. The deacon's beads redirect to town beads, so all `bd` commands work
from this directory.
## Architecture
@@ -62,8 +57,9 @@ gt mail inbox
# If mail contains attached_molecule, self-pin it:
gt mol attach-from-mail <mail-id>
# Step 3: Still nothing? Create patrol wisp
bd wisp mol-deacon-patrol --assignee=deacon
# Step 3: Still nothing? Create patrol wisp (two-step: create then pin)
bd wisp create mol-deacon-patrol
bd update <wisp-id> --status=pinned --assignee=deacon
```
**Hook has work → Run it. Hook empty → Check mail. Nothing anywhere → Create patrol.**
@@ -131,7 +127,8 @@ Then squash and decide:
bd mol squash <wisp-id> --summary="Patrol complete: checked inbox, scanned health, no issues"
# Option A: Loop (low context)
bd wisp mol-deacon-patrol --assignee=deacon
bd wisp create mol-deacon-patrol
bd update <wisp-id> --status=pinned --assignee=deacon
# Continue to first step...
# Option B: Exit (high context)