Swarm cleanup: delete merged polecat branches and reset state

After a swarm completes and branches are merged, leftover state remains:

## Current Problem

1. **Remote branches not deleted** - polecat/* branches stay on origin after merge
2. **Polecat clones not reset** - still on old branch with completed work
3. **No cleanup command** - manual cleanup required

## Observed After Swarm

Remote branches still present:
- origin/polecat/Morsov
- origin/polecat/Nux
- origin/polecat/Rictus
- origin/polecat/Slit
- origin/polecat/Toast

## Proposed Solution

Add cleanup commands:

1. gt swarm cleanup <swarm-id> - Clean up after swarm completion
   - Delete remote polecat branches that were merged
   - Reset polecat clones to main
   - Clear issue assignments

2. gt polecat reset <rig>/<polecat> - Reset single polecat
   - git checkout main && git pull
   - Delete local polecat branch
   - Clear current issue assignment

3. Auto-cleanup option on gt session stop --cleanup

## Manual Cleanup For Now

git push origin --delete polecat/Nux polecat/Toast ...
cd polecats/Nux && git checkout main && git pull


Digest: mol-deacon-patrol

Patrol 3: Quiet, all agents healthy


Digest: mol-deacon-patrol

Patrol 4: All healthy, no messages


Digest: mol-deacon-patrol

Patrol 19: 3 rigs healthy


gt convoy merge: Consolidate multiple convoys into one

When work gets slung individually (e.g., due to gt swarm being broken), each issue gets its own convoy via auto-convoy. Need ability to merge these into a single tracking unit.

## Use Case

```bash
# Current state: 5 convoys for one logical swarm
gt convoy list
  1. hq-cv-6svfs: Work: gt mail reply
  2. hq-cv-2zdme: Work: gt mail search
  3. hq-cv-k3v6u: Work: gt mail archive/purge
  4. hq-cv-pc2ww: Work: gt mail mark/delete
  5. hq-cv-xdf66: Work: gt mail check

# Desired: merge into one
gt convoy merge hq-cv-xdf66 hq-cv-pc2ww hq-cv-k3v6u hq-cv-2zdme hq-cv-6svfs --title "Mail CLI Implementation"
# Result: single convoy tracking all 5 issues
```

## Implementation

- Take target convoy (first arg) or create new one
- Move tracked issues from source convoys to target
- Close/delete source convoys
- Update subscribers

## Alternative

Could also support:
```bash
gt convoy add hq-cv-xdf66 gt-d46.2 gt-d46.3 gt-d46.4 gt-d46.5
# Then manually close the orphaned convoys
```

But merge is cleaner UX.


Digest: mol-refinery-patrol

Patrol: merged 5 branches, closed 1 already-merged (dementus). No issues.


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.

## Idle Town Principle

**The Deacon should be silent/invisible when the town is healthy and idle.**

- Skip HEALTH_CHECK nudges when no active work exists
- Sleep 60+ seconds between patrol cycles (longer when idle)
- Let the feed subscription wake agents on actual events
- The daemon (10-minute heartbeat) is the safety net for dead sessions

This prevents flooding idle agents with health checks every few seconds.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Move disk 5: C → A

Move disk 5 from peg C to peg A. (Move 464/1023)


Execute registered plugins

Execute registered plugins.

Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with TOML frontmatter defining its gate (when to run) and instructions (what to do).

See docs/deacon-plugins.md for full documentation.

Gate types:
- cooldown: Time since last run (e.g., 24h)
- cron: Schedule-based (e.g., "0 9 * * *")
- condition: Metric threshold (e.g., wisp count > 50)
- event: Trigger-based (e.g., startup, heartbeat)

For each plugin:
1. Read plugin.md frontmatter to check gate
2. Compare against state.json (last run, etc.)
3. If gate is open, execute the plugin

Plugins marked parallel: true can run concurrently using Task tool subagents. Sequential plugins run one at a time in directory order.

Skip this step if ~/gt/plugins/ does not exist or is empty.


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 167/1023)


Digest: mol-deacon-patrol

Patrol 15: routine


Digest: mol-deacon-patrol

Patrol 9: healthy


Digest: mol-deacon-patrol

Patrol 88: All healthy


Refinery Patrol

Merge queue processor patrol loop with verification gates.


Digest: mol-deacon-patrol

Patrol cycle 15


Digest: mol-deacon-patrol

Patrol 13: All agents healthy


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 87/1023)


Resolve external dependencies

Resolve external dependencies across rigs.

When an issue in one rig closes, any dependencies in other rigs should be notified. This enables cross-rig coordination without tight coupling.

**Step 1: Check recent closures from feed**
```bash
gt feed --since 10m --plain | grep "✓"
# Look for recently closed issues
```

**Step 2: For each closed issue, check cross-rig dependents**
```bash
bd show <closed-issue>
# Look at 'blocks' field - these are issues that were waiting on this one
# If any blocked issue is in a different rig/prefix, it may now be unblocked
```

**Step 3: Update blocked status**
For blocked issues in other rigs, the closure should automatically unblock them (beads handles this). But verify:
```bash
bd blocked
# Should no longer show the previously-blocked issue if dependency is met
```

**Cross-rig scenarios:**
- bd-xxx closes → gt-yyy that depended on it is unblocked
- External issue closes → internal convoy step can proceed
- Rig A issue closes → Rig B issue waiting on it proceeds

No manual intervention needed if dependencies are properly tracked - this step just validates the propagation occurred.


Simplify Go daemon to Deacon-watcher

Refactor internal/daemon to only: (1) check deacon/heartbeat.json every 60s, (2) poke gt-deacon if stale, (3) restart Deacon and mail for help if very stale. Remove all lifecycle processing and agent poking.


Digest: mol-deacon-patrol

Patrol 16: quick pass


polecat nuke: Check if work is on main, not just 'pushed'

## Problem

After Refinery merges a branch and deletes it, the polecat's local branch shows 'unpushed commits' relative to the now-gone tracking branch. This blocks safe nuke even though the work IS on main.

## Current Behavior

```
$ gt polecat nuke gastown/dementus
Error: has 1 unpushed commit(s)
```

But the commit IS already on main (via squash merge).

## Proposed Fix

In nuke safety check (`internal/cmd/polecat.go` or similar):

1. Check if local HEAD commit content is on main (not just if pushed to tracking branch)
2. If commit SHA or equivalent changes are on main → safe to nuke
3. Only block if there's genuinely unpushed/unmerged work

## Implementation Options

A. Check if HEAD is ancestor of origin/main (commit-based)
B. Check if diff between HEAD and main is empty (content-based)
C. Both: fast ancestor check, fallback to diff check

Option A is faster but misses squash merges. Option B is slower but catches all cases.


rebase-main

Rebase against main to incorporate any changes.
Resolve conflicts if needed.

git fetch origin main
git rebase origin/main

If there are conflicts, resolve them carefully and continue the rebase.

Depends: self-review, verify-tests


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 693/1023)


Digest: mol-deacon-patrol

Patrol 14: Quiet


Merge: gt-3x0z.3

branch: polecat/slit
target: main
source_issue: gt-3x0z.3
rig: gastown


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 987/1023)


Session ended: gt-gastown-crew-gus


Agent Startup Consolidation: Unified nudge, seance metadata, LLM-agnostic

## Problem

Agent startup nudge logic is scattered across 6+ files with inconsistent behavior:
- start.go, crew_lifecycle.go, crew_at.go, handoff.go, deacon.go, witness.go

Some paths work (handoff), others fail (crew start). The core issues:

1. **tmux send-keys Enter issue**: `send-keys "foo" Enter` concatenates, doesnt send Enter separately
2. **All sessions look identical**: First message is "gt prime" everywhere, `/resume` shows duplicate-looking sessions
3. **No seance metadata**: Cant differentiate predecessors by sender, role, timestamp, topic
4. **Hardcoded to Claude**: `claude --dangerously-skip-permissions` everywhere

## Solution

1. **Unified StartupNudge function** - All paths call one function with rich metadata
2. **Seance-aware nudge format** - First message contains: sender, recipient, timestamp, topic
3. **Runtime configuration** - LLM command/args in config, not hardcoded
4. **gt seance command** - Find and resume predecessor sessions

## Nudge Format

The startup nudge becomes the session title in `/resume`:
```
[GAS TOWN] gastown/crew/gus ← mayor • 2025-12-30T15:42 • cold-start
```

Components:
- Address: gastown/crew/gus (recipient identity)
- Sender: mayor, deacon, witness, self (for handoff)
- Timestamp: When session started
- Topic: mol-id, "cold-start", "handoff", etc.

## Key Insight

The GUPP nudge content doesnt matter for triggering propulsion - agent already read CLAUDE.md and hooks ran. What matters is:
1. The nudge arrives reliably (NudgeSession solves this)
2. The nudge creates a unique, identifiable session title

## Related

- gt-p2o6s: Extend gt nudge to support channel:name syntax
- gt-9guv2: Messaging Channels epic
- Session beacon already exists but is for identity, not session title


Plugin/molecule catalog integration design

Two currently independent systems:
1. Disk-based plugins (~~/gt/plugins/) - Deacon patrol extensions
2. Molecule catalog (protos in beads) - bd pour/wisp/bond

Investigate integration points:
- User-contributed molecules bonded to catalog
- Dynamic molecule attachment during execution (e.g., 'attach security sniffer because we noticed condition X')
- How plugins could contribute protos
- How protos could trigger plugins

Not blocking launch. Future design investigation.


Digest: mol-deacon-patrol

Patrol complete: checked inbox (empty), scanned health (all witnesses/refineries running), no gates, no convoys, no orphans, 1 dog idle, no plugins


Digest: mol-deacon-patrol

P16: stable


Digest: mol-deacon-patrol

Patrol 142 complete: All agents healthy, no incidents


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


End-of-cycle inbox hygiene

Verify inbox hygiene before ending patrol cycle.

**Step 1: Check inbox state**
```bash
gt mail inbox
```

Inbox should be EMPTY or contain only just-arrived unprocessed messages.

**Step 2: Archive any remaining processed messages**

All message types should have been archived during inbox-check processing:
- WITNESS_PING → archived after acknowledging
- HELP/Escalation → archived after handling
- LIFECYCLE → archived after processing

If any were missed:
```bash
# For each stale message found:
gt mail archive <message-id>
```

**Goal**: Inbox should have ≤2 active messages at end of cycle.
Deacon mail should flow through quickly - no accumulation.


Digest: mol-deacon-patrol

Patrol 3: Routine


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 831/1023)


mol-deacon-patrol


Move disk 2: A → C

Move disk 2 from peg A to peg C. (Move 206/1023)


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 346/1023)


Update rig init to create refinery as worktree

Modify rig initialization to create refinery as a git worktree instead of a separate clone.

## Changes
- internal/rig/init.go or similar - change refinery setup
- Create worktree at <rig>/refinery/ with branch 'refinery'
- Remove clone logic for refinery
- Update any path assumptions

## Considerations
- Refinery worktree should track main (or its own branch?)
- May need to handle existing rigs (migration path)


BUG: Daemon doesn't kill zombie tmux sessions before recreating

## Problem

When the daemon detects an agent isn't running (per bead state), it tries to create a new session. But if a zombie tmux session exists (session alive, Claude dead), the create fails:

```
2026/01/02 18:18:20 Witness for gastown not running per agent bead, starting...
2026/01/02 18:18:20 Error creating witness session for gastown: session already exists
```

## Root Cause

`gt witness start` (and similar) fail if tmux session exists, even if it's a zombie. The daemon should:
1. Detect if existing session is responsive
2. Kill zombie if unresponsive
3. Create fresh session

## Current Behavior

```go
// In ensureWitnessRunning or similar:
if err := tmux.NewSession(sessionName, dir); err != nil {
    // Fails with 'session already exists'
    return err
}
```

## Expected Behavior

```go
// Pseudo-code for 'ensure running' semantics:
if sessionExists(name) {
    if !isResponsive(name) {
        killSession(name)  // Kill zombie
    } else {
        return  // Already running and healthy
    }
}
createSession(name)  // Create fresh
```

## Impact

- Dead witness/refinery stay dead indefinitely
- Daemon logs fill with 'session already exists' errors
- Town health degrades with no auto-recovery

## Solution

Add `ensureSessionFresh()` helper that:
1. Checks if session exists
2. If exists, checks if Claude is responsive (look for prompt, or check heartbeat)
3. Kills zombie sessions
4. Creates new session only if needed


Hook reading in gt prime

Enhance gt prime to check and display hook contents.

## Current Behavior

gt prime loads context:
- Reads CLAUDE.md
- Injects beads workflow info
- Shows status

## New Behavior

After loading context, check hook:

```go
// In prime.go
func checkHook(agent string) {
    wispPath := ".beads-wisp/hook-" + agent + ".wisp.yaml"
    if wisp := readWisp(wispPath); wisp != nil {
        // Inject hook info into prime output
        showSlungWork(wisp)
    }
}
```

## Output Format

When hook has slung work:

```markdown
## Your Hook

You have work assigned:

**Bead:** gt-xxx
**Title:** Fix authentication bug
**Priority:** P1

Context from previous session:
> Continue where I left off...

**BEGIN WORK NOW.** Claim it with:
  bd update gt-xxx --status=in_progress
```

## Files Modified

- cmd/gt/prime.go - Add hook checking
- internal/wisp/hook.go - Hook reading utilities


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 406/1023)


Move disk 8: A → C

Move disk 8 from peg A to peg C. (Move 128/1023)


Digest: mol-deacon-patrol

Patrol 5


Digest: mol-deacon-patrol

Patrol cycle 24: All healthy, no incidents


attached_args: Extract molecule_lifecycle boilerplate

Extract duplicate boilerplate in molecule_lifecycle.go.

## Files to modify
- internal/cmd/molecule_lifecycle.go

## Current duplication
runMoleculeBurn (lines 17-53) and runMoleculeSquash (lines 121-165) share ~50 lines of identical target detection code:
- Get cwd
- Find workspace
- Parse target argument
- Determine rig from address or role

## Implementation
Extract helper function:
```go
type AgentContext struct {
    TownRoot string
    RigName  string
    Role     string
    Target   string  // polecat name or crew name
}

func getTargetAgentContext(args []string) (*AgentContext, error) {
    cwd, err := os.Getwd()
    if err != nil {
        return nil, fmt.Errorf("getting current directory: %w", err)
    }
    townRoot, err := workspace.FindFromCwd()
    if err != nil {
        return nil, fmt.Errorf("finding workspace: %w", err)
    }
    if townRoot == "" {
        return nil, fmt.Errorf("not in a Gas Town workspace")
    }
    // ... rest of target detection logic ...
}
```

## Acceptance criteria
- [ ] AgentContext struct defined
- [ ] getTargetAgentContext function extracts shared logic
- [ ] runMoleculeBurn uses getTargetAgentContext
- [ ] runMoleculeSquash uses getTargetAgentContext
- [ ] Duplicate code eliminated (diff shows net negative lines)
- [ ] go build ./... passes
- [ ] go test ./internal/cmd/... passes


Digest: mol-deacon-patrol

Patrol 61: All agents healthy, 2 convoys in progress, 1 idle dog, no incidents


Move disk 4: B → A

Move disk 4 from peg B to peg A. (Move 40/1023)


Digest: mol-deacon-patrol

Patrol cycle 2: All agents healthy, 6 health pings sent


gt hook: Cannot resolve HQ beads from polecat context

## Problem
`gt hook hq-eggh5` fails from within a polecat clone:
```
Error: resolving ID hq-eggh5: operation failed: failed to resolve ID: no issue found matching "hq-eggh5"
```

## Context
- Ran from: ~/gt/gastown/polecats/furiosa
- Bead exists: `bd show hq-eggh5` works from town root
- Routes exist: ~/gt/.beads/routes.jsonl has hq- prefix mapped

## Expected
HQ beads (hq-* prefix) should be resolvable from anywhere in town via prefix-based routing.

## Actual
Polecat can only resolve beads with its own rig's prefix (gt-*).

## Impact
Cannot sling HQ-level issues to polecats - breaks cross-rig coordination.

## Workaround
Unknown - possibly need to copy/mirror the bead to rig-level beads first.


Digest: mol-deacon-patrol

Patrol 59: All healthy


gt-gastown-polecat-organic

gt-gastown-polecat-organic

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: null
role_bead: gt-polecat-role
cleanup_status: has_stash
active_mr: gt-scdyn
notification_level: null


mol-witness-patrol molecule definition

Create mol-witness-patrol in builtin_molecules.go.

## Steps (10 total)
1. inbox-check - Process witness mail (lifecycle, help requests)
2. load-state - Read handoff bead, get nudge counts
3. survey-workers - gt polecat list, categorize by status
4. inspect-workers - tmux capture-pane for each 'working' polecat
5. decide-actions - Apply nudge matrix, queue actions
6. execute-actions - Nudge, kill, or escalate as decided
7. save-state - Update handoff bead with new states
8. generate-summary - Summarize cycle for digest
9. context-check - Check own context usage
10. burn-or-loop - Squash wisp, then loop or cycle session

## Key Behaviors
- Uses wisp storage (.beads-wisp/)
- Reads/writes witness handoff bead for state persistence
- Progressive nudging (3 levels before escalate)
- Pre-kill verification before killing polecats

## Reference
- See prompts/roles/witness.md for protocol details
- See mol-refinery-patrol for similar structure
- Parent epic: gt-aqd8


Refinery background daemon mode

Refinery currently only works in foreground mode. Background daemon is stubbed.

## Current State
manager.go line 128-129:
```go
// Background mode: spawn a new process
// For MVP, we just mark as running - actual daemon implementation in gt-ov2
return nil
```

## Requirements

### 1. Background Process Spawning
```go
func (m *Manager) Start(foreground bool) error {
    if !foreground {
        // Spawn gt refinery start --foreground as subprocess
        cmd := exec.Command(os.Args[0], "refinery", "start", m.rig.Name, "--foreground")
        cmd.Start()  // Don't wait
        // Record PID
    }
}
```

### 2. PID File Management
- Write PID to .gastown/refinery.pid
- Check PID validity on status
- Clean up stale PID files

### 3. Log Output
- Redirect stdout/stderr to .gastown/refinery.log
- Log rotation (optional for MVP)

### 4. Graceful Shutdown
- Handle SIGTERM/SIGINT
- Complete current merge before exit
- Update state to stopped

### 5. Health Check
- Process existence check via kill -0
- Optional: heartbeat file with timestamp

## Files to Modify
- internal/refinery/manager.go: Start(), Status(), process spawning

## Acceptance Criteria
- [ ] gt refinery start <rig> spawns background process
- [ ] gt refinery status shows running with PID
- [ ] gt refinery stop sends SIGTERM and waits
- [ ] Logs written to .gastown/refinery.log
- [ ] Survives terminal close


Digest: mol-deacon-patrol

Patrol 6: Mayor OK, 11 sessions


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 181/1023)


Polecat didn't commit before gt done

Integration test gt-7psb8: Polecat furiosa ran gt done before committing changes.

The polecat:
1. Created a test file
2. Closed the bead with bd close --force
3. Ran bd sync
4. Ran gt done

But it NEVER ran:
- git add <file>
- git commit

Result: Branch pushed with no new commits. Refinery detected branch at same commit as main.

The polecat CLAUDE.md or session close protocol should enforce commit before gt done.


os.Exit() calls in library code prevent proper error handling

internal/cmd/mail.go and other files have os.Exit() calls.

Issues:
- Hard to test
- Prevents graceful shutdown
- Can lose unsaved state
- Doesn't compose well in library code

Should return errors instead of calling os.Exit() directly.
Let main() decide how to exit.


Crew startup missing metadata injection for gt seance

When crew members are started via 'gt crew start', they don't receive the metadata string that gt seance uses to identify running sessions. This makes it harder to track which crew sessions are active.

The metadata injection should happen during crew startup similar to how other agent types get their identifiers injected.


crew_add.go: Agent bead ID uses wrong format

In internal/cmd/crew_add.go:84, the agent bead ID is constructed as:

  crewID := fmt.Sprintf("gt-crew-%s-%s", rigName, name)

This produces 'gt-crew-gastown-joe' but existing beads and the session name format use:

  gt-<rig>-crew-<name>  (e.g., gt-gastown-crew-joe)

This causes agent beads to not be found/matched properly.

Fix: Change line 84 to:

  crewID := fmt.Sprintf("gt-%s-crew-%s", rigName, name)


Digest: mol-deacon-patrol

Patrol 13: all clear


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 497/1023)


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 57/1023)


Bug: LIFECYCLE messages use literal <rig> placeholder

Found stale LIFECYCLE messages addressed to @<rig>/witness instead of actual rig names like @gastown/witness. Template substitution not happening.

Examples found:
- gm-bay: LIFECYCLE: polecat requesting shutdown (to @<rig>/witness)
- gm-7du, gm-94e, gm-u5x, gm-89b: same issue

Fix: Ensure rig name is substituted in lifecycle mail templates.


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol cycle 33: All healthy, no incidents


Digest: mol-deacon-patrol

Patrol 15


Digest: mol-deacon-patrol

Patrol #7: Quick cycle, no pending spawns.


Digest: mol-deacon-patrol

Patrol cycle 18: All agents healthy


Digest: mol-deacon-patrol

Patrol cycle 43: All healthy, no incidents


Merge: gt-t9u7

branch: polecat/furiosa
target: main
source_issue: gt-t9u7
rig: gastown


mol-deacon-patrol

Mayor's daemon patrol loop.

The Deacon is the Mayor's background process that runs continuously, handling callbacks, monitoring rig health, and performing cleanup. Each patrol cycle runs these steps in sequence, then loops or exits.

## Second-Order Monitoring

Witnesses send WITNESS_PING messages to verify the Deacon is alive. This
prevents the "who watches the watchers" problem - if the Deacon dies,
Witnesses detect it and escalate to the Mayor.

The Deacon's agent bead last_activity timestamp is updated during each patrol
cycle. Witnesses check this timestamp to verify health.


Digest: mol-deacon-patrol

Patrol 20: final cycle complete, handoff time


Advice operators: before, after, around

Implement Lisp-style advice operators for molecules:
- before(target, step) - insert step before target
- after(target, step) - insert step after target
- around(target, wrapper) - wrap target with before/after

Support glob patterns for targeting (*.implement, shiny.*, etc).


Digest: mol-deacon-patrol

Patrol 1: All healthy, no lifecycle requests, 8 active sessions


Move disk 2: B → A

Move disk 2 from peg B to peg A. (Move 526/1023)


MVP Takeoff: Polecats just work

## Goal
Get to the point where we can sling any issue to a polecat with a formula and it "just works" end-to-end.

## Success Criteria
1. `gt daemon start` brings up the engine
2. Deacon patrols: inbox, health checks, cleanup
3. Witnesses patrol: monitor polecats, verify completion, cleanup
4. Refineries patrol: process merge queue
5. Polecat lifecycle: spawn → work → complete → cleanup
6. Shiny formula: design → implement → review → test → submit

## What This Enables
- "Engineer in a box" - take any issue, expand via shiny, get a reviewed/tested PR
- Reliable multi-agent coordination
- Self-healing infrastructure (patrols fix problems)

## Blocked By
- gt-ronyn (deacon murder bug) - FIXED
- Basic patrol formulas - DONE (mol-*-patrol.formula.toml exist)

## Children
See linked tasks below.


Digest: mol-deacon-patrol

Patrol 16: Quiet


Digest: mol-deacon-patrol

Patrol 18: routine


Digest: mol-deacon-patrol

Patrol 121: All agents healthy, 6 health pings sent, no callbacks, no orphans, 1 idle dog, inbox clean


README: Add beads (bd) as prerequisite

CRITICAL: gt calls bd via exec.Command for sling, cook, gate, etc. but beads is not listed in Prerequisites. Users following Quick Start will fail.

Fix:
1. Add 'beads (bd)' to Prerequisites with install link
2. Move Prerequisites section BEFORE Quick Start
3. Add version requirements for each dep


Digest: mol-deacon-patrol

Patrol cycle 16: nominal


Move disk 3: C → A

Move disk 3 from peg C to peg A. (Move 548/1023)


Clarify formula semantics: read-only reference, not instantiated

## Problem

An agent (likely the Deacon) read the `mol-deacon-patrol.formula.toml` file and created beads from its steps. This is wrong - formulas are reference documents describing a workflow, not templates to be instantiated into trackable work.

## What Happened

1. Formula exists at `.beads/formulas/mol-deacon-patrol.formula.toml`
2. Deacon (or predecessor agent) created an epic + 9 task beads matching the formula steps
3. These showed up in `bd ready` (separate bug filed)

## Correct Model

| Artifact | Purpose | Created How |
|----------|---------|-------------|
| Formula (.toml) | Reference doc describing workflow | Manual/design |
| Wisp | Ephemeral execution context | `bd wisp create` (no child beads) |
| Proto | Template for pour | `bd cook` from formula |

**Formulas should NOT create beads.** They're documentation. When the Deacon runs a patrol, it follows the formula instructions directly - it doesn't need beads for each step.

## Fix Needed

1. Update Deacon template to clarify: "Follow the formula instructions. Do not create beads from formula steps."
2. Audit what command created the beads - was it `bd wisp create` expanding the formula? If so, that command shouldn't create child beads.
3. Consider renaming formulas to `.md` if they're just prose instructions.

(Moved from hq-ufiy)