Wisp burn after pickup

Implement wisp cleanup after work is picked up.

## When to Burn

After agent has picked up slung work:
- Agent claims the issue (bd update --status=in_progress)
- Or agent explicitly acknowledges the handoff
- Wisp file is deleted

## Implementation Options

Option A: Agent burns manually
```bash
gt hook burn  # Deletes current hook wisp
```

Option B: Auto-burn on claim
- bd update detects theres a hook for this issue
- Burns the wisp automatically

Option C: Burn in prime (after display)
- Once shown to agent, delete the wisp
- Simple but might lose info if agent crashes before reading

## Recommendation

Use Option A (manual burn) for v0.1:
- Explicit is better than implicit
- Agent controls when theyre done with handoff
- Add auto-burn in v0.2

## Command

```bash
gt hook burn
# Deletes .beads-wisp/hook-<agent>.wisp.yaml
# Confirms: "Hook cleared"
```


Phase 2: Hook Execution Protocol

# Phase 2: Hook Execution Protocol

Making agents actually RUN what's on their hook.

## The Problem

Currently, agents wake up, get primed, and... wait. They don't automatically
execute their pinned molecule or slung work. The propulsion is missing.

## The Solution

gt prime should end with an ACTION, not just context loading:

```
gt prime output:
  1. Load context (existing)
  2. Check hook
  3. If hook has work → tell agent to RUN IT NOW
```

## Hook Types

| Hook Content | Action |
|--------------|--------|
| Pinned molecule (mol-*) | Execute current step, close step when done |
| Slung bead (gt-xxx) | Show bead, begin work |
| Nothing | Wait for assignment |

## Molecule Execution Pattern

When hook has a molecule:

```markdown
## Your Hook: mol-deacon-patrol

Current step: inbox-check (gt-xxx)
Status: pending (ready to execute)

**EXECUTE THIS STEP NOW.**

### Step: inbox-check
Check the Mayor's inbox for messages...

When complete, close the step:
  bd close gt-xxx

Then check for next step:
  bd ready
```

The agent sees this, does the step, closes the step bead.

## Key Insight (from bd-hulf/bd-3zm7 rejection)

Molecule execution state is DERIVED from which child beads are closed vs open.
No separate state.yaml files needed. bd mol current already does this.

"Advancing" a molecule = closing the current step bead. Next step is
whichever child is now ready (unblocked).

## Remaining Work

gt-qvn7.2.3: Enhance gt prime to show molecule step prompt using bd mol current.

## Files Changed

- internal/cmd/prime.go - Hook check and action injection
- Uses bd mol current for step discovery (already exists in beads)

## Acceptance Criteria

- gt prime shows current hook and prompts action
- Agent closes step with bd close <step-id>
- bd ready / bd mol current shows next step
- Agent naturally follows the execution flow


bd mol advance command

## Cross-Repo Reference

This work is tracked in beads repo as **bd-3zm7**.

The gastown task gt-qvn7.2.1 is a placeholder.
Actual implementation happens in beads.

See: bd show bd-3zm7 (from beads/crew/dave)


Molecule state file management

## Cross-Repo Reference

This work is tracked in beads repo as **bd-hulf**.

The gastown task gt-qvn7.2.2 is a placeholder.
Actual implementation happens in beads.

See: bd show bd-hulf (from beads/crew/dave)


gt prime molecule execution prompt

Enhance gt prime to show molecule execution prompts.

## When Hook Has Molecule

gt prime should output:

```markdown
## Your Patrol: mol-deacon-patrol

**Current Step:** inbox-check
**Status:** pending (ready to execute)

### Step: inbox-check

Handle callbacks from agents.

Check the Mayor inbox for messages from:
- Witnesses reporting polecat status
- Refineries reporting merge results
...

**EXECUTE THIS STEP NOW.**

When complete, close the step:
  bd close <step-id>

Then check for next step:
  bd ready
```

## Logic

1. Check if hook has pinned molecule (via handoff bead with attachment)
2. Use bd mol current to find current step (derives from open children)
3. Get step details from the bead itself
4. Format execution prompt
5. Include close command (NOT bd mol advance - that was rejected)

## Key Insight (from bd-hulf rejection)

Molecule execution state is DERIVED from which child beads are closed vs open.
No separate state.yaml files. bd mol current already does this correctly.

"Advancing" a molecule = closing the current step bead. The next step
is whichever child is now ready (unblocked).

## Different from Slung Work

Slung work (bead) says "work on this issue"
Molecule says "execute this step of this workflow"

Both use the hook, but prompts differ.

## Files

- internal/cmd/prime.go
- Uses bd mol current for step discovery


Phase 3: Polecat Work Cycle

# Phase 3: Polecat Work Cycle

The complete lifecycle of a single polecat working a single issue.

## The Cycle

```
spawn → wake → prime → read hook → work → submit → complete → cleanup
```

## Step by Step

### 1. Spawn (Deacon/Mayor initiates)

```bash
gt spawn --issue gt-xxx --rig gastown
```

Creates fresh worktree, assigns issue, creates polecat session.

### 2. Wake (Claude starts)

Polecat Claude session starts. SessionStart hook fires.

### 3. Prime (Context loads)

```bash
gt prime  # Runs automatically via hook
```

Loads CLAUDE.md, injects beads context, checks hook.

### 4. Read Hook

gt prime finds the assigned issue on the hook:

```
## Your Hook: gt-xxx

You have been assigned this issue. Begin work now.

Title: Fix authentication bug
Priority: P1
Description: ...

Claim it with: bd update gt-xxx --status=in_progress
```

### 5. Work

Polecat:
- Claims issue: `bd update gt-xxx --status=in_progress`
- Reads relevant code
- Makes changes
- Commits with issue ID

### 6. Submit

Polecat:
- Pushes branch
- Creates MR bead: `bd create "Merge: gt-xxx" --type=merge-request`
- Signals completion

### 7. Complete

Polecat:
- Closes the issue: `bd close gt-xxx --reason "Fixed in commit abc123"`
- Syncs beads: `bd sync`

### 8. Cleanup

Polecat:
- Sends completion mail to Witness
- Session terminates (or awaits next assignment)

## The mol-polecat-work Molecule

This is already defined. The polecat should be bonded to it on spawn.

Key steps:
1. orient - Read context, understand codebase
2. claim - Update issue status
3. work - Implement the fix
4. test - Run tests, verify
5. submit - Push, create MR
6. handoff - Signal done, sync

## Implementation

### gt spawn enhancements

- Automatically pin mol-polecat-work to new polecat
- Pass issue ID as variable
- Ensure hook is set before Claude starts

### Polecat CLAUDE.md

Must include:
- Hook reading instructions
- Molecule execution pattern
- Exit state vocabulary (COMPLETED, BLOCKED, ESCALATE)

## Acceptance Criteria

- gt spawn creates polecat with issue on hook
- Polecat wakes and begins work automatically
- Polecat completes issue and submits MR
- Issue is closed with commit reference


gt spawn pins mol-polecat-work

Enhance gt spawn to automatically pin mol-polecat-work to new polecats.

## Current Behavior

gt spawn --issue gt-xxx creates polecat with issue in mail but no molecule.

## New Behavior

gt spawn should:
1. Create fresh worktree (existing)
2. Initialize polecat beads (existing)
3. Bond mol-polecat-work with issue as variable
4. Pin the molecule to polecat hook
5. Create polecat session

## Molecule Bonding

```bash
bd mol bond mol-polecat-work --var issue_id=gt-xxx --var rig=gastown
```

Creates .beads/molecules/mol-polecat-work-<hash>.state.yaml

## Hook Pinning

```bash
bd pin mol-polecat-work-<hash> --for polecat/<name>
```

Creates .beads-wisp/hook-polecat-<name>.wisp.yaml pointing to molecule

## Files

- internal/spawn/spawn.go - Add mol-polecat-work bonding
- Or: internal/cmd/spawn.go depending on structure


Polecat CLAUDE.md update for hook execution

Update polecat role CLAUDE.md to include hook execution instructions.

## Key Additions

### Startup Protocol

```markdown
## Startup Protocol

When you wake up:

1. **Check your hook first**
   Run: gt prime
   This shows your assigned work.

2. **If hook has molecule**
   You are running a workflow. Execute the current step.
   When done: bd mol advance <mol-id>

3. **If hook has slung bead**
   Work on that specific issue.
   Claim it: bd update <id> --status=in_progress

4. **If hook empty**
   Wait for assignment via mail or spawn.
```

### Work Completion

```markdown
## Completing Work

When you finish your assigned issue:

1. Commit changes: git add && git commit -m "description (issue-id)"
2. Push branch: git push -u origin <branch>
3. Create MR bead: bd create "Merge: <issue-id>" --type=merge-request
4. Close issue: bd close <issue-id> --reason "Fixed in commit abc123"
5. Sync: bd sync
6. Signal done: gt mail send witness/ -s "LIFECYCLE: Done" -m "Completed <issue-id>"
```

### Exit States

```markdown
## Exit States

When finishing, signal your state:

- COMPLETED: Work done successfully
- BLOCKED: Cannot proceed, need help
- ESCALATE: Problem beyond your scope
- HANDOFF: Passing to successor
```

## File

templates/polecat/CLAUDE.md


mol-polecat-work minimal formula

Create minimal mol-polecat-work formula for tracer bullet.

## Simplified Steps

For v0.1, just the essentials:

```yaml
formula: mol-polecat-work-v01
description: Minimal polecat work cycle for tracer bullet.
version: 1

variables:
  - name: issue_id
    required: true
  - name: rig
    required: true

steps:
  - id: claim
    title: Claim the issue
    description: |
      Run: bd update {{issue_id}} --status=in_progress
      Read the issue: bd show {{issue_id}}
      Understand what needs to be done.

  - id: work
    title: Implement the fix
    needs: [claim]
    description: |
      Do the work described in the issue.
      Make your changes.
      Test them.
      Commit with issue ID: git commit -m "description ({{issue_id}})"

  - id: submit
    title: Submit for review
    needs: [work]
    description: |
      Push your branch: git push -u origin <branch>
      Create MR: bd create "Merge: {{issue_id}}" --type=merge-request
      Close issue: bd close {{issue_id}}
      Sync: bd sync
      Signal done: gt mail send witness/ -s "LIFECYCLE: Done"
```

## Location

.beads/formulas/mol-polecat-work-v01.formula.yaml

## Notes

- Keep it simple for tracer bullet
- Full mol-polecat-work can be more elaborate
- This proves the pattern works


Phase 4: Deacon Patrol Loop

$(cat /tmp/phase4.md)


Deacon CLAUDE.md for patrol execution

Update Deacon role CLAUDE.md for patrol execution.

## Key Additions

### Role Definition

```markdown
## Your Role: DEACON

You are the Deacon - Gas Towns heartbeat process.
You run mol-deacon-patrol continuously.

Your job:
- Check mail for callbacks
- Spawn polecats for ready work
- Monitor rig health (basic)
- Cycle context when full
```

### Patrol Execution

```markdown
## Patrol Execution

You run mol-deacon-patrol on your hook.

On each heartbeat from the daemon:
1. Check your current step: bd hook
2. Execute that step
3. Advance: bd mol advance mol-deacon-patrol
4. If COMPLETE: restart the patrol or cycle context

The daemon keeps you alive. Your job is to run the patrol.
```

### Heartbeat Response

```markdown
## Heartbeat Response

When you see "HEARTBEAT: ..." from the daemon:
- If idle: check your hook, start/resume patrol
- If mid-step: continue working
- If waiting: the heartbeat reminds you to check state

Heartbeats are your clock tick. Use them.
```

### Context Cycling

```markdown
## Context Cycling

When context is high (>80%):
1. Write state to molecule
2. Run: gt handoff -s "Deacon cycling" -m "Context full"
3. Exit cleanly
4. Daemon respawns you
5. You wake, prime, read hook, continue
```

## File

deacon/CLAUDE.md (in town root)


mol-deacon-patrol minimal formula

Create minimal mol-deacon-patrol formula for tracer bullet.

## Simplified Patrol (v0.1)

```yaml
formula: mol-deacon-patrol-v01
description: Minimal Deacon patrol for tracer bullet.
version: 1

steps:
  - id: inbox-check
    title: Check inbox
    description: |
      Run: gt mail inbox
      Handle any messages.
      Note any spawn requests or status updates.

  - id: spawn-work
    title: Spawn polecat for ready work
    needs: [inbox-check]
    description: |
      Run: bd ready
      If work available and no polecat already working it:
        gt spawn --issue <first-ready> --rig gastown
      If no work: proceed to next step.

  - id: self-inspect
    title: Assess context and decide loop vs cycle
    needs: [spawn-work]
    description: |
      Evaluate whether to loop (reset) or cycle (handoff).

      ## Heuristics

      **Favor LOOP (bd mol reset):**
      - Context < 60%
      - No errors in this cycle
      - Patrol completed normally

      **Favor CYCLE (gt handoff):**
      - Context > 80%
      - Errors encountered
      - Been running > 1 hour without cycle
      - Model suggests refresh would help

      **Action:**
      - If LOOP: bd mol reset mol-deacon-patrol
      - If CYCLE: gt handoff -s "Deacon cycling" -m "Context: X%, cycles: N"
```

## Loop via Reset

After self-inspect, if staying:
```bash
bd mol reset mol-deacon-patrol
```

This resets all steps to pending, current_step to inbox-check.
Deacon immediately continues with fresh patrol cycle.

## Cycle via Handoff

If context high or refresh needed:
```bash
gt handoff -s "Deacon cycling" -m "Context high, cycling for fresh start"
```

Daemon respawns fresh Deacon with mol-deacon-patrol on hook.

## Location

.beads/formulas/mol-deacon-patrol-v01.formula.yaml


Deacon initialization with patrol molecule

Ensure Deacon always has mol-deacon-patrol on hook.

## The Problem

When Deacon starts fresh, it needs:
1. mol-deacon-patrol bonded
2. Molecule pinned to hook
3. Ready to execute

## Solution: Bootstrap in gt prime

When gt prime runs for role=deacon:

1. Check if mol-deacon-patrol exists on hook
2. If not: bond it and pin it
3. Then show execution prompt

```go
// In prime.go for deacon role
if role == "deacon" && !hasPatrolOnHook() {
    // Bond the patrol formula
    bondDeaconPatrol()
    // Pin to hook
    pinToHook("deacon", patrolMolID)
}
```

## Alternative: Deacon Startup Hook

Or handle in Deacon SessionStart hook:
- Check hook
- If empty: gt mol bond mol-deacon-patrol && gt mol pin

## Files

- cmd/gt/prime.go (if handling in prime)
- deacon/hooks/session-start.sh (if handling in hook)


Phase 5: Integration and Demo

$(cat /tmp/phase5.md)


End-to-end integration test

Create and run end-to-end integration test.

## Test Scenario

1. Clean state: no polecats, fresh beads
2. Create test issue: simple documentation fix
3. Verify Deacon sees it: bd ready shows issue
4. Trigger Deacon: send heartbeat or wait
5. Verify spawn: gt polecats shows new polecat
6. Watch polecat work: tmux attach
7. Verify completion: issue closed, MR created

## Test Script

```bash
#!/bin/bash
# e2e-test.sh

# 1. Clean state
gt polecat remove --all
bd create "Test: update README typo" --type=task --priority=1

# 2. Verify ready
bd ready | grep "update README"

# 3. Wait for Deacon or trigger
# (manual for v0.1)

# 4. Watch
gt status
gt polecats gastown

# 5. Wait for completion
# (manual observation for v0.1)

# 6. Verify
bd list --status=closed | grep "update README"
```

## Success Criteria

- Issue created and visible in bd ready
- Polecat spawned and working
- Issue closed with commit reference
- No manual intervention (except observation)


Documentation humility pass

Update documentation with humble framing.

## Changes Needed

### README.md

- Add "Experimental" or "Alpha" badge
- Clarify current state vs future vision
- List what works vs what is planned
- Include honest limitations section

### Architecture docs

- Mark autonomous features as "planned"
- Distinguish implemented from designed
- Add "Current Status" sections

### CLAUDE.md files

- Remove claims about autonomous operation (where not true)
- Add "v0.1" qualifiers to features
- Be honest about manual steps required

## Tone

NOT: "Gas Town automatically manages agent lifecycles"
YES: "Gas Town provides infrastructure for agent lifecycle management.
     v0.1 requires some manual coordination."

NOT: "The Refinery processes merges autonomously"
YES: "The Refinery is designed for autonomous merge processing.
     v0.1 demonstrates the pattern with manual triggering."

## Files to Review

- README.md
- docs/architecture.md
- docs/quickstart.md (if exists)
- CLAUDE.md files for all roles


Demo recording

Record a terminal demo of the tracer bullet.

## Recording Tool

Use asciinema:
```bash
brew install asciinema
asciinema rec gastown-demo.cast
```

## Demo Script

1. Show gt status (the town)
2. Show bd ready (available work)
3. Show Deacon running (tmux session)
4. Trigger spawn (create issue, Deacon picks it up)
5. Show polecat working (tmux attach briefly)
6. Show completion (bd list, issue closed)
7. Show MR created (bd list --type=merge-request)

## Tips

- Practice run first
- Keep it under 3 minutes
- Add commentary (terminal echo or voiceover)
- Show the key moments clearly

## Output

- gastown-demo.cast (asciinema file)
- gastown-demo.gif (optional, for embedding)
- YouTube/Vimeo upload (optional)


Digest: mol-deacon-patrol

Patrol 9: healthy


Refinery and witness rigs should redirect .beads to mayor rig

The refinery's rig clone and witness rig clones should have their .beads directories redirect to the mayor's rig beads (like polecats do).

Current state:
- Polecats have .beads symlinked/redirected to mayor rig beads
- Refinery and witness have their own .beads (or none)

Desired state:
- refinery/rig/.beads -> mayor/rig/.beads (or equivalent redirect)
- witness/rig/.beads -> mayor/rig/.beads (or equivalent redirect)

This ensures all rig agents share the same issue tracking state.


Digest: mol-deacon-patrol

Patrol 212: All nominal


Digest: mol-deacon-patrol

Patrol 17 complete


Test issue for spawn molecule


Merge: gt-jzot

branch: polecat/nux
target: main
source_issue: gt-jzot
rig: gastown


Test4

test4 body


Digest: mol-deacon-patrol

Patrol 104: All agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, inbox empty, 1 dog idle


Refinery patrol: Add banners and wisp-based execution

Bring Refinery patrol up to Deacon's level of sophistication:

## Current state
- mol-refinery-patrol exists (needs verification)
- Basic merge queue processing

## Needed
1. **Banners** - Print step banners like Deacon does:
   ```
   ═══════════════════════════════════════════════════════════════
     ⚗ QUEUE-CHECK
     Processing merge queue entries
   ═══════════════════════════════════════════════════════════════
   ```

2. **Wisp-based execution** - Spawn patrol as wisp, squash when complete
3. **Handoff bead attachment** - Refinery needs its own handoff bead with attached_molecule
4. **Loop-or-exit step** - Context-aware cycling like Deacon
5. **Patrol summary banner** at end of each cycle

## Reference
See Deacon patrol implementation in ~/gt/deacon/CLAUDE.md


EXTERNAL: Beads Messaging & Knowledge Graph (bd-kwro)

Tracking issue for external dependency on Beads v0.30.2 messaging features.

Beads epic: bd-kwro in ~/src/beads (steveyegge/beads repo)

This blocks GGT work that depends on:
- bd mail send/inbox/read/ack commands
- message issue type
- replies_to threading
- Hooks system for notifications
- Identity configuration

GGT mail commands will be thin wrappers around bd mail once available.

When bd-kwro ships in Beads v0.30.2, close this and unblock dependent work.


Merge: imperator-1767106079026

branch: polecat/imperator-1767106079026
target: main
source_issue: imperator-1767106079026
rig: gastown


Digest: mol-deacon-patrol

Patrol cycle 67: All healthy


Digest: mol-deacon-patrol

Patrol 10: quick pass, hitting halfway point


Digest: mol-deacon-patrol

Patrol cycle 9


Merge: valkyrie-1767147773208

branch: polecat/valkyrie-1767147773208
target: main
source_issue: valkyrie-1767147773208
rig: gastown


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, 1 message processed, no orphans


gt spawn: Notify Deacon and Witness on polecat start

When gt spawn creates a polecat, it should mail both Deacon and Witness:

```
gt mail send <rig>/witness -s 'POLECAT_STARTED furiosa' -m 'Issue: gt-xxx'
gt mail send deacon/ -s 'POLECAT_STARTED gastown/furiosa' -m 'Issue: gt-xxx'
```

This enables:
- Witness to bond a lease to its patrol wisp
- Deacon to verify worker started (redundancy)
- Both to nudge if worker is idle at prompt

Part of the village self-monitoring architecture.


Merge: gt-5wb7

branch: polecat/nux
target: main
source_issue: gt-5wb7
rig: gastown


Move mol run semantics from bd into gt spawn

Currently gt spawn shells out to bd mol run for the pour+assign+pin combo. This blurs the architectural boundary between bd (data layer) and gt (orchestration layer).

## Current State
- bd mol run = bd pour + bd update --status=in_progress + bd pin --for me
- gt spawn calls: exec.Command("bd", "mol", "run", ...)

## Proposed Change
Move the combo logic into gt spawn directly:
1. gt spawn calls bd pour (create issues from template)
2. gt spawn calls bd update --status=in_progress (claim work)
3. gt spawn calls bd pin (set pinned flag)
4. gt spawn does session/tmux orchestration

This keeps bd as pure data operations and gt as the orchestration layer.

## Why
- Cleaner separation of concerns
- bd mol run feels like orchestration but it's in the data layer
- gt should own the "start a workflow" semantics

## Coordination
beads side will deprecate bd mol run once gt no longer depends on it.


Digest: mol-deacon-patrol

Patrol 1: All agents healthy. Clone divergence (zoey/jack) noted for witnesses.


Digest: mol-deacon-patrol

Patrol 4: quiet


Implement pinned beads for handoff state

Add pinned bead support to beads:
- Pinned beads never close, only update
- Use for persistent state like Refinery handoffs
- bd create --pinned flag
- bd list --pinned to find them
- Update description to change state


Digest: mol-deacon-patrol

Patrol 154: All healthy


Digest: mol-deacon-patrol

Cycle 200: Final cycle of session, all agents healthy, handoff triggered


Digest: mol-deacon-patrol @ 2025-12-24 19:46

Patrol 14: All healthy


Digest: mol-deacon-patrol

Patrol complete: all 3 rigs healthy, no incidents


Patrol System: Agent lifecycle loops with attachments

Enable Gas Town agents to run continuous patrols, survive crashes, and hand off work across sessions.

## Core Concepts
- **Attachments**: Molecules bound to agent's pinned bead until complete
- **Patrols**: Cyclic molecules that loop (deacon, witness, refinery)
- **Quiescent**: Agents that sleep until triggered (witness, refinery)

## Design Doc
See docs/patrol-system-design.md

## Phases
Phase 1: Foundation (attachment field, daemon detection, mol-deacon-patrol)
Phase 2: Quiescent Agents (wake triggers, witness/refinery patrols)
Phase 3: Callbacks and Plugins (mail protocol, plugin runner)
Phase 4: Polish (gt patrol status, metrics, tuning)

## Key Decisions
- Attachment as field on pinned bead (not edge type, for now)
- Mail-based orchestration for all callbacks
- Queue replacement for heartbeat delivery (not pile-up)
- Burn and respawn for patrol loops (not in-place reset)


Phase 1.1: Attachment field on pinned beads

Add attached_molecule field to pinned bead schema.

## Schema Change
Add to handoff/pinned bead issues:
- attached_molecule: string (root issue ID of attached mol)
- attached_at: timestamp

## Implementation
- Update beads Issue struct if needed
- Or: use labels/metadata field
- Ensure bd show displays attachment info

## Acceptance
- Can set/clear attachment on a bead
- bd show displays attachment status


Phase 1.2: Daemon attachment detection

Daemon polls Deacon's pinned bead to detect naked state.

## Implementation
- Daemon knows Deacon's pinned bead ID
- Every heartbeat cycle: bd show <pinned> --json
- Parse attached_molecule field
- If null/empty: Deacon is naked

## Actions on Naked
- Spawn mol-deacon-patrol
- Attach to Deacon's pinned
- Nudge Deacon to start

## Failsafes
- Keepalive file monitoring
- Stale detection (>10min no progress)
- Force nudge on stale

Depends: gt-rana.1


Phase 1.3: mol-deacon-patrol definition

Define the Deacon patrol molecule in builtin_molecules.go.

## Steps
1. inbox-check - Handle callbacks from agents
2. health-scan - Ping Witnesses and Refineries
3. plugin-run - Execute registered plugins
4. orphan-check - Find abandoned work
5. session-gc - Clean dead sessions
6. context-check - Check own context limit
7. loop-or-exit - Burn and let daemon respawn, or exit if context high

## Implementation
- Add DeaconPatrolMolecule() to builtin_molecules.go
- Add to BuiltinMolecules() list
- Test with bd mol show mol-deacon-patrol


Phase 1.4: Basic patrol runner in Deacon

Deacon CLAUDE.md and prime context for patrol execution.

## Deacon Context
- Update Deacon CLAUDE.md with patrol instructions
- On wake: check pinned bead for attachment
- If attached: resume molecule from current step
- Execute steps, close each when done
- On final step: burn molecule, go naked

## gt prime Enhancement
- Detect if agent has attached molecule
- Show molecule progress in prime output
- Include patrol-specific instructions

Depends: gt-rana.3


Phase 2: Quiescent agents (Witness, Refinery)

Enable Witness and Refinery to sleep until triggered.

## Scope
- Wake triggers: gt spawn, MR submit, mail, Deacon ping
- Wake SLA: <1 minute
- mol-witness-patrol and mol-refinery-patrol definitions
- Quiescent entry/exit protocol

## Implementation
- Kill tmux session on quiescent entry
- Preserve sandbox (worktree, state files)
- Restart session on wake trigger
- Agent checks pinned, spawns default patrol if naked

Depends: Phase 1 complete


Phase 3: Callbacks and plugins

Mail-based callback protocol and plugin surface.

## Callbacks
- Polecat → Witness: shutdown requests
- Witness → Deacon: escalations, status
- Crew → Deacon: recycle requests
- Deacon → Mayor: escalations

## Plugins
- .beads/plugins.yaml registry
- Cooldown tracking
- Plugin runner in deacon patrol

Depends: Phase 2


Phase 4: Polish and observability

Production readiness.

## Commands
- gt patrol status - Show patrol state for all agents
- gt patrol history - Recent patrol activity

## Observability
- Metrics collection
- Alert thresholds
- Dashboard (optional)

## Tuning
- Cooldown optimization
- Wake SLA verification
- Error threshold tuning

Depends: Phase 3


Harden bd daemon startup for reliable gt status

GH #25: gt status slow (39s) when bd daemon not running. Needs daemon health checks, auto-migration, better errors.


Digest: mol-deacon-patrol

Patrol 20: clear, handoff


Digest: mol-deacon-patrol

Patrol cycle 5: routine, healthy


Digest: mol-deacon-patrol

Patrol 12: quick pass


Merge: splendid-mjwjk3my

branch: polecat/splendid-mjwjk3my
target: main
source_issue: splendid-mjwjk3my
rig: gastown
agent_bead: gt-gastown-polecat-splendid


Witness events in gt feed

Wire witness patrol events to gt feed display.

After 'Witness emits activity events' is done:
- gt feed should show patrol activity
- Useful for debugging polecat issues

Example output:
  19:45 PATROL_COMPLETE gastown/witness (checked 3 polecats)
  19:44 POLECAT_NUDGED gastown/polecats/nux (idle 10m)
  19:40 ESCALATION mayor (polecat stuck)


Test Polecat Arm

Test child for bonding pattern


Digest: mol-deacon-patrol

Patrol 81: All agents healthy, 2 epics in progress, 1 idle dog, inbox clear


Digest: mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol cycle 15: All healthy.


gt-refinery-gastown

Refinery - per-rig merge queue processor for gastown.

role_type: refinery
rig: gastown
agent_state: idle
hook_bead: null
role_bead: gt-refinery-role


Refinery Role Definition

You are the Refinery - merge queue processor for your rig. You process
completed polecat work, merging it to main one branch at a time with
sequential rebasing.

Your mission: Process the merge queue sequentially, rebasing each branch
atop the current baseline before merging.

session_pattern: gt-{rig}-refinery
work_dir_pattern: {town}/{rig}/refinery/rig
needs_pre_sync: true
start_command: exec claude --dangerously-skip-permissions

default_molecule: mol-refinery-patrol
capabilities:
  - merge_queue_processing
  - sequential_rebase
  - conflict_resolution
  - verification_gates

## The Engineer Mindset

You are Scotty in the engine room. The merge queue is your warp core.

The Beads Promise: Work is never lost. If you discover ANY problem:
1. Fix it now (preferred if quick), OR
2. File a bead and proceed (tracked for cleanup crew)

There is NO third option. Never "disavow" by noting something exists and moving on.

The Scotty Test: Before proceeding past any failure, ask yourself:
"Would Scotty walk past a warp core leak because it existed before his shift?"

## Propulsion Principle

If you find something on your hook, YOU RUN IT.

Your work is defined by the mol-refinery-patrol molecule. Execute steps:
- bd ready (find next step)
- bd show <step-id> (see what to do)
- bd close <step-id> (mark complete)

## Sequential Rebase Protocol

WRONG (parallel merge - causes conflicts):
  main then branch-A (old main) + branch-B (old main) = CONFLICTS

RIGHT (sequential rebase):
  main then merge A (rebased on main) then merge B (rebased on main+A)

After every merge, main moves. Next branch MUST rebase on new baseline.

## Verification Gate

The handle-failures step is a verification gate:
- Tests PASSED: Gate satisfied, proceed to merge
- Tests FAILED (branch caused): Abort, notify polecat, skip branch
- Tests FAILED (pre-existing): MUST fix OR file bead - cannot proceed without

## Commands

### Patrol
- gt mol status - Check attached patrol
- bd ready / bd show / bd close - Step management
- bd mol spawn <mol> --wisp - Spawn patrol wisp

### Git Operations
- git fetch origin - Fetch all remote branches
- git branch -r | grep polecat - List polecat branches
- git rebase origin/main - Rebase on current main
- git push origin main - Push merged changes

### Communication
- gt mail inbox - Check for messages
- gt mail send <addr> -s "Subject" -m "Message" - Notify workers


Digest: mol-deacon-patrol

Patrol 5: Quiet


Deprecate hook files, use pinned beads for propulsion

## Problem

Hook files were "deprecated" via comments but NOT eradicated. The code is all still there and actively used.

## Current State (NOT Done)

**Live hook file exists:**
- `/Users/stevey/gt/deacon/.beads/hook-deacon.json`

**Code still calling hook functions:**
- `resume.go:151` - WriteSlungWork
- `park.go:114` - ReadHook
- `spawn.go:407` - WriteSlungWork
- `molecule_step.go:293` - WriteSlungWork
- `molecule_step.go:368` - BurnHook

**Hook infrastructure still exists:**
- `internal/wisp/io.go` - All hook I/O functions
- `internal/wisp/types.go` - SlungWork, Wisp types, constants
- `.beads/.gitignore` - hook-*.json pattern

**14 docs still reference hooks:**
architecture.md, beads-data-plane.md, molecular-chemistry.md, molecules.md,
pinned-beads-design.md, polecat-lifecycle.md, polecat-wisp-architecture.md,
propulsion-principle.md, session-lifecycle.md, sling-design.md, vision.md,
wisp-architecture.md, witness-patrol-design.md, ~/gt/CLAUDE.md

## Goal: Total Eradication

1. Remove ALL hook file code from callers
2. Delete hook functions from internal/wisp/
3. Delete hook types and constants
4. Remove gitignore patterns
5. Delete any live hook files, convert to pinned beads
6. Update all documentation
7. Verify propulsion cycle works with pinned beads only


Remove hook code from cmd callers

Remove hook file calls from:
- resume.go:151 - WriteSlungWork → use bd update --status=pinned
- park.go:114 - ReadHook → query pinned beads
- spawn.go:407 - WriteSlungWork → use bd update --status=pinned
- molecule_step.go:293 - WriteSlungWork → use bd update --status=pinned
- molecule_step.go:368 - BurnHook → use bd update --status=open


Delete hook functions from internal/wisp

Delete from internal/wisp/io.go:
- WriteSlungWork
- ReadHook
- BurnHook
- HasHook
- ListHooks
- HookPath

Keep: EnsureDir, WispPath, writeJSON (used by other things)


Delete hook types from internal/wisp

Delete from internal/wisp/types.go:
- WispType type
- TypeSlungWork constant
- HookPrefix, HookSuffix constants
- Wisp struct
- SlungWork struct
- NewSlungWork function
- HookFilename function
- AgentFromHookFilename function

The entire file may become empty or minimal.


Clean up hook-related gitignore and live files

- Remove hook-*.json from .beads/.gitignore
- Delete /Users/stevey/gt/deacon/.beads/hook-deacon.json
- Convert gt-wisp-0gu to pinned bead if needed


Update all documentation to remove hook references

14 docs reference hooks:
- docs/architecture.md
- docs/beads-data-plane.md
- docs/molecular-chemistry.md
- docs/molecules.md
- docs/pinned-beads-design.md
- docs/polecat-lifecycle.md
- docs/polecat-wisp-architecture.md
- docs/propulsion-principle.md
- docs/session-lifecycle.md
- docs/sling-design.md
- docs/vision.md
- docs/wisp-architecture.md
- docs/witness-patrol-design.md
- ~/gt/CLAUDE.md

Update all to reflect pinned beads as the sole propulsion mechanism.


Digest: mol-deacon-patrol

Patrol cycle 2: All healthy, quick pass


gt up: set BD_ACTOR env var when spawning agents

When gt spawns agents (polecats, crew, patrol roles), it should set BD_ACTOR env var so that bd commands (like `bd hook`) know the agent identity.

Currently gt sets GT_ROLE but bd can't check that (no coupling to gt). bd already checks BD_ACTOR, so gt just needs to set it.

Places to update:
- `gt up` for polecats/crew
- Deacon, Witness, Refinery spawning
- Any other agent spawn points

Related: closed bd-fej5 in beads repo as obsolete (fix belongs here).


Activity Feed TUI

Terminal UI for browsing Gas Town activity. Shows hierarchical view of rigs, workers, and their current state. Features: live updates, expandable details, molecule progress (step X of Y). Built with bubbletea/lipgloss. Design doc: history/activity-feed-tui-design.md


Digest: mol-deacon-patrol

Patrol cycle 59: All healthy


Bug: parseLifecycleRequest always matches 'cycle' due to LIFECYCLE prefix

In lifecycle.go, parseLifecycleRequest checks strings.Contains(title, "cycle") first, but the prefix "LIFECYCLE:" contains the word "cycle". This means ALL lifecycle messages match the cycle action, making restart and shutdown unreachable. Fix: check for restart/shutdown before cycle, or use word boundaries.


Merge: nux-mjxltj45

branch: polecat/nux-mjxltj45
target: main
source_issue: nux-mjxltj45
rig: gastown
agent_bead: gt-gastown-polecat-nux


Digest: mol-deacon-patrol

Patrol cycle 74: All healthy


Digest: mol-deacon-patrol

Patrol complete: gastown healthy, beads dormant


CLI: gt refinery commands (start, stop, status, queue)

CLI commands for managing the Refinery agent.

## Commands

```bash
gt refinery start <rig>      # Start refinery for a rig
gt refinery stop <rig>       # Stop refinery
gt refinery status <rig>     # Show refinery status
gt refinery queue <rig>      # Show merge queue
```

## gt refinery start

Starts the Refinery daemon for the specified rig.

Options:
- --foreground: Run in foreground (default: background)
- --auto-merge: Enable auto-merge (default: from config)

## gt refinery stop

Stops a running Refinery. Gracefully finishes current MR if processing.

## gt refinery status

Shows:
- Running state (running/stopped)
- Current MR being processed (if any)
- Queue length
- Last merge time
- Recent activity

## gt refinery queue

Shows the merge queue:
```
Merge queue for 'wyvern':
  1. [pending] Toast/polecat-auth-fix (15m ago)
  2. [pending] Capable/polecat-new-feature (5m ago)

1 merged today, 0 rejected
```

## Implementation

Uses gt-ov2 (Refinery agent) for daemon functionality.


Digest: mol-deacon-patrol

Patrol 20: all healthy


Digest: mol-deacon-patrol

Patrol 27: all polecats working, jack session started


Digest: mol-deacon-patrol

Patrol 20: Final. 19 polecats. 3 MQ pending. All healthy.


CRITICAL: gt doctor orphan-processes kills active crew sessions

## Problem

The deacon's patrol runs `gt doctor --fix` which includes an orphan-processes check. This check is incorrectly identifying ACTIVE crew sessions as orphaned and killing them.

## Impact

- Crew workers are being killed mid-session
- Work is lost
- The deacon is currently disabled until this is fixed

## Root Cause

The orphan-processes detection logic in `internal/doctor/` doesn't properly identify crew workers. It likely:
1. Doesn't recognize the `gt-<rig>-<name>` session pattern for crew
2. Or misidentifies the Claude process as orphaned when it has a valid tmux parent

## Workaround

The patrol formula was updated to instruct deacon not to run `--fix` if orphan-processes reports any PIDs. But this workaround failed - the deacon still killed crew.

## Fix Required

1. Update `internal/doctor/identity_check.go` or `branch_check.go` to properly detect crew sessions
2. Add crew session patterns to the valid session detection
3. Add test coverage for crew worker scenarios

## Files

- internal/doctor/identity_check.go
- internal/doctor/branch_check.go
- internal/cmd/doctor.go

## Related

- Commit 3452b041 attempted to fix via formula instructions but failed
- The digest hq-yedg claimed to file gt-vj5zc but never did


Digest: mol-deacon-patrol

Patrol 6: all clear


Extend auto-continue to polecats (not just crew)

gt prime currently only outputs AUTO-CONTINUE MODE for crew workers.
Polecats with attached work should also auto-continue.

## Current behavior
outputCrewAttachmentStatus() in prime.go:
- Only runs for RoleCrew
- Outputs '→ AUTO-CONTINUE MODE' when attached work detected

## Desired behavior
- Rename to outputAttachmentStatus() or similar
- Run for RoleCrew AND RolePolecat
- Same directive: if attachment exists, work immediately

## The Propulsion Principle
'If you find something on your hook, YOU RUN IT.'

This applies to ALL workers, not just crew.

## Implementation
1. Extend role check in outputCrewAttachmentStatus()
2. Adjust assignee detection for polecats vs crew
3. Test with both worker types


Digest: mol-deacon-patrol

Patrol 6: All healthy


gt crew remove: Does not close agent bead

When running 'gt crew remove <name>', the command removes the crew workspace directory but does not close the associated agent bead (gt-<rig>-crew-<name>).

This leaves orphaned agent beads in the system after crew removal.

The remove command should close the agent bead with a reason like 'Crew workspace removed'.


Digest: mol-deacon-patrol

Patrol 7: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol cycle 14: All healthy - dag polecat started


mol-swarm-cleanup: Post-swarm debris cleanup molecule

After a 20+ worker swarm completed, found significant beads debris:
- 18 stale messages (work assignments, lifecycle requests, swarm instructions)
- 3 completed issues still open/in_progress
- Test messages accumulated

Need: Document a post-swarm checklist or create gt swarm cleanup command that:
1. Closes stale work assignment messages
2. Reviews in_progress issues for completion
3. Closes orphaned lifecycle messages
4. Optionally archives test messages


Digest: mol-deacon-patrol

Patrol 6: all healthy


implement

Implement the solution for gt-ds3h3. Follow codebase conventions.
File discovered work as new issues with bd create.

Make regular commits with clear messages.
Keep changes focused on the assigned issue.

Depends: load-context


Bug: Deacon session linked to Mayor pane causes heartbeat crosstalk

**Root cause found**: The gt-deacon tmux session was linked to gt-mayor window 2 - they shared the same pane (@283). When the daemon sent heartbeats to the Deacon, they appeared as typed input in the Mayor's window, interrupting user prompts.

**Fix applied**: Killed the broken gt-deacon session. The daemon auto-recreates it with a proper independent pane.

**Prevention**: Investigate how sessions can get linked and add safeguards to session creation code.

Original symptom: Mayor receiving 'HEARTBEAT: Tip: Witnesses monitor polecats...' messages that ate user input.


Merge: capable-1767074974673

branch: polecat/capable-1767074974673
target: main
source_issue: capable-1767074974673
rig: gastown


Digest: mol-deacon-patrol

Patrol 15: All healthy


Digest: mol-deacon-patrol

Patrol cycle 8: all healthy


Fix TestHasPolecat test failure in internal/session

TestHasPolecat in internal/session/manager_test.go fails because it expects
specific polecats (Toast, Cheedo) to exist in the test environment.

Error:
```
manager_test.go:46: expected hasPolecat(Toast) = true
manager_test.go:49: expected hasPolecat(Cheedo) = true
```

Fix: Either create test fixtures or mock the filesystem check.


Digest: mol-deacon-patrol

Patrol 5: healthy


Digest: mol-deacon-patrol

Patrol 10: healthy


gt mail send: support reading message body from stdin

Currently gt mail send -m requires the message as a command-line argument, which causes shell escaping issues with backticks, quotes, and special characters.

Add support for reading message body from stdin:
- gt mail send addr -s 'Subject' --stdin  # Read body from stdin
- echo 'body' | gt mail send addr -s 'Subject' -m -  # Convention: -m - means stdin

This would allow:
cat <<'EOF' | gt mail send addr -s 'Subject' --stdin
Message with \`backticks\` and 'quotes' safely
EOF

Without this, agents struggle to send handoff messages containing code snippets.

## Moved from beads
Originally bd-3bsz. gt mail is in gastown, not beads.


Implement Boot: daemon entry point dog for Deacon triage

Boot is a dog (Deacon helper) that the daemon pokes instead of the Deacon directly.

Purpose: Centralize 'when to wake Deacon' decision in an agent that can reason about it.

Lifecycle:
- Daemon tick spawns Boot (fresh each time)
- Boot runs triage molecule:
  - Observe (wisps, mail, git state, tmux panes)
  - Decide (start/wake/nudge/interrupt/nothing)
  - Act
  - Clean inbox (discard stale handoffs)
  - Handoff (or exit in degraded mode)

Location: ~/gt/deacon/dogs/boot/
Session: gt-deacon-boot
Created by: bd doctor

Needs:
- Boot formula (mol-boot-triage.toml)
- gt dog prime boot command
- Daemon change to poke Boot instead of Deacon
- Degraded mode support (GT_DEGRADED=true)

See: gastown/mayor/rig/docs/operational-state.md


Digest: mol-deacon-patrol

Patrol 10: routine, halfway


Merge: bix-mjufugoo

branch: polecat/bix-mjufugoo
target: main
source_issue: bix-mjufugoo
rig: gastown


Digest: mol-deacon-patrol

Patrol 8: Routine


Digest: mol-deacon-patrol

Patrol 9: All clear


Digest: mol-deacon-patrol

Patrol 18: all healthy


Day 1.4c: Create polecat agent bead lifecycle

Define ephemeral polecat agent bead lifecycle.

Polecats need agent beads for ZFC compliance (self-report state).

Lifecycle:
1. On spawn: Create agent bead
   ```yaml
   id: gt-polecat-<rig>-<name>
   type: agent
   role_type: polecat
   rig: <rig>
   state: spawning
   hook_bead: <assigned-issue>
   ```

2. On Claude ready: Update state=working

3. On completion: Update state=done

4. On nuke: Delete agent bead

Commands needed:
- gt polecat spawn creates agent bead
- gt polecat nuke deletes agent bead
- Polecat updates own state via bd agent state

Note: This ensures Witness can read polecat state from beads instead of tmux scraping.

Implemented polecat agent bead lifecycle: spawn creates bead with state=spawning, nuke deletes bead. State updates (spawning→working→done) require bd agent state command (beads CLI enhancement).


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no callbacks, cleaned 1 stale lock


Multiple merge/landing models documented without clarification

Architecture describes three different merge models:

1. Refinery-only model (traditional)
2. Direct landing model (Mayor bypass)
3. Swarm integration branch model (internal/swarm)

These appear to conflict. Documentation should clarify:
- Which model is canonical?
- When to use which model?
- Or are some deprecated?

This is confusing for users trying to understand the system.


Digest: mol-deacon-patrol

Patrol 158 complete


Digest: mol-deacon-patrol

Patrol 12: all quiet


HOP: Entity chain tracking for agents

Track work history per-entity (CV chains). See ~/ai/stevey-gastown/hop/decisions/002-entity-chains.md for design. Post-v0.1 work.


Digest: mol-deacon-patrol

Patrol 2: inbox empty, all agents healthy, fixed 1 orphan process


test


Digest: mol-deacon-patrol

Patrol cycle 6: All healthy


Digest: mol-deacon-patrol

Patrol 11: Routine


Clean up stale children on deacon handoff bead

The deacon handoff bead hq-8r8 has 7 stale children (hq-8r8.1 through hq-8r8.7) from a previous patrol that got incorrectly parented. These should be cleaned up.

The handoff bead should only contain the attached_molecule reference, not instantiated steps.


Witness patrol: stale MR queue detection needs state tracking

The mol-witness-patrol check-refinery step says 'if queue is non-empty for >30 min, send nudge' but doesn't explain how to track when the queue first became non-empty.

## Problem
The Witness needs to persist:
- When MR queue first became non-empty
- Previous queue state for comparison

Without this, the Witness can't detect stale queues.

## Solution
Add to witness handoff bead:
- mr_queue_nonempty_since: timestamp
- Update in save-state step
- Check in check-refinery step


Digest: mol-deacon-patrol

Patrol 2: Quick scan, all healthy, no work


gt polecat: add 'done' or 'finish' command to transition from working to idle

When a polecat finishes work but session wasn't properly cleaned up, there's no way to reset it from 'working' state back to 'idle'.

Tried:
```
gt polecat sleep gastown/Angharad
Error: sleeping polecat: polecat is not active (state: working)
```

The sleep command only works on 'active' polecats, not 'working' ones.

Had to manually edit state.json to reset:
```
jq '.state = "idle" | .issue = ""' state.json
```

Need a command like:
```
gt polecat done gastown/Angharad   # working -> idle
gt polecat finish gastown/Angharad # working -> idle
gt polecat reset gastown/Angharad  # any state -> idle (force)
```


Recover orphaned commits from polecat work

73 orphaned commits found via `gt orphans`. These are polecat work that was done
but never merged to main - either due to merge conflicts, refinery issues, or
premature session kills.

**Recovery Process:**
1. Run `gt orphans` to get full list with SHAs
2. For each commit, categorize:
   - Already merged (different SHA but same work) → skip
   - Needs cherry-pick → attempt cherry-pick, resolve conflicts
   - Obsolete (superseded by other work) → skip
3. Cherry-pick valuable commits in dependency order
4. Push recovered work to main

**Known valuable orphans (sample):**
- 77f9da07 convoy CLI (RECOVERED)
- 8d2f5ca8 Dog infrastructure (gt-0x5og.2)
- 5c3f1795 Swarm beads backing (gt-kc7yj.1)
- 341414df Wire MQ lifecycle events to gt feed (gt-lak31)
- Many more...

**Root cause to fix:**
- Witness closing tasks before verifying merge success
- Refinery not handling conflicts gracefully
- Need "Landing Rule" enforcement


Glass Cockpit: See WTF is happening

Glass cockpit - see what's happening across the system.

Phase 1 got the engine running. Phase 2 makes it observable.

**Pillars:**
- Pillar 4: Swarm-in-Beads (gt-kc7yj - already exists)
- Pillar 5: MQ Observability
- Pillar 6: Witness Observability
- Pillar 7: Unified Dashboard

**Success criteria:**
1. gt status shows per-rig queue depth and agent health
2. gt feed shows MQ and swarm lifecycle events
3. gt dashboard provides live system visibility
4. No .runtime/*.json files for observable state
5. Swarms fully tracked in beads

Reference: ~/gt/docs/liftoff-plan.md


Digest: mol-deacon-patrol

Patrol cycle 69: All healthy


Batch wisp squashing in Deacon maintenance

Add wisp squashing to Deacon's maintenance duties:
- Patrol plugin to find orphaned/completed wisps across all rigs
- Squash completed patrol wisps to digests
- Burn abandoned wisps that have no audit value
- Part of the hygiene/cleanup system

Also: Witness polecat shutdown should spawn its own short wisp for the cleanup protocol.


gt status: Show agent hook_bead (current work) in status output

attached_args: Implement the hook_bead display in gt status. The agent bead lifecycle is complete - just need to read hook_bead and display it.

## Current State

gt status shows agents with their agent_state from beads:
```
   crew/max       ✓ running [running]
```

## Enhancement

Show what each agent is working on (hook_bead field from agent beads):
```
   crew/max       ✓ running [running] → gt-abc (Fix auth bug)
   crew/joe       ✓ running [running] → gt-xyz (Add tests)
   refinery       ✓ running → refinery Handoff
```

This gives the overseer a quick view of:
1. Who is running
2. What each agent is working on
3. Progress at a glance

## Implementation

In status.go, when displaying agents:
1. Look up agent bead by ID (e.g., gt-crew-gastown-max)
2. Parse hook_bead from description
3. If hook_bead set, fetch its title for display
4. Show as: agent_state → hook_bead (title truncated)

## Related

The agent bead lifecycle is now complete:
- prime.go creates agent beads
- sling.go sets hook_bead
- done.go clears hook_bead and sets final state


Digest: mol-deacon-patrol

Patrol 7: nominal


Digest: mol-deacon-patrol

Patrol 13: all clear


Digest: mol-deacon-patrol

Patrol 13: all healthy


Digest: mol-deacon-patrol

P4: stable


Add 'gt rig start <rig>' to start witness and refinery together

After a town restart, need a convenient way to start both witness and refinery for a rig.

Current workflow requires two commands:
  gt witness start <rig>
  gt refinery start <rig>

Desired:
  gt rig start <rig>  # starts both witness and refinery

Should also support:
  gt rig stop <rig>   # stops both
  gt rig restart <rig> # restarts both


Digest: mol-deacon-patrol

Patrol 4: 3 rigs healthy


Phase 1: Core messaging primitives (@group, list:, queue:)

## Scope

Core messaging infrastructure that enables multi-recipient and work-queue patterns.

### Deliverables

1. **Config directory structure** - ~/gt/config/ with lists.json, queues.json
2. **@group dynamic resolution** - Filesystem scan for agent directories
   - @rig/gastown → scan gastown/ for agents
   - @town → scan all rigs
   - @witnesses, @crew/gastown, etc.
3. **list:name static lookup** - Fan-out to N copies (each recipient gets work item)
4. **queue:name with claim** - Shared storage, atomic claim via bd update --claim
5. **Fan-out at send time** - gt mail send handles expansion

### Key semantics
- @group and list: both fan out (N copies, N obligations)
- queue: shared copy, first-to-claim wins
- All resolve at send time, not receive time


Digest: mol-deacon-patrol

Test patrol cycle - verifying wisp flow


Digest: mol-deacon-patrol

Patrol cycle 1: All 3 rigs healthy (beads, gastown, wyvern). Witnesses/Refineries running. No orphans, no zombies, 1 dog idle. 3 convoys open tracking work.


gt swarm dispatch command not working

The "gt swarm dispatch" command shown in help does not work as expected.

**Observed:**
```
$ gt swarm dispatch bd-784c
[prints help text instead of dispatching]
```

**Expected:**
Should dispatch the next ready task from the epic to an available worker.

**Workaround:**
Had to manually use "gt sling <issue> <polecat>" for each task dispatch.

**Impact:**
- Manual task dispatch defeats swarm automation
- Coordinator has to track which tasks are ready and which polecats are free

**Suggestion:**
Implement or fix "gt swarm dispatch" to:
1. Find next unassigned task in epic
2. Find idle polecat in swarm
3. Sling task to polecat automatically

(Moved from bd-kp9y)


Remove gt context --usage estimation

The external context estimation approach doesn't work:
- tmux scrollback trick breaks with --cycle
- Can't see actual context usage from outside
- Only the agent knows its internal state

Remove or deprecate:
- gt context --usage flag
- Any external context monitoring logic

Document why in comments: 'Context management is agent-initiated, not externally monitored.
See self-check guidance in role templates.'

This is P3 because it's cleanup - the feature just doesn't work, not actively harmful.


Execute registered plugins

Execute registered plugins.

Scan ~/gt/plugins/ for plugin directories. Each plugin has a plugin.md with
YAML 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.


Digest: mol-deacon-patrol

Patrol 160 complete


Filter agent session molecule noise from activity feed

Agent session molecules (gt-crew-gastown-joe, gt-crew-gastown-max, etc.) update frequently
and create noisy entries like:

  [10:22:37] → gt-crew-gastown-joe updated · gt-crew-gastown-joe

These are not useful in the activity feed. Options:
1. Filter them out entirely
2. Collapse repeated updates into single entries
3. Show them in a separate "agent status" section

Part of epic gt-u7dxq


Digest: mol-deacon-patrol

Patrol cycle 11: All healthy - Witness/Refinery running, no pending spawns, no convoys, no gates, no orphans, inbox clean


inbox-check

Process witness mail: lifecycle requests, help requests.

```bash
gt mail inbox
```

Handle by message type:
- LIFECYCLE/Shutdown: Queue for pre-kill verification
- Blocked/Help: Assess if resolvable or escalate
- HANDOFF: Load predecessor state
- Work complete: Verify issue closed, proceed to pre-kill

Record any pending actions for later steps.
Mark messages as processed when complete.


Digest: mol-deacon-patrol

Patrol 45: All healthy


Merge: slit-1767073379145

attached_args: Code review

branch: polecat/slit-1767073379145
target: main
source_issue: slit-1767073379145
rig: gastown


Digest: mol-deacon-patrol

Patrol cycle 7: all healthy


Digest: mol-deacon-patrol

Patrol 13: routine


Enhanced polecat decommission prompting

Add decommission checklist to polecat AGENTS.md.template. Make crystal clear: verify ALL before signaling done.

## Checklist for AGENTS.md.template

```markdown
## Decommission Checklist

**CRITICAL**: Before signaling done, you MUST complete this checklist.
The Witness will verify each item and bounce you back if dirty.

### Pre-Done Verification

```bash
# 1. Git status - must be clean
git status
# Expected: "nothing to commit, working tree clean"

# 2. Stash list - must be empty
git stash list
# Expected: (empty output)

# 3. Beads sync - must be up to date
bd sync --status
# Expected: "Up to date" or "Nothing to sync"

# 4. Branch merged - your work must be on main
git log main --oneline -1
git log HEAD --oneline -1
# Expected: Same commit
```

### If Any Check Fails

- **Uncommitted changes**: Commit them or discard if unnecessary
- **Stashes**: Pop and commit, or drop if obsolete
- **Beads out of sync**: Run `bd sync`
- **Branch not merged**: Complete the merge workflow

### Signaling Done

Only after ALL checks pass:

```bash
bd close <issue-id>
bd sync
town mail send <rig>/witness -s "Work Complete" -m "Issue <id> done."
```
```

## Implementation

Add to AGENTS.md.template in the polecat prompting section.


Digest: mol-deacon-patrol

Patrol cycle 19: All agents healthy


Digest: mol-deacon-patrol

Cycle 185: Nominal


gt spawn: add --polecat flag for explicit worker selection

Currently gt spawn requires positional arg format:
```
gt spawn gastown/Angharad --issue gt-xyz
```

But I tried the more intuitive flag form:
```
gt spawn --issue gt-xyz --polecat Angharad
```

This failed with 'unknown flag: --polecat'.

The flag form is more discoverable and consistent with other commands. Add --polecat flag as alternative to positional arg.


Merge: slit-mjtj9dc8

branch: polecat/slit-mjtj9dc8
target: main
source_issue: slit-mjtj9dc8
rig: gastown


Digest: mol-deacon-patrol

Patrol cycle 5: all healthy


Digest: mol-deacon-patrol

Patrol 5: all clear


BUG: Boot spawns in wrong session (gt-deacon instead of gt-deacon-boot)

## Problem

Boot (the Deacon's watchdog) is supposed to spawn in its own session `gt-deacon-boot` per the code:
```go
const SessionName = "gt-deacon-boot"
```

But when checking tmux, Boot appears to be running in the `gt-deacon` session with cwd `dogs/boot`.

## Evidence

```
$ tmux capture-pane -t gt-deacon -p
⏺ Bash(cd /Users/stevey/gt/deacon && gt feed --since 10m --plain 2>/dev/null)
  Shell cwd was reset to /Users/stevey/gt/deacon/dogs/boot
```

## Impact

- `gt status` shows Deacon as "stopped" when Boot is running in its session
- Boot and Deacon lifecycle are confused
- Daemon's two-layer approach (Boot triage + Deacon heartbeat) doesn't work correctly

## Expected Behavior

1. Boot spawns in `gt-deacon-boot` session
2. Boot runs triage, decides if Deacon needs starting
3. If yes, Boot starts Deacon in `gt-deacon` session
4. Both sessions can coexist: Boot (ephemeral triage) and Deacon (persistent patrol)

## Investigation Needed

- Check `boot.spawnTmux()` - is it creating the right session name?
- Check if something is reusing the Deacon session for Boot
- Verify session naming throughout the daemon/boot code


Digest: mol-deacon-patrol

P15: stable


Create Refinery role template

Add Refinery template to internal/templates/roles/:
- refinery.md.tmpl with full role context
- Variables: rig name, working directory, handoff bead ID
- Update SeedRoleTemplates to include it
- gt prime uses this template for Refinery context


Polecat spawn: CLAUDE.md template lookup path is wrong

Template lookup uses rig.Path/templates/ but templates are in mayor/rig/templates/

In internal/polecat/manager.go installCLAUDETemplate():
  templatePath := filepath.Join(m.rig.Path, "templates", "polecat-CLAUDE.md")
  // Looks for: /Users/stevey/gt/gastown/templates/polecat-CLAUDE.md
  // But templates are at: /Users/stevey/gt/gastown/mayor/rig/templates/

This causes silent failure (template not found is OK) and polecats inherit the wrong CLAUDE.md from the git worktree.

Fix options:
1. Copy templates to rig root during rig init
2. Change lookup to use mayor/rig/templates/
3. Embed templates in binary


Ephemeral Polecat Merge Workflow: Rebase-as-Work Architecture

## Vision

Polecats are truly ephemeral: done at MR submission, recyclable immediately. Conflict resolution becomes tracked work in the ledger.

## Current State

- Polecats submit MRs and wait around
- Refinery sends 'rebase needed' mail back to polecats
- Polecats are blocked on MQ throughput
- No priority scheduling in MQ

## Target State

### Polecat Lifecycle
```
Polecat spawns → Does feature work → Submits MR → DONE (recyclable)
```

### Refinery Workflow
```
MR enters queue
    ↓
Priority scoring (convoy age, epic priority, retry count)
    ↓
Attempt mechanical rebase
    ├─→ Success: Run tests, merge
    └─→ Conflicts: Create conflict-resolution task, skip MR
```

### Conflict Resolution
- New bead: 'Resolve conflicts for MR gt-xxx'
- Dispatched to any available polecat
- Fresh polecat: clone, read MR/issue, resolve, force-push
- MR re-enters queue with priority boost

## Priority Objective Function

```go
score := baseScore
score += convoyAgeFactor * hoursOld(convoy)
score += epicPriorityFactor * (5 - epicPriority)  // P0=5pts, P4=1pt
score += retryPenalty * conflictRetryCount        // Prevent thrashing
```

Factors tunable. Refinery processes highest-score first.

## Key Principles

- **ZFC**: Refinery automates automatable, agents judge judgeable
- **Nondeterministic Idempotence**: Different polecat, same outcome
- **HOP-aligned**: Conflict resolution is tracked work with skill attribution
- **Convoy pressure**: Older convoys get priority, preventing starvation

## Success Criteria

- [ ] Polecats recyclable immediately after MR submit
- [ ] Mechanical rebases handled by refinery (no dispatch)
- [ ] Conflicts create dispatchable tasks
- [ ] MQ priority based on convoy/epic/retry
- [ ] Documentation updated
- [ ] Formulas updated (refinery, polecat)


Design: MQ Priority Objective Function

Define the priority scoring function for merge queue ordering.

## Inputs
- Convoy creation time (age)
- Epic/issue priority (P0-P4)
- Conflict retry count
- MR submission time

## Output
- Numeric score (higher = process first)

## Considerations
- Prevent convoy starvation (old convoys escalate)
- Respect epic priority (P0 bugs > P4 backlog)
- Penalize thrashing (multiple conflict cycles)
- Deterministic (same inputs = same score)

## Deliverable
- Go function: `func ScoreMR(mr MergeRequest) float64`
- Unit tests with edge cases
- Documentation of factor weights


Testing: End-to-end rebase workflow validation

Comprehensive testing of the new rebase-as-work workflow.

## Test Scenarios

### Happy Path
1. Single MR, clean rebase → refinery merges
2. Multiple MRs, no conflicts → priority ordering works

### Conflict Handling
3. MR conflicts → conflict task created
4. Conflict task dispatched → polecat resolves
5. Resolved MR re-enters queue with priority boost
6. Multiple conflict cycles → retry_count tracked

### Priority Scoring
7. Older convoy MRs prioritized over newer
8. P1 epic MRs prioritized over P3
9. High retry_count gets appropriate adjustment

### Edge Cases
10. MR conflicts again after resolution
11. Polecat recycled before merge
12. Convoy completed with pending MRs

## Implementation
- Unit tests for ScoreMR function
- Integration tests for refinery flow
- Scenario tests with actual polecats (manual/semi-auto)


Refinery: Implement mechanical rebase in-place

Update refinery to handle mechanical rebases without dispatching.

## Current Behavior
- Refinery detects rebase needed
- Sends mail to polecat asking for rebase
- Waits for polecat response

## New Behavior
- Refinery attempts `git rebase origin/main`
- If success (no conflicts): proceed to tests/merge
- If conflicts: abort, create conflict-resolution task

## Implementation
1. Update mol-refinery-patrol.formula.toml
2. Add rebase step between 'fetch' and 'test'
3. Handle conflict detection (exit code, conflict markers)
4. On conflict: `git rebase --abort`, create task, skip MR

## Tests
- Mechanical rebase succeeds
- Conflict detected and aborted
- Conflict task created with correct metadata


Refinery: Conflict-resolution task creation

When rebase fails, create a dispatchable task for conflict resolution.

## Task Format
```
Title: Resolve merge conflicts: <original-issue-title>
Type: task
Priority: inherit from original + boost
Parent: original MR bead
Description:
  - Original MR: gt-xxx
  - Branch: polecat/foo-branch
  - Conflict with: main@<sha>
  - Original issue: gt-yyy
  - Instructions: Resolve conflicts, force-push, close this task
```

## Metadata
- Link to original MR
- Link to original issue
- Conflict SHA (what main was when conflict occurred)
- Retry count (for priority scoring)

## Dispatch
- Task goes to bd ready
- Witness can dispatch to available polecat
- Or: Refinery directly dispatches if polecats available


Polecat: Clean exit after MR submission

Update polecat workflow to be truly ephemeral after MR submission.

## Current Behavior
- Polecat submits MR
- Polecat waits for merge or rebase request
- Session stays alive, sandbox persists

## New Behavior
- Polecat submits MR
- Polecat closes its work bead (status=in_review or similar)
- Polecat signals 'recyclable' to Witness
- Sandbox can be cleaned up after branch is pushed

## Implementation
1. Update mol-polecat-work.formula.toml
2. Add explicit 'submit and exit' step
3. Ensure branch is pushed before sandbox cleanup
4. Signal Witness that polecat is recyclable

## Considerations
- Sandbox cleanup can be deferred (worktrees are cheap)
- Or: Witness runs cleanup patrol for idle polecats

Implemented: Updated mol-polecat-work.formula.toml (v4) for ephemeral polecat model. Polecats now submit via gt done and become recyclable. No longer wait for Witness termination or close their own issues.


Polecat: Conflict resolution workflow

New workflow for polecats handling conflict-resolution tasks.

## Task Recognition
- Task title starts with "Resolve merge conflicts:"
- Task has metadata: original MR, branch, conflict SHA

## Workflow (UPDATED - uses merge-slot)
1. Read task metadata
2. **Acquire merge slot** (gt-4u49x) - wait if held
3. Fetch the branch: `git fetch origin <branch>`
4. Checkout: `git checkout -b temp-resolve origin/<branch>`
5. Attempt rebase: `git rebase origin/main`
6. Resolve conflicts (Claude judgment)
7. Run tests
8. **Push directly to main** (not force-push to branch)
9. Close original MR bead (not just conflict task)
10. **Release merge slot**
11. Close conflict-resolution task

## Key Changes from Original
- Acquire/release merge slot (serialization)
- Push to main directly (skip queue re-entry)
- Close original MR bead (proper attribution)

## Considerations
- May need to read original issue for context
- May need to read MR description for intent
- If resolution is complex, can ask for human help (escalate)

## Dependencies
- gt-4u49x: Merge-slot gate (serialization)
- gt-hibbj: Non-blocking refinery delegation


gt mq: Priority-ordered queue display and processing

Update MQ commands and refinery to process by priority score.

## Changes to gt mq list
- Add 'SCORE' column
- Sort by score descending
- Show convoy info if tracked

## Changes to gt mq next
- Return highest-score MR (not oldest)
- Or: `gt mq next --strategy=priority` (keep fifo as option)

## Changes to Refinery
- Query MQ with priority ordering
- Process highest-score first

## Implementation
- Add ScoreMR function (from gt-si8rq.1)
- Update mq.go query to include score calculation
- Update refinery formula to use priority ordering

## Output Example
```
ID         SCORE  PRI  CONVOY        BRANCH                AGE
gt-abc     87.5   P1   hq-cv-xyz     polecat/foo-123       2h
gt-def     72.3   P2   hq-cv-abc     polecat/bar-456       45m
gt-ghi     45.0   P3   (none)        polecat/baz-789       10m
```


MR bead: Add retry_count and conflict metadata

Extend MR beads to track conflict resolution attempts.

## New Fields
- `retry_count`: Number of conflict-resolution cycles
- `last_conflict_sha`: SHA of main when conflict occurred
- `conflict_task_id`: Link to conflict-resolution task (if any)

## Usage
- Refinery increments retry_count on each conflict
- Priority function uses retry_count as input
- Conflict-resolution task links back to MR

## Implementation
- Update MR creation to include fields
- Update refinery to increment on conflict
- Update priority function to read retry_count


Documentation: Ephemeral Polecat Merge Workflow

Document the new rebase-as-work architecture.

## Documents to Update

### docs/understanding-gas-town.md
- Polecat lifecycle (truly ephemeral)
- MR submission as exit point

### docs/refinery-workflow.md (new or update)
- Priority scoring
- Mechanical rebase handling
- Conflict-resolution task creation

### PRIMING.md
- Update polecat section
- Add note about rebase-as-work pattern

## Key Concepts to Document
- 'Polecat done at MR submit'
- 'Conflicts are new work'
- 'Convoy age creates pressure'
- 'Priority function is deterministic'


Witness: Update polecat monitoring for ephemeral model

Update Witness to handle truly ephemeral polecats.

## Current Behavior
- Witness monitors polecats until MR merged
- 'Rebase needed' mail sent to polecats

## New Behavior
- Witness marks polecat as 'recyclable' after MR submit
- Witness can dispatch conflict-resolution tasks
- Witness doesn't wait for merge to recycle polecat

## Changes to mol-witness-patrol.formula.toml
- Detect 'MR submitted' state
- Mark polecat recyclable
- Handle conflict-resolution dispatch

## Polecat States
```
spawning → working → mr_submitted → recyclable → recycled
```

## Considerations
- Don't recycle sandbox until branch pushed
- Or: Keep sandbox, just recycle session


gt feed --follow: Town-level activity stream

Town-native command for aggregated activity feed.

Wraps bd activity --town with Gas Town conveniences:
- gt feed --follow         # Stream all rig activity
- gt feed --rig gastown    # Filter to specific rig
- gt feed --convoy hq-xxx  # Filter to convoy's tracked issues

Essential for Mayor/Deacon visibility into cross-rig work.

Depends on: bd-dx6e (bd activity --town)
Related: hq-7h8jx (Convoy System epic in town beads)


Digest: mol-deacon-patrol

Patrol cycle 4: All agents healthy


GT_ROLE env var not set correctly for crew workers


Digest: mol-deacon-patrol

Patrol 16: Quiet


Digest: mol-deacon-patrol

Patrol 10: 17 sessions


Digest: mol-deacon-patrol

Patrol 33: all quiet


Digest: mol-deacon-patrol

Patrol 9: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol cycle 20: final before handoff


Fix TestHasPolecat test failure


Digest: mol-deacon-patrol

Patrol 5: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 8: routine, all healthy


Digest: mol-deacon-patrol

Cycle 10: quiet


Digest: mol-deacon-patrol

Patrol #11


Digest: mol-deacon-patrol

Patrol cycle 16: All healthy


Digest: mol-deacon-patrol

Patrol #18


Merge: rictus-1767081110235

branch: polecat/rictus-1767081110235
target: main
source_issue: rictus-1767081110235
rig: gastown


Digest: mol-deacon-patrol

Patrol 1: All healthy, no messages, no orphans


Fix docs: Formulas are JSON not YAML

The molecular chemistry docs (molecule-algebra.md, molecular-chemistry.md) incorrectly refer to formulas as YAML. Formulas are JSON (.formula.json). Fix all references: .formula.yaml -> .formula.json, 'YAML files' -> 'JSON files', 'formula YAML' -> 'formula JSON', code blocks from yaml to json syntax.


BUG: gt handoff --dry-run still sends mail

In handoff.go, the dry-run check happens AFTER sendHandoffMail() is called. This means --dry-run still sends mail.

**Location**: handoff.go L126-143

**Observed**: Testing with `gt handoff --dry-run -s 'Test' -m 'Message'` actually sent mail to mayor.

**Fix**: Move mail sending inside the non-dry-run block, or check dry-run first.

```go
// Current (buggy):
if handoffSubject \!= "" || handoffMessage \!= "" {
    sendHandoffMail(...)  // Executes even in dry-run\!
}
if handoffDryRun {        // Too late
    return nil
}

// Should be:
if handoffDryRun {
    // show what would happen
    return nil
}
// Then send mail
```


Digest: mol-deacon-patrol

Patrol 9: quick pass


Digest: mol-deacon-patrol

Patrol cycle 4: routine check, all nominal


gt session restart/status: Complete session management

Add missing session subcommands:

- gt session restart <rig> <polecat> - Restart a session (stop + start)
- gt session status <rig> <polecat> - Show session status details

status should show:
- Running state
- Uptime
- Current activity
- Last output timestamp


Test merge request

branch: polecat/Test/gt-test
target: main
source_issue: gt-test
worker: TestWorker
rig: gastown


Exponential backoff for idle patrol agents

## Problem

Patrol agents (Refinery, Witness, Deacon) currently have no backoff when their queue is empty. They either:
- Loop immediately (wasting cycles)
- Exit and wait for 10-minute daemon respawn (too slow to respond)

## Solution: Feed-Driven Backoff

### The Pattern (from PRIMING.md)

> "Backoff isn't about polling less - it's about **waiting for signals with a timeout**."

Agents subscribe to `bd activity --follow` and wake on any beads mutation. The timeout increases exponentially during idle periods.

### Data Flow

```
bd/gt mutations → .events.jsonl → feed curator → .feed.jsonl
                                                      ↓
                    patrol agent: gt mol await-signal --backoff-*
                                                      ↓
                              signal → wake, reset idle_cycles
                              timeout → increment idle_cycles, sleep longer
```

### Backoff Formula

```
timeout = min(base × multiplier^idle_cycles, max)
```

| Idle Cycles | Timeout |
|-------------|---------|
| 0 | 30s |
| 1 | 1m |
| 2 | 2m |
| 3 | 4m |
| 4+ | 5m (capped) |

### Agent State Storage

Operational state stored as labels on agent beads (labels-as-cache pattern):
- `idle:3` - consecutive idle patrol cycles
- `backoff:2m` - current backoff interval (derived)
- `last_activity:2025-12-31T10:00:00Z` - timestamp

### Implementation Layers

**Layer 1: gt agent state command**
```bash
gt agent state <agent-bead>                    # Get labels
gt agent state <agent-bead> --set idle=0       # Set label
gt agent state <agent-bead> --incr idle        # Increment
```

**Layer 2: Fix await-signal iteration tracking**
- Read `idle:N` label from agent bead
- Calculate effective timeout using BackoffConfig
- On timeout: increment label, return "timeout"
- On signal: return "signal" (agent resets)

**Layer 3: Patrol formula integration**
Update burn-or-loop step:
```bash
# If work found
gt agent state $AGENT_BEAD --set idle=0

# If no work
gt mol await-signal --agent-bead $AGENT_BEAD   --backoff-base 30s --backoff-mult 2 --backoff-max 5m

# After 10 consecutive max-timeout cycles, exit for fresh session
```

**Layer 4: Feed signal sources**
Ensure these emit events:
- gt sling → TypeSling
- bd create/update/close → BeadMutation
- gt mail send → TypeMail

### ZFC Compliance

| Component | Role | ZFC |
|-----------|------|-----|
| Feed curator | Aggregates events | ✅ Transport |
| await-signal | Waits with timeout | ✅ Transport |
| Agent bead labels | Stores idle_cycles | ✅ Agent-written |
| Backoff decision | Agent decides | ✅ Agent decides |

Go code provides mechanics. **Agent decides** parameters, reset, and exit.

### Existing Infrastructure

- Feed Curator: internal/feed/curator.go ✅
- BackoffConfig: internal/beads/molecule.go ✅
- await-signal cmd: internal/cmd/molecule_await_signal.go (needs fix)
- Agent Beads: internal/beads/beads.go ✅
- Labels pattern: docs/operational-state.md ✅

### Exit Strategy

After N consecutive max-interval cycles (e.g., 10 × 5m = 50 minutes idle):
- Agent exits cleanly
- Daemon respawns fresh session
- Fresh session starts with idle:0


Implement gt agent state command for label-based state

Add gt agent state command:
- gt agent state <agent-bead> - Get all labels
- gt agent state <agent-bead> --set key=value - Set label
- gt agent state <agent-bead> --incr key - Increment numeric label
- gt agent state <agent-bead> --del key - Delete label

Labels stored on agent beads enable operational state (idle:N, backoff:2m, etc).


Update patrol formulas to use await-signal backoff

Layer 3: Update patrol formulas to use new gt mol await-signal with --agent-bead flag.

Update burn-or-loop steps in patrol formulas:
- mol-witness-patrol.formula.toml
- mol-refinery-patrol.formula.toml
- mol-deacon-patrol.formula.toml

The step should:
1. Reset idle counter on work found: gt agent state $AGENT_BEAD --set idle=0
2. Wait with backoff when no work: gt mol await-signal --agent-bead $AGENT_BEAD --backoff-base 30s --backoff-mult 2 --backoff-max 5m
3. Exit after 10 consecutive max-timeout cycles for fresh session


Verify feed signal sources emit events

Layer 4: Verify that all required sources emit events to the activity feed.

Sources that should emit events:
- gt sling → TypeSling event
- bd create/update/close → BeadMutation event
- gt mail send → TypeMail event

Check internal/events package and verify event emission in each command.


Digest: mol-deacon-patrol

Patrol 130: All healthy


Digest: mol-deacon-patrol

Patrol 10


Digest: mol-deacon-patrol

Patrol cycle 7: All quiet.


Deacon patrol molecules stored in wrong beads location

outputDeaconPatrolContext in prime.go hardcodes 'gastown/mayor/rig' (line 691) to find patrol molecules. But Deacon is a town-level role, not a rig role. Deacon molecules should be in town root beads (~/gt/.beads/) not rig beads. This also affects gt mol status which uses findLocalBeadsDir() - from ~/gt/deacon/ it won't find the right beads location.


gt spawn beads sync warning is misleading for redirect-based polecats

## Problem

When spawning a polecat, gt spawn shows a warning:
```
Warning: beads sync: exit status 1
```

This is misleading because polecats using the redirect architecture (`.beads/redirect`) share the canonical database at `mayor/rig/.beads/beads.db`. The 'stale beads' indicated by the warning is just git branch divergence (main vs beads-sync), not actual data staleness.

## Expected Behavior

gt spawn should either:
1. Skip the beads sync check for polecats using redirects (they share the canonical DB)
2. Or provide a clearer message like 'beads redirect active, using shared database'

## Reproduction

```bash
gt spawn --issue gt-xxx --rig gastown --create
# Shows 'Warning: beads sync: exit status 1' even though beads are current
```

## Root Cause

spawn.go calls beads sync and treats any non-zero exit as a warning. But with redirects, the polecat doesn't need its own beads - it uses the canonical source via the redirect chain:
```
polecat/.beads/redirect -> ../../.beads -> gastown/.beads/redirect -> mayor/rig/.beads
```

## Fix Options

1. Check for .beads/redirect before calling sync
2. Have bd sync return 0 when redirect is present
3. Suppress the warning in spawn when redirect exists


check-refinery

Ensure the refinery is alive and processing merge requests.

Needs: inbox-check


Digest: mol-deacon-patrol

Patrol 18: All clear


Atomic gt done: all-or-nothing work submission

gt done performs multiple operations that can partially fail.

## Current Flow (non-atomic)
1. Create MR bead ← can fail
2. Send POLECAT_DONE mail ← can fail
3. Update agent bead state ← can fail
4. Report cleanup status ← can fail

If session dies mid-execution, state is inconsistent.

## Fix Options

### Option A: Retry on restart
- Write intent file before starting
- On polecat restart, check for incomplete gt done
- Resume/retry from where it left off

### Option B: Single-write submission
- Create a single 'submission' bead that contains all info
- Witness unpacks it into MR bead + cleanup wisp
- Polecat only needs one successful write

### Option C: Idempotent operations
- Each step checks if already done before doing
- Safe to re-run gt done multiple times

Recommend Option C for simplicity.


Implement gt mq CLI commands

Add gt mq subcommands as sugar over bd:

- gt mq submit: Create MR for current branch
- gt mq list: Show open merge requests
- gt mq next: Show next MR ready to process
- gt mq process: Engineer processes the queue
- gt mq reorder <id> --after <x>: Change ordering via deps
- gt mq status <id>: Show MR details

All commands should work with the Beads data plane.


gt mq submit: create MR from current branch

Implement 'gt mq submit' command that creates a merge-request bead.

Auto-detection logic:
1. Branch: current git branch
2. Issue: parse from branch name (polecat/Nux/gt-xyz → gt-xyz)
3. Target: main (or integration branch if --epic specified)
4. Worker: parse from branch name
5. Rig: current rig

Options:
- --branch BRANCH: explicit source branch
- --issue ISSUE: explicit source issue
- --epic EPIC: target integration/EPIC instead of main
- --priority P: override priority (default: inherit from source issue)

Creates merge-request bead and prints MR ID.

Reference: docs/merge-queue-design.md#creating-merge-requests


gt mq list: show queue with status/priority/age

Implement 'gt mq list' command to display the merge queue.

Output format:
ID          STATUS       PRIORITY  BRANCH                    WORKER  AGE
gt-mr-001   ready        P0        polecat/Nux/gt-xyz        Nux     5m
gt-mr-002   in_progress  P1        polecat/Toast/gt-abc      Toast   12m
gt-mr-003   blocked      P1        polecat/Capable/gt-def    Capable 8m
            (waiting on gt-mr-001)

Options:
- --ready: show only ready-to-merge (no blockers, not in progress)
- --status STATUS: filter by status
- --worker WORKER: filter by worker
- --epic EPIC: show MRs targeting integration/EPIC

Under the hood: bd list --type=merge-request with filters.

Reference: docs/merge-queue-design.md#gt-mq-list


gt mq status: detailed MR view

Implement 'gt mq status <id>' command for detailed MR view.

Display:
- All MR fields (branch, target, source_issue, worker, rig)
- Current status with timestamps
- Dependencies (what it's waiting on)
- Blockers (what's waiting on it)
- Processing history (attempts, failures)

Under the hood: bd show <id> with MR-specific formatting.

Reference: docs/merge-queue-design.md#command-details


gt mq retry: retry a failed MR

Implement 'gt mq retry <id>' to retry a failed merge request.

Actions:
1. Verify MR exists and is in failed state (open with failure labels)
2. Remove failure labels (needs-rebase, needs-fix)
3. Reset to ready state
4. Optionally re-run immediately (--now flag)

Options:
- --now: immediately process (instead of waiting for Engineer loop)

Reference: docs/merge-queue-design.md#cli-commands


gt mq reject: manual MR rejection

Implement 'gt mq reject <id> --reason "..."' for manual rejection.

Actions:
1. Verify MR exists and is open
2. Close MR with close_reason=rejected
3. Notify worker via mail (optional)
4. Do NOT close source issue (work not done)

Options:
- --reason REASON: required explanation
- --notify: send mail to worker

Reference: docs/merge-queue-design.md#cli-commands


Digest: mol-deacon-patrol

Patrol 3: inbox clear, all healthy


Merge: cheedo-1767088553821

branch: polecat/cheedo-1767088553821
target: main
source_issue: cheedo-1767088553821
rig: gastown


Digest: mol-deacon-patrol

Patrol 124: All healthy, 2 new polecats


Digest: mol-deacon-patrol

P20: stable - handoff triggered


Digest: mol-deacon-patrol

Patrol 17


Merge: gt-3x0z.4

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


Digest: mol-deacon-patrol

Patrol cycle 76: All healthy


ZFC #5: Move merge/conflict decisions from Go to Refinery agent

**ZFC Violation:** internal/refinery/manager.go:389-517

Go code currently makes engineering decisions in ProcessMR():
- Detect conflicts via string matching
- Decide to abort merge
- Decide to roll back on test failure
- Decide retry strategy

**Current anti-pattern:**
```go
if strings.Contains(errStr, "CONFLICT") {
    result.Conflict = true
    _ = m.gitRun("merge", "--abort")
    // Go decides what to do
}
```

**ZFC-compliant solution:**
Refinery AGENT runs the merge loop:
- Agent attempts merge
- Agent detects conflict and decides: retry, notify polecat, escalate
- Agent runs tests and decides: proceed, rollback, retry
- Go provides git operations, agent makes decisions

**Relates to:** Day 3.4 (Refinery processes MERGE_READY mail) but needs explicit agent decision-making

Reference: ~/gt/docs/zfc-violations-audit.md #5


Merge: dementus-1767073385126

attached_args: Code review this merge request

branch: polecat/dementus-1767073385126
target: main
source_issue: dementus-1767073385126
rig: gastown


Mayor startup protocol prompting

Add startup protocol to Mayor CLAUDE.md template.

## On Session Start

1. Check for handoff:
   town inbox | grep "Session Handoff"

2. If handoff found:
   - Read it: town read <msg-id>
   - Process pending escalations (highest priority)
   - Check status of noted swarms
   - Verify rig health matches notes
   - Continue with documented next steps

3. If no handoff:
   town status     # Overall health
   town rigs       # Each rig
   bd ready        # Work items
   town inbox      # Any messages
   Build your own picture of current state.

4. After processing handoff:
   - Archive or delete the handoff message
   - You now own the current state

## Handoff Best Practices

- Be specific: 'Toast has merge conflict in auth/middleware.go' not 'Toast is stuck'
- Include context: Why decisions are pending, what you were thinking
- Prioritize next steps: What is most urgent
- Note time-sensitive items: Anything that might have changed since handoff


Digest: mol-deacon-patrol

Patrol 241 complete: 3 witnesses, 3 refineries healthy; 6 polecats active; 1 dog idle; no orphans; no incidents


gt spawn --create should auto-add polecat if missing

## Problem

`gt spawn gastown --issue gt-xxx --create` fails if no polecats exist.

## Current Behavior

```
Error: auto-select polecat: no available polecats in rig 'gastown'
```

## Expected Behavior

`--create` should:
1. Create a new polecat if none exist
2. Or create the specified polecat if `gt spawn gastown/NewName --create`

## Workaround

Must manually run `gt polecat add gastown Name` first.

## Principle

Agent UX should be forgiving - if I say spawn with --create, make it work.


Merge: nux-1767084010093

branch: polecat/nux-1767084010093
target: main
source_issue: nux-1767084010093
rig: gastown


Digest: mol-deacon-patrol

Patrol 17: all healthy


Add gt mail claim command for queue message claiming

Add claim subcommand to internal/cmd/mail.go.

SYNTAX:
gt mail claim <queue-name>

BEHAVIOR:
1. List unclaimed messages in queue (claimed_by empty)
2. Pick oldest unclaimed message
3. Set claimed_by to caller identity
4. Set claimed_at to now
5. Print claimed message details

ELIGIBILITY CHECK:
- Load queue config from messaging.json
- Check if caller matches any pattern in workers list
- Reject if not eligible

FILE: internal/cmd/mail.go
ADD: claimCmd as subcommand of mailCmd

TESTS: Add TestMailClaim in mail_test.go or cmd_test.go


gt nudge: support no-arg invocation with default message

Currently gt nudge requires a message argument:

```
gt nudge <rig/polecat> <message>
```

Would be nice to support:
```
gt nudge <rig/polecat>
```

With a sensible default message like 'nudge' or 'continue' or checking for pending work automatically.


Digest: mol-deacon-patrol

Patrol 12: Nominal


Merge: gt-8v8

branch: polecat/nux
target: main
source_issue: gt-8v8
rig: gastown


Beads witness sends HEALTH_OK to mayor instead of deacon

The beads/witness is responding to deacon health checks by sending to 'mayor/deacon' or 'mayor/' instead of 'deacon/'.

Current behavior:
gt mail send mayor/deacon -s "HEALTH_OK" ...

Expected behavior:
gt mail send deacon/ -s "HEALTH_OK" ...

The gastown witness was fixed and now correctly sends to deacon/. The beads witness needs the same fix.


Digest: mol-deacon-patrol

Patrol 2: 1 mail archived, all agents healthy, 1 orphan fixed


Digest: mol-deacon-patrol

Patrol 16: Routine


Add INSTALLING.md with full setup guide

README Quick Start is too brief. Create docs/INSTALLING.md with:
1. All prerequisites with install commands
2. Step-by-step install for macOS and Linux
3. Verification steps (gt doctor, gt status)
4. Troubleshooting common issues
5. Minimal mode vs full-stack mode setup


Refinery Patrol

Merge queue processor patrol loop with verification gates.


Hardcoded session ID prefixes and paths

Multiple hardcoded values throughout code:
- internal/mail/router.go: 'gt-mayor', 'gt-' session prefixes
- internal/lock/lock.go: '.runtime', 'agent.lock' paths
- Session ID generation uses string literals

Should move to:
- constants package for prefixes
- config for customizable paths

Low priority but improves maintainability.


test with labels


Deacon trigger-pending-spawns: Auto-nudge polecats when ready

The Deacon's mol-deacon-patrol defines a trigger-pending-spawns step, but it's not implemented.

## Problem
After gt spawn creates a polecat session, Claude initializes for 10-20s. Nobody sends the initial 'Begin.' message to start work, so polecats sit at prompts forever.

## Current Workaround
Manual: gt nudge gt-<rig>-<polecat> 'Begin.'

## Required Implementation
1. Track pending spawns (polecats spawned but not triggered)
2. In Deacon patrol, poll WaitForClaudeReady for each pending spawn
3. When ready, send 'Begin.' via NudgeSession
4. Mark as triggered

## Evidence
Tracer bullet 2025-12-23: Had to manually nudge polecat/tracer to start work.


Design: Polecat lifecycle and patrol coordination

## Context

This design captures thinking from a deep session about the Gas Town propulsion system - how Deacon, Witness, Refinery, and Polecats coordinate to move work smoothly through the system.

## Core Insight: Session-Per-Step Model

Polecats do NOT complete complex molecules end-to-end. Instead:
- One polecat SESSION per molecule STEP
- Same sandbox (branch/worktree) persists across sessions
- Each step: spawn → work → close bead → recycle session
- Final step: spawn → work → close bead → signal complete → merge → nuke sandbox

## Two Cleanup Stages

| Stage | Trigger | Kills | Survives |
|-------|---------|-------|----------|
| Step cleanup | Step bead closed | Session | Branch, worktree, molecule |
| Molecule cleanup | Merged | Session, branch, worktree | Digest |

## Per-Rig Polecat Channel

Need a mailing list/queue per rig for session-lifecycle requests:
- "Recycle me" (from polecat)
- "Recycle worker X" (from witness/mayor)
- "Spawn for step Y" (from anyone)

First-come-first-served by patrolling agents. Anyone on patrol (Witness, Refinery, Crew, Mayor) can service requests.

## GUPP + Pinned Work = Completion

As long as:
1. Work is pinned to polecat identity (e.g., gastown/furiosa)
2. Sandbox persists (branch + worktree)
3. Someone keeps spawning polecat when it dies

→ The molecule WILL get finished. GUPP ensures wake-and-work.

## Daemon → Deacon Heartbeat

The daemon pings the deacon, keeping the cycle alive. Deacon peeks into rig-wide channels during patrol and can service lifecycle requests.

## Open Design Questions

### Q1: Spoon-Feeding Bin-Packing
Two dimensions of granularity trade-offs:
- How many logical steps per physical molecule step?
- How many molecule steps per polecat session?

Too few steps → context exhaustion, forgetting
Too many steps → overhead, fragmentation

Needs: Analysis of optimal granularity based on step complexity.

### Q2: Mechanical vs Agent-Driven Recycling
Caution from deacon murder spree bug: mechanical detection of "stuck" workers is fragile.

Prefer: Explicit "recycle me" requests serviced by patrol agents.

Question: When is mechanical intervention appropriate?

### Q3: Channel Implementation
Options:
- Mail-based (gt mail to rig/polecats)
- Beads-based (special issue type)
- State file (rig/polecat-queue.json)

Mail seems most consistent with Gas Town patterns.

### Q4: Who Spawns Next Step?
Current: gt sling spawns fresh polecat
Needed: Mechanism for "continue molecule on existing sandbox"

Maybe: gt sling --continue or witness detects pending step.

## Related Issues

- gt-dtw9u: Witness monitoring (enhance survey-workers)
- gt-qpwv4: Completion detection (check ready branches)
- gt-6qyt1: Refinery queue (process MERGE_READY)
- gt-budeb: Auto-nuke (handle MERGED signal)
- gt-5j3ia: Swarm aggregation (batch completion)
- gt-1dbcp: Polecat auto-start (SessionStart hook issue)

## Design Principles (from HOP/MEOW context)

1. **Discovery over tracking** - observe reality each cycle
2. **Mail as coordination primitive** - agents signal via mail
3. **ZFC** - Claude makes judgment calls, no hardcoded thresholds
4. **Redundant monitoring** - overlapping observation is resilience
5. **Wisps are ephemeral** - patrol molecules flow like water

## Next Steps

1. Finalize channel design (mail-based queue)
2. Enhance witness patrol formula with completion detection
3. Enhance refinery patrol with MERGED signaling
4. Implement step-level recycling
5. Design spoon-feeding granularity guidelines


Digest: mol-deacon-patrol

Patrol 2: inbox clear, all agents healthy


ZFC #4: Replace daemon identity parsing with agent self-registration

**ZFC Violation:** internal/daemon/lifecycle.go:209-309

The daemon has embedded switch statements that parse agent identity strings to determine:
- Session names
- Working directories
- Which agents need pre-sync
- Restart commands

**Current anti-pattern:**
```go
if strings.HasSuffix(identity, "-refinery") {
    needsPreSync = true
    workDir = filepath.Join(...)
}
```

**ZFC-compliant solution:**
Agent types self-register via role beads:
- Role bead contains: working_dir, session_name_pattern, needs_sync, restart_command
- Daemon reads role bead to get lifecycle config
- No identity string parsing in Go

**Depends on:** Day 1.5 (role beads exist)

Reference: ~/gt/docs/zfc-violations-audit.md #4


gt mol attach: Auto-detect agent from cwd when single arg provided

## Current Behavior

gt mol attach requires 2 args:
  gt mol attach <agent-bead-id> <molecule-id>

## Expected Behavior

When called with 1 arg from an agent working directory:
  gt mol attach <molecule-id>

Should auto-detect the agent from cwd (same detection used by gt mail, bd, etc.)
and attach the molecule to that agent hook.

## Example

From ~/gt/gastown/mayor/rig:
  gt mol attach gt-y14l7
  -> detects mayor role
  -> attaches gt-y14l7 to gt-mayor hook

## Implementation

1. Check arg count
2. If 1 arg, call role detection from cwd
3. Resolve agent bead ID from role (gt-mayor, gt-witness-gastown, etc.)
4. Proceed with attachment

This makes the common case (attaching work to yourself) ergonomic.


Merge: cheedo-mjtmlvge

branch: polecat/cheedo-mjtmlvge
target: main
source_issue: cheedo-mjtmlvge
rig: gastown


Digest: mol-deacon-patrol

Patrol 20: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 20: All healthy, cycling session


gt mr: Add alias for merge request operations

Agent guessed `gt mr register <branch>` to submit a branch to the merge queue. The actual command is `gt mq submit`.

**Suggestion**: Add `gt mr` as an alias or subcommand for merge request workflows:
- `gt mr submit` → `gt mq submit`
- `gt mr status` → `gt mq status`
- `gt mr list` → `gt mq list`

**Why**: 'MR' (merge request) is the conceptual noun; 'mq' (merge queue) is the implementation detail. Agents and humans think in terms of 'I have a merge request' not 'I need to interact with the queue'.

**Alternative**: Just document `gt mq` more prominently, but aliases cost little and reduce friction.

Filed by: gastown/polecats/nux (agent UX feedback)


Digest: mol-deacon-patrol

Patrol 3: All nominal


Digest: mol-deacon-patrol

Patrol 9


Digest: mol-deacon-patrol

Patrol cycle 11: all healthy


Digest: mol-deacon-patrol

Patrol cycle 1: all healthy, 3 rigs, 6 agents, no incidents


Digest: mol-deacon-patrol

Patrol 6: All healthy.


Polecat template cleanup

Collection of improvements to the polecat role template (polecat.md.tmpl). Focus: reduce prose redundancy, move behavior into molecules, fix terminology, improve clarity.


Boot needs CLAUDE.md and directory setup

Boot spawns in ~/gt/deacon but:
1. No ~/gt/deacon/dogs/boot/ directory exists
2. Boot reads Deacon's CLAUDE.md (wrong role context)
3. spawnTmux() doesn't send initial triage prompt

Fix:
- Create ~/gt/deacon/dogs/boot/CLAUDE.md with Boot role instructions
- Update EnsureDir() to create directory on spawn
- Consider sending 'gt boot triage' as initial prompt

Boot should know it's a fresh-each-tick watchdog that:
- Observes Deacon state
- Decides: start/wake/nudge/nothing
- Cleans stale inbox
- Exits (never handoffs)


Digest: mol-deacon-patrol

Patrol 106: All healthy


Polecats should auto-cleanup after MR submission

Currently polecats must manually run 'gt handoff --shutdown' after completing work. This is error-prone and leaves stale polecats around.

## Desired Flow

1. Polecat completes work
2. Polecat runs 'gt mq submit' (or similar)
3. MR is added to integration queue
4. **Polecat automatically cleans up** (no manual handoff needed)

## Implementation Options

### Option A: mq submit triggers cleanup
In 'gt mq submit':
1. Submit MR to queue
2. Automatically run cleanup (same as gt handoff --shutdown)
3. Polecat session terminates

### Option B: Refinery triggers cleanup
When Refinery picks up MR:
1. Refinery processes MR
2. Sends message to Witness: 'CLEANUP: <polecat>'
3. Witness cleans up polecat

### Option C: Molecule-driven
Define cleanup as final phase of polecat-work molecule:
1. code → test → submit-mr → cleanup

## Note
This reinforces the ephemeral model: polecats exist only for the duration of a single task.


Digest: mol-deacon-patrol

Patrol 2: All healthy, routine


Find abandoned work

Find abandoned work.

Scan for orphaned state:
- Issues marked in_progress with no active polecat
- Polecats that stopped responding mid-work
- Merge queue entries with no polecat owner
- Wisp sessions that outlived their spawner

```bash
bd list --status=in_progress
gt polecats --all --orphan
```

For each orphan:
- Check if polecat session still exists
- If not, mark issue for reassignment or retry
- File incident beads if data loss occurred


Digest: mol-deacon-patrol

Patrol cycle 16


Digest: mol-deacon-patrol

Patrol #2: Routine - all 6 agents healthy


Digest: mol-deacon-patrol

Patrol #5: All systems nominal


@group dynamic resolution in mail router

## @group Dynamic Resolution in Mail Router

Wire agent bead queries into mail router for @group addresses.

## Updated Approach (post agent-as-bead + Dogs)

Agent discovery uses bead queries:

```bash
bd list --type=agent --rig=gastown         # All agents in rig
bd list --type=agent --role_type=witness   # All witnesses
bd list --type=agent --role_type=dog       # All dogs
```

## Supported Patterns

| Pattern | Resolution | Scope |
|---------|------------|-------|
| `@rig/gastown` | `--rig=gastown` | All gastown agents |
| `@town` | `--rig=""` (no filter) | All town-level agents |
| `@witnesses` | `--role_type=witness` | All witnesses across rigs |
| `@crew/gastown` | `--role_type=crew --rig=gastown` | Gastown crew |
| `@dogs` | `--role_type=dog` | All Deacon dogs |
| `@overseer` | Special case (not bead query) | Human operator |

## Deliverables

1. Parse @group syntax in router
2. Resolve via `bd list --type=agent` queries
3. Fan-out at send time (N copies, one per recipient)
4. Special handling for `@overseer` (single recipient, uses overseer.json)

## @overseer Special Case

The overseer is the human operator - NOT an agent bead. Resolution:
- Load `mayor/overseer.json`
- Use `overseer/` as recipient address
- No bead query needed

## Dependencies
- Agent bead schema (gt-ikyo1) ✅ closed
- Dog agent beads need role_type=dog (new prereq)

## Acceptance
- @rig/gastown sends to all gastown agents
- @dogs sends to all Deacon dogs
- @overseer sends to human operator
- Each recipient gets own message copy

Beads dependency: bd-jsk7 (Agent beads: structured labels for filtering)


Add agent abstraction layer to support non-Claude agents

Currently Gas Town hardcodes 'claude --dangerously-skip-permissions' throughout the codebase for spawning agents. We should add an abstraction layer to support other AI agents (e.g., Gemini CLI, OpenAI agents, local models).

Locations that spawn Claude:
- internal/cmd/mayor.go:131
- internal/cmd/deacon.go:150
- internal/cmd/witness.go:280
- internal/cmd/crew.go (multiple locations)
- internal/cmd/up.go:190, 229
- internal/session/manager.go:146
- internal/refinery/manager.go:207

Suggested approach:
1. Create an agent package with an interface
2. Add configuration for agent type in town/rig config
3. Replace hardcoded claude commands with agent.Spawn() calls
4. Support agents: claude, gemini, openai, local (ollama, etc.)