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:
@@ -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>`")
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user