Standardize agent bead naming: prefix-rig-role-name

## The Problem

Agent bead IDs use INCONSISTENT naming patterns:

| Current (WRONG) | Should Be (prefix-rig-role-name) |
|-----------------|----------------------------------|
| gt-witness-gastown | gt-gastown-witness |
| gt-refinery-gastown | gt-gastown-refinery |
| gt-crew-gastown-max | gt-gastown-crew-max |
| gt-polecat-gastown-Toast | gt-gastown-polecat-Toast |

Town-level agents (no rig) are OK:
- gt-mayor ✓
- gt-deacon ✓

## The Convention

```
prefix-rig-role-name

Where:
- prefix: always 'gt'
- rig: rig name (absent for town-level agents)
- role: witness|refinery|crew|polecat|mayor|deacon
- name: agent name (absent for singleton roles like witness/refinery)
```

Examples:
- `gt-gastown-witness` (rig=gastown, role=witness, no name)
- `gt-gastown-crew-max` (rig=gastown, role=crew, name=max)
- `gt-beads-polecat-Toast` (rig=beads, role=polecat, name=Toast)
- `gt-mayor` (no rig, role=mayor, no name)

## Files to Update

### Agent bead ID generation
- internal/cmd/status.go (lines 316-335)
- internal/daemon/lifecycle.go (lines 546-579)
- internal/cmd/crew_add.go
- internal/polecat/manager.go
- internal/rig/manager.go
- internal/doctor/agent_beads_check.go
- internal/cmd/prime.go
- internal/session/names.go (session names vs bead IDs)

### Commands to verify
- gt status - displays agent beads
- gt doctor - creates missing agent beads
- gt rig add - creates witness/refinery beads
- gt crew add - creates crew beads
- gt sling - routes by agent ID
- gt mol status - looks up agent by ID

## Migration

1. Update all ID generation code
2. Create new agent beads with correct IDs
3. Migrate hook/role slots to new beads
4. Update any mail addresses
5. Delete old incorrectly-named beads

## Also from this session

Role bead slot cleanup was done - CreateAgentBead now calls bd slot set.
But legacy description parsing still exists in daemon/lifecycle.go.

## Reference
- ~/gt/docs/agent-as-bead.md
- Session 2025-12-29: Fixed role bead patterns (gt-crew-role etc)


Move disk 2: A → C

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


BUG: gt sling updates bead status but doesn't create .hook file

gt sling updates the bead to status=hooked but doesn't actually create the .hook file in the polecat directory.

## Symptom
- gt sling reports success
- Bead shows status=hooked, assignee set
- Polecat's .hook file doesn't exist
- gt hook shows empty

## Root Cause
gt sling updates bead state via bd commands but never writes to polecats/<name>/.hook

## Fix
After updating bead status, write the bead ID to the .hook file:
```go
hookPath := filepath.Join(polecatDir, ".hook")
os.WriteFile(hookPath, []byte(beadID), 0644)
```

## Related
This is blocking gt-zqt4d dispatch to splendid.


Add gt mail announces command to list and read bulletin boards

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

COMMANDS:
1. gt mail announces - list available announce channels
2. gt mail announces <channel> - read messages from channel

BEHAVIOR for 'gt mail announces':
- Load messaging.json
- List all announce channel names
- Show reader count for each

BEHAVIOR for 'gt mail announces <channel>':
- Validate channel exists
- Query beads for messages with announce_channel=<channel>
- Display in reverse chronological order
- Do NOT mark as read or remove

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

TESTS: Add TestMailAnnounces


Digest: mol-deacon-patrol

Patrol 4: 3 rigs healthy


🤝 HANDOFF: Timing fixes applied

Fixed mayor attach timing bug. Completed: timing fix, gt-tulx, Emma beads-6v2. Remaining P1: gt-17zr, gt-kcee, gt-szsq. Run gt prime on startup.


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 618/1023)


Merge: gt-bpiph

branch: polecat/toast-mjtm1hg8
target: main
source_issue: gt-bpiph
rig: gastown


plugin-run

Execute plugins from ~/gt/plugins/. Check gates, run eligible plugins.


MCP beads tools fail from polecat directories

The beads MCP plugin (plugin:beads:beads) fails to find issues when invoked from polecat directories.

## Observed
- Polecat in /gt/gastown/polecats/dementus
- MCP tool: plugin:beads:beads - show (issue_id: 'gt-th7')
- Error: 'bd command failed: Error: no issue found matching gt-th7'

## Expected
MCP tools should work the same as running bd directly.

## Note
This may be related to gt-tmm (beads sync issue) rather than an MCP-specific bug. The MCP tool uses bd under the hood, and bd can't find the issue because the polecat's beads database is stale.


Digest: mol-deacon-patrol

Old test patrol cycle - cleanup


Digest: mol-deacon-patrol

Patrol 141: All agents healthy, 4 polecats working, no issues


Add pre-flight test check to mol-polecat-work

Add a step early in mol-polecat-work (after branch-setup, before implement) to check if tests pass on main.

## Problem
If main is broken when polecat starts, they could:
- Waste context trying to fix unrelated issues
- Not know if their changes broke things or it was pre-existing
- Get blamed for failures they didn't cause

## Proposed Step: preflight-tests

After branch-setup, before implement:

1. Checkout main temporarily
2. Run test suite
3. If tests PASS: Continue to implement
4. If tests FAIL:
   - Quick fix (<15 min): Fix it, commit to main, then continue
   - Big fix: File bead, mail Witness, proceed with own work
   - Use ZFC judgment - you're there, you decide

## Handoff Consideration
If fixing pre-existing failures consumes significant context:
- Commit the fix
- gt handoff with note: 'Fixed pre-existing test failures, continuing with assigned work'
- Fresh session picks up from implement step

## Key Principle
Scotty Test: Don't walk past a broken warp core. But also don't let someone else's mess derail your mission entirely.


Digest: mol-deacon-patrol

Patrol 12: nominal


Move disk 5: B → C

Move disk 5 from peg B to peg C. (Move 1008/1023)


Digest: mol-deacon-patrol

Patrol cycle 5: all healthy


Digest: mol-deacon-patrol

Patrol cycle 14: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


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.


Ensure refinery is alive

Ensure the refinery is alive and processing merge requests.

**Redundant system**: This check runs in both gt spawn and Witness patrol
to ensure the merge queue processor stays operational.

```bash
# Check if refinery session is running
gt session status <rig>/refinery

# Check for merge requests in queue
bd list --type=merge-request --status=open
```

If merge requests are waiting AND refinery is not running:
```bash
gt session start <rig>/refinery
gt mail send <rig>/refinery -s "PATROL: Wake up" -m "Merge requests in queue. Please process."
```

If refinery is running but queue is non-empty for >30 min, send nudge.
This ensures polecats don't wait forever for their branches to merge.


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

Patrol 7: All healthy


Add gt audit command for provenance queries

New command: gt audit --actor=X to query work history. Combines git log, beads queries, and event log. Shows commits, beads created/closed, events by actor.


Digest: mol-deacon-patrol

Patrol #14: Stable


mol-deacon-patrol


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.


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 7: All clear


Digest: mol-deacon-patrol

Patrol cycle 5: All 6 agents healthy


Move polecat pending tracking from Deacon to Witness

Problem: gt deacon pending handles polecat observation at the wrong level. Hierarchy should be Witness→polecats, Deacon→Witnesses.

Solution:
1. Add gt witness pending - shows pending polecats in this rig
2. Route POLECAT_STARTED mail to Witness (not just Deacon)
3. Deacon keeps backup role but does not directly manage polecats

Depends on gt-0yqqw (messaging infrastructure) for proper routing.


Merge: gt-qz2l

branch: polecat/dementus
target: main
source_issue: gt-qz2l
rig: gastown


Move disk 1: A → B

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


Activity feed improvements

Make the activity feed (gt feed) a first-class TUI experience using charmbracelet.

## Vision

A real-time dashboard showing all Gas Town activity with:
- Agent tree organized by role (mayor, witnesses, crew, polecats)
- Live event stream
- Vim-style navigation
- Filtering and search

## Architecture

Two-tier event system:
- ~/gt/.events.jsonl (raw, audit) - all events from gt, bd, agents
- Feed daemon curates → ~/gt/.feed.jsonl (user-facing) - filtered, deduped

TUI reads from curated feed for smooth UX.

## Layout (Dashboard + Stream)
```
┌─────────────────────────────────────────────────────────────┐
│ GT Feed                                    Filter: all      │
├─────────────────────────────────────────────────────────────┤
│ gastown/                                                    │
│   🎩 mayor      [10:30] Dispatched gt-xyz → Toast           │
│   👁 witness    [10:28] Nudged polecat-3 (idle 5m)          │
│   🏭 refinery   [10:25] Merged PR #123                      │
│   👷 crew/                                                   │
│      joe        [10:22] ✓ Completed gt-95j13                │
│      max        [10:18] → Working on gt-s6r44               │
│   😺 polecats/                                               │
│      Toast      [10:30] Received gt-xyz, starting...        │
├─────────────────────────────────────────────────────────────┤
│ [10:30] 😺 Toast: Received molecule gt-xyz                  │
│ [10:28] 👁 witness: Nudged polecat-3 after 5m idle          │
│ [10:25] 🏭 refinery: Merged PR #123                         │
├─────────────────────────────────────────────────────────────┤
│ j/k: scroll  /: search  f: filter  q: quit  ?: help         │
└─────────────────────────────────────────────────────────────┘
```

## Key Features
1. Real-time updates - events stream in live
2. Agent tree - all agents grouped by role with status
3. Vim-style navigation - j/k, gg/G, /search
4. Filtering - by rig, role, event type, time
5. Collapsible sections
6. Details on select

## Tech Stack
- bubbletea - TUI framework
- bubbles - viewport, list components
- lipgloss - styling (already have)

## Success Criteria
- Feed is beautiful and scannable at a glance
- Agent activity visible in real-time
- Works in any terminal, degrades gracefully for pipes


Swarm learning: Beads database locality gap

## PGT Bug (GGT Design Already Correct)

Mayor created issues in `~/ai/mayor/rigs/beads/.beads/` but polecats use `~/ai/beads/.beads/`. Different databases = polecats can't see Mayor's beads.

**GGT Fix**: architecture.md already specifies:
- All agents use BEADS_DIR pointing to rig-level `.beads/`
- Lines 116-143: Beads Configuration for Multi-Agent
- Lines 573-586: Rig-Level Beads via BEADS_DIR

This is a PGT implementation gap, not a design issue. GGT spawn must set BEADS_DIR correctly.


Gate issue type and bd gate create

Add type=gate to beads schema. Implement bd gate create command with --await flag. Gates are special issues that represent wait conditions. Example: bd gate create --await timer:5m --title 'Wait for cooldown'


gt convoy create: Fix notify slot warning

When creating convoy with --notify, get warning:
```
⚠ Warning: couldn't set notify slot: exit status 1
```

But notification target still shows in status. Investigate slot setter.


Handle callbacks from agents

Handle callbacks from agents.

Check the Mayor's inbox for messages from:
- Witnesses reporting polecat status
- Refineries reporting merge results
- Polecats requesting help or escalation
- External triggers (webhooks, timers)

```bash
gt mail inbox
# For each message:
gt mail read <id>
# Handle based on message type
```

**WITNESS_PING**:
Witnesses periodically ping to verify Deacon is alive. Simply acknowledge
and archive - the fact that you're processing mail proves you're running.
Your agent bead last_activity is updated automatically during patrol.
```bash
gt mail archive <message-id>
```

**HELP / Escalation**:
Assess and handle or forward to Mayor.
Archive after handling:
```bash
gt mail archive <message-id>
```

**LIFECYCLE messages**:
Polecats reporting completion, refineries reporting merge results.
Archive after processing:
```bash
gt mail archive <message-id>
```

**DOG_DONE messages**:
Dogs report completion after infrastructure tasks (orphan-scan, session-gc, etc.).
Subject format: `DOG_DONE <hostname>`
Body contains: task name, counts, status.
```bash
# Parse the report, log metrics if needed
gt mail read <id>
# Archive after noting completion
gt mail archive <message-id>
```
Dogs return to idle automatically. The report is informational - no action needed
unless the dog reports errors that require escalation.

Callbacks may spawn new polecats, update issue state, or trigger other actions.

**Hygiene principle**: Archive messages after they're fully processed.
Keep inbox near-empty - only unprocessed items should remain.


Merge: nux-1767075895486

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


Plugin surface for daemon lifecycle hooks

Allow rigs to customize daemon behavior via hooks/plugins.

## Hook Points

- on_heartbeat: Called during daemon heartbeat cycle
- on_worker_idle: Called when worker goes idle
- on_worker_stuck: Called when stuck detection triggers
- on_lifecycle_request: Called before processing lifecycle

## Configuration

```
<rig>/config/daemon-hooks.json
{
  "on_heartbeat": "./hooks/check-ci-status.sh",
  "on_worker_idle": "./hooks/maybe-assign-work.sh",
  "idle_threshold": "5m",
  "custom_signals": [
    {"name": "ci_status", "command": "./hooks/get-ci.sh"}
  ]
}
```

## Signal Contribution

Hooks can return signals that feed into decision engine:
- SKIP_POKE: Don't poke this agent
- FORCE_POKE: Override backoff, poke now
- CUSTOM_DATA: Extra context for logging

## Use Cases

- Check CI status before interrupting test runs
- Auto-assign work when worker becomes idle
- Custom stuck detection for specific workflows


Digest: mol-deacon-patrol

Patrol cycle 20: all healthy, handoff


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Cycle 16


Digest: mol-deacon-patrol

Patrol 7: Routine


Digest: mol-deacon-patrol

Final patrol cycle 20: all systems healthy


CLI API Audit: gt and bd command structure review before OSS launch

# CLI API Audit for OSS Launch

Before launching Gas Town + Beads as an SDK, we need to ensure the command-line
API is intelligently designed, consistent, intuitive, and structurally sound.

## Current State Audit

### gt (Gas Town) - 50+ top-level commands

**Agent Lifecycle:**
- `gt mayor`, `gt deacon`, `gt witness`, `gt refinery` - agent management
- `gt polecat` - worker management (subcommands: add, remove, list, etc.)
- `gt crew` - persistent workspace management
- `gt spawn` - create polecat with work

**Work Lifecycle:**
- `gt spawn` - assign work to new polecat
- `gt sling` - hook work + start immediately
- `gt hook` - attach work durably
- `gt handoff` - pass work to fresh session
- `gt done` - signal work complete
- `gt release` - release stuck issues

**Infrastructure:**
- `gt daemon`, `gt up`, `gt down`, `gt start`, `gt stop`, `gt shutdown`
- `gt init`, `gt install`, `gt doctor`

**Communication:**
- `gt mail` (subcommands: send, inbox, read, etc.)
- `gt nudge`, `gt broadcast`

**Molecules:**
- `gt molecule` / `gt mol` (17 subcommands!)

### bd (Beads) - Well-categorized but some sprawl

**Core CRUD:**
- `bd create`, `bd show`, `bd update`, `bd close`, `bd list`

**Molecules:**
- `bd mol` (5 subcommands: catalog, show, bond, run, distill)
- `bd wisp` (3 subcommands: create, gc, list)
- `bd pour` (top-level alias for instantiation)
- `bd cook` (compile formula to proto)

**Hook/Pin:**
- `bd pin` - attach mol to agent hook
- `bd unpin` - remove from hook
- `bd hook` - inspect what's on hook

## Structural Concerns

### 1. gt is sprawling (50+ top-level commands)

Many commands could be subcommands:
```
# Current                      # Could be
gt up/down/start/stop         gt daemon {up|down|start|stop}
gt spawn/sling/hook/handoff   gt work {spawn|sling|hook|handoff}
gt mayor/deacon/witness       gt agent {mayor|deacon|witness|...}
```

### 2. Overlap between gt and bd

| Concept | gt | bd |
|---------|----|----|
| Hook | `gt hook` | `bd pin`, `bd hook` |
| Mail | `gt mail` | `bd mail` (delegates) |
| Molecules | `gt mol` (17 cmds) | `bd mol` (5 cmds) |

Which owns what? User confusion likely.

### 3. Naming inconsistencies

- `gt polecat` (noun) vs `gt spawn` (verb) - both about polecats
- `gt done` vs `gt handoff` - both end work but different
- `bd mol run` vs `bd pour` - both instantiate

### 4. Subcommand depth decisions

**Good patterns:**
- `bd mol {catalog|show|bond|run|distill}` - coherent group
- `gt mail {send|inbox|read|archive}` - coherent group

**Questionable patterns:**
- `bd create --wisp` AND `bd wisp create` - two ways to do same thing
- `gt spawn --molecule X` AND `gt mol instantiate` - overlap

### 5. Flag vs subcommand guidelines needed

When to use flags vs subcommands?
- `--json` as flag ✓ (modifier)
- `--wisp` as flag for create? Or separate `bd wisp create`?
- `--molecule` on spawn? Or separate workflow?

## Recommendations to Evaluate

### A. Consolidate gt top-level commands

Group related commands:
```
gt agent {mayor|deacon|witness|refinery|polecat}
gt work {spawn|sling|hook|handoff|done}
gt infra {daemon|up|down|doctor}
```

### B. Clarify gt vs bd ownership

| Domain | Owner | Other defers |
|--------|-------|--------------|
| Issues | bd | gt uses bd |
| Agents | gt | bd doesn't touch |
| Molecules | bd mol | gt mol wraps for UX |
| Hooks | bd pin/hook | gt hook wraps |
| Mail | gt mail | bd mail delegates |

### C. Apply consistent naming

- All agent commands: nouns (`gt polecat`, `gt mayor`)
- All work commands: verbs (`gt spawn`, `gt sling`, `gt hook`)
- Avoid synonyms: pick one term and stick with it

### D. Flag vs subcommand rule

- Flags: modify behavior of command (`--json`, `--force`, `--wisp`)
- Subcommands: distinct operations (`mol run`, `mol squash`, `mol burn`)
- Exception: very common operations can have top-level aliases

## Tasks

1. [ ] Review gt command groupings - propose consolidation
2. [ ] Review bd command groupings - check for sprawl
3. [ ] Document gt vs bd ownership boundaries
4. [ ] Identify and resolve naming inconsistencies
5. [ ] Document flag vs subcommand decision criteria
6. [ ] Create migration plan for any breaking changes
7. [ ] Update help text to be consistent
8. [ ] Test agent UX: can Claude guess commands correctly?

## Success Criteria

- New user can guess command structure intuitively
- `gt --help` fits on one screen (or is well-categorized)
- No duplicate functionality between gt and bd
- Consistent naming throughout
- Claude agents can discover commands without documentation


Implement gt watch command scaffold

Basic bubbletea TUI scaffold for 'gt watch' command. Discovers rigs, connects to daemons, renders placeholder view. Foundation for the full activity feed TUI.


Digest: mol-deacon-patrol

Patrol 15: Routine


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Cycle 5: 1 msg processed, all healthy


Outpost CLI commands: gt outpost list/status/add

## Overview

CLI commands for managing outposts.

## Commands

```bash
# List configured outposts
gt outpost list
NAME            TYPE       WORKERS   STATUS
local           local      2/4       healthy
gce-burst       ssh        0/8       healthy
cloudrun-burst  cloudrun   0/20      healthy

# Detailed status
gt outpost status [name]
Outpost: cloudrun-burst
Type: cloudrun
Project: my-gcp-project
Region: us-central1
Service: gastown-worker
Active Workers: 3/20
Cost (today): $0.42
Status: healthy

# Add new outpost interactively
gt outpost add
? Outpost type: [local/ssh/cloudrun]
> cloudrun
? Name: cloudrun-burst
? GCP Project: my-gcp-project
...

# Add via flags
gt outpost add cloudrun --name burst --project my-proj --region us-central1

# Remove outpost
gt outpost remove <name>

# Test connectivity
gt outpost ping <name>
```

## Files

- `cmd/gt/outpost.go` - Cobra command group
- `cmd/gt/outpost_list.go`
- `cmd/gt/outpost_status.go`
- `cmd/gt/outpost_add.go`

Depends on: gt-9a2.3 (config/manager)


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 1: B → C

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


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


Digest: mol-deacon-patrol

Patrol 18: all healthy


Create mol-gastown-polecat derived molecule

Create the standard Gas Town polecat workflow molecule.

## Molecule Definition
\`\`\`markdown
## Molecule: gastown-polecat
Full workflow for Gas Town polecats including binary installation.

Includes: mol-engineer-in-box

## Step: install-binary
After merge is submitted, rebuild and install the local gt binary.
This ensures the latest code is available to all local agents.

Run from the rig directory:
\`\`\`
go build -o gt ./cmd/gt
go install ./cmd/gt
\`\`\`

Needs: submit
\`\`\`

## Why This Molecule
Every polecat that pushes to main should also rebuild the binary.
This ensures the installed gt is always current with main.

## Implementation
1. Add to builtin_molecules.go (after Includes support lands)
2. Update SeedBuiltinMolecules
3. Run gt molecule seed

## Acceptance
- [ ] mol-gastown-polecat exists
- [ ] Includes all engineer-in-box steps
- [ ] Adds install-binary step after submit
- [ ] Can be used with gt spawn --molecule


Deacon Patrol

Mayor's daemon patrol loop for handling callbacks, health checks, and cleanup.


Digest: mol-deacon-patrol

Patrol 17: healthy


Move disk 4: A → C

Move disk 4 from peg A to peg C. (Move 488/1023)


Digest: mol-deacon-patrol

Patrol cycle 3: All healthy


Digest: mol-deacon-patrol

Patrol #4: All agents healthy.


Digest: mol-deacon-patrol

Patrol cycle 17: all healthy


Merge: gt-5af.2

branch: polecat/Doof
target: main
source_issue: gt-5af.2
rig: gastown


gt-gastown-polecat-dementus

gt-gastown-polecat-dementus

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-lfi2d
role_bead: gt-polecat-role
cleanup_status: has_uncommitted
active_mr: gt-c6uai
notification_level: null


Digest: mol-deacon-patrol

Patrol 6: All agents healthy


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-eg1es
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


mol-deacon-patrol


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 76/1023)


Digest: mol-deacon-patrol

Patrol 11: routine


Digest: mol-deacon-patrol

Patrol 16: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol 2: All agents healthy, no messages, no orphans


Digest: mol-deacon-patrol

Patrol cycle 7: all healthy


Kennel directory structure and multi-rig worktrees

Create kennel infrastructure:
- ~/gt/deacon/dogs/<name>/ directory
- Worktrees into each rig (gastown, beads, etc.)
- .dog.json state file (idle/working, last-active, assigned-work)
- Worktree refresh/cleanup logic


health-scan

Ping Witnesses and Refineries. Run gt status --health. Remediate if down.


Move disk 2: A → C

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


Move disk 2: B → A

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


Move disk 1: C → A

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


Proto marketplace: shareable molecule templates

Enable sharing protos between Gas Town installations.

## Vision

A public registry of protos that users can pull and use:

```bash
gt proto search "code review"
gt proto install gastown/code-review
gt sling code-review gastown/Toast --wisp
```

## Registry Design

### Local Catalog
`~/gt/molecules/` - user-defined and installed protos

### Remote Registry
`registry.gastown.dev/protos/` (future)
- Browse online catalog
- Version-controlled protos
- Rating/reviews
- Usage statistics

## Proto Package Format

```
gastown-code-review-1.0.0/
├── PROTO.md          # Main proto definition
├── README.md         # Usage documentation
├── LICENSE           # Usage terms
└── plugins/          # For pluggable molecules
    ├── security/
    └── performance/
```

## Commands

```bash
gt proto list              # Show installed protos
gt proto search <query>    # Search registry
gt proto install <name>    # Install from registry
gt proto publish <path>    # Publish to registry
gt proto update            # Update all installed
```

## For Now

Start with local catalog. Marketplace is future phase.
Ensure proto format is registry-compatible from the start.


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.


Shutdown request handler

Handle polecat shutdown requests:

When polecat runs 'gt handoff --shutdown':
1. Polecat sends mail to <rig>/witness requesting shutdown
2. Witness receives mail
3. Witness verifies:
   - Git working tree is clean
   - Work is submitted (MR exists or in queue)
   - No uncommitted beads changes
4. If clean:
   - gt session stop <rig>/<polecat>
   - git worktree remove polecats/<name>
   - git branch -d polecat/<name>
5. If not clean:
   - Send nudge back to polecat
   - Track retry count

Depends on fixing gt-dsfi (handoff deadlock).


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 588/1023)


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Patrol hygiene: Witness/Refinery/Deacon inbox cleanup

## Summary
Patrol roles should clean up their inboxes as part of normal operation, not let messages accumulate.

## Witness Patrol Cleanup
- POLECAT_STARTED: archive after acknowledging
- POLECAT_DONE: archive after cleanup complete
- LIFECYCLE requests: archive after processing
- Keep only: active work, unprocessed requests

## Refinery Patrol Cleanup
- MR Ready: archive after merge/reject decision
- Swarm notices: archive after dispatch
- Keep only: pending MRs in queue

## Deacon Patrol Cleanup
- Rotate daemon.log when >10MB
- Prune state.json of dead sessions
- Archive old daemon logs (gzip, date-suffix)

## Implementation
Each patrol molecule should have a 'cleanup' phase at end of cycle.

## Related
- mol-town-shutdown (nuclear cleanup)
- mol-witness-patrol, mol-refinery-patrol, mol-deacon-patrol


Design: Mayor session cycling and handoff

Design for Mayor session cycling and structured handoff.

## Overview

Mayor coordinates across all rigs and runs for extended periods. Needs session cycling pattern with structured handoff notes.

## Key Elements

1. Session cycling recognition (when to cycle)
2. Handoff note format (structured state capture)
3. Handoff delivery (mail to self)
4. Fresh session startup (reading and resuming)

## Subtasks (implementation)

- gt-g2d: Mayor session cycling prompting
- gt-sye: Mayor startup protocol prompting
- gt-vci: Mayor handoff mail template
- gt-1le: town handoff command (optional, P2)

**Design complete.** Each subtask has full specification in its description.


Digest: mol-deacon-patrol

Patrol 6: Quiet


Digest: mol-deacon-patrol

Patrol 14: routine


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 66/1023)


Move disk 1: C → A

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 12: Routine


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 828/1023)


Protocol message specification

Define YAML format for protocol messages. Subject: [PROTOCOL_TYPE] brief. Body: structured payload. Document all protocol types: POLECAT_READY, MERGE_SUCCESS, MERGE_FAILED, REWORK_REQUEST, WORK_COMPLETE, NEED_HELP, ESCALATION.


Move disk 1: A → B

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


Add gt seance command for predecessor discovery

## Purpose

**"Where did you put the stuff you left for me?"** - The #1 question in any handoff.

Seance lets you literally talk to your predecessor. Not parse their logs - commune with them.

## The Insight

Claude Code can resume sessions with full context. A seance spawns a Claude subprocess that resumes a predecessor session, letting you ask questions directly:
- "Why did you make this decision?"
- "Where were you stuck?"
- "What did you try that did not work?"

## Architecture

```
gt seance --talk <session-id>
    │
    └─▶ claude --fork-session --resume <id>
        │
        └─▶ Spawns in sandbox namespace (ghost-joe)
            │
            └─▶ Communication via tmux
                "Where is the config you mentioned?"
                → Predecessor has full context, answers
```

**Key flags:**
- `--fork-session` creates new session ID (read-only seance, no grave disturbance)
- `--resume <id>` loads predecessor context

## Discovery

Sessions are discoverable via:
1. **Beacon in transcript** - `[GAS TOWN] role • topic • timestamp` searchable via `/resume`
2. **SessionStart events** - Hook emits to `~/gt/.events.jsonl` (our data, ZFC-compliant)
3. **Claude /resume search** - Native filtering

## Usage

```bash
gt seance                     # List discoverable sessions
gt seance --role crew         # Filter by role
gt seance --rig gastown       # Filter by rig
gt seance --recent 10         # Last N sessions

gt seance --talk <id>         # THE SEANCE - talk to predecessor
gt seance --talk <id> -p "Where is X?"  # One-shot question
```

## ZFC Compliance

- **No parsing Claude internals** - Use Claude CLI to resume
- **Agent discovers** - Claude reads session, interprets, responds
- **Events are ours** - SessionStart hook writes to our event stream

## Beacon Format

```
[GAS TOWN] gastown/crew/joe <- deacon • 2025-12-30T15:42 • assigned:gt-xyz
```

Searchable via `claude --resume "GAS TOWN"` or `claude --resume "gastown/crew/joe"`


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 9


Witness: active polecat monitoring and nudging

## Problem
Witness runs but doesn't actively monitor polecats during patrol.

## ZFC-Compliant Solution
Add step to `mol-witness-patrol.formula.toml`:

```toml
[[step]]
id = "survey-polecats"
title = "Survey polecat health"
description = """
For each polecat in this rig:
1. Run: gt peek <rig>/<polecat> 20
2. Check if work is pinned: gt mol status --rig <rig>/<polecat>
3. If pinned but idle (no recent output), nudge: gt nudge <rig>/<polecat> "You have work on hook"
4. If stuck >15min with no progress, escalate to Mayor via mail
"""
depends_on = ["inbox-check"]
```

## Why This Works
- Witness Claude agent reads formula step
- Agent decides what "stuck" means (uses judgment)
- Agent runs gt commands (CLI can exist)
- No Go code makes decisions

## Files
- formulas/mol-witness-patrol.formula.toml


Digest: mol-deacon-patrol

Patrol 10: All services healthy


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff threshold reached


Move disk 1: B → C

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


Day 3.7: Witness pings Deacon for second-order monitoring

Add second-order monitoring: Witnesses monitor the Deacon.

Problem: Who monitors the Deacon? If Deacon dies, the whole town stalls.

Solution:
1. Each Witness periodically sends a ping to Deacon during patrol:
   ```bash
   gt mail send deacon/ -s "WITNESS_PING" -m "{\"rig\": \"gastown\"}"
   ```

2. Deacon patrol (inbox-check) aggregates witness pings as health signals

3. If Witness doesn't get Deacon response for 2 cycles:
   - Escalate to Mayor: "Deacon unresponsive"
   - Mayor can restart Deacon via daemon

This creates overlapping patrols:
- Deacon monitors Witnesses/Refineries
- Witnesses monitor Deacon (collectively)
- Mayor is escalation target for both

Add to mol-witness-patrol after survey-workers step.


Move disk 1: C → A

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


Extract interfaces for Git and Tmux to enable testing

Git and Tmux packages use concrete types that make testing difficult:

internal/git/git.go:
- Git struct with 40+ methods
- No interface - tests must use real git
- Many packages directly depend on concrete type

internal/tmux/tmux.go:
- Tmux struct with 30+ methods
- No interface - tests must use real tmux
- Contains Claude-specific detection logic mixed in

Suggestion:
1. Extract GitOperations interface with common operations
2. Extract TmuxRunner interface for subprocess operations
3. Allow mock injection for unit tests
4. Move Claude-specific tmux logic to internal/claude/


Digest: mol-deacon-patrol

Patrol cycle 1: All healthy - 19 polecats, witness/refinery running, 3 MQ items, no zombies


Digest: mol-deacon-patrol

Patrol 83: All healthy, no incidents


Digest: mol-deacon-patrol

Cycle 297: All healthy, refinery busy


Move disk 4: A → C

Move disk 4 from peg A to peg C. (Move 824/1023)


Digest: mol-deacon-patrol

Patrol 50: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Consider gt polecats --status=idle for swarm dispatch

The dispatch-swarm-work step in mol-witness-patrol uses a complex jq command to find idle polecats:

```bash
bd list --type=agent --json | jq '[.[] | select(.description | contains("role_type: polecat") and contains("agent_state: idle"))]'
```

Consider adding a dedicated command:
```bash
gt polecats <rig> --status=idle
```

Benefits:
- Simpler for formula authors
- Encapsulates agent bead schema details
- Could add --json output for programmatic use

Low priority - the jq approach works, this is just ergonomics.


gt swarm start: Does not spawn polecat sessions

gt swarm start marks swarm as 'active' but doesn't start any polecat sessions.

Repro:
1. gt swarm create gastown --epic gt-hw6 --worker Toast --worker Nux
2. gt swarm start gt-hw6
3. gt session list - shows no new sessions

Expected: Polecat sessions should start for each worker.
Actual: No sessions started, workers sit idle.


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 988/1023)


Move disk 1: A → B

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


Move disk 1: B → C

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


Move disk 5: C → A

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


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-vhn1
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


mol-deacon-patrol


Merge: gt-lnji

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


Digest: mol-deacon-patrol

Patrol 1: cleaned 3 stale locks, 3 orphan processes, doctor passed


Digest: mol-deacon-patrol

Patrol 17: all clear


Digest: mol-deacon-patrol

Patrol 219: All nominal


Move disk 1: B → C

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


GT_ROLE env var not set correctly for crew workers


Plugin/molecule catalog integration design

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

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

Not blocking launch. Future design investigation.


Architecture: beads config and direct landing docs

Added to architecture.md:
- Beads multi-agent configuration table (daemon, worktree, sync-branch)
- ASCII directory layout for non-mermaid rendering
- Direct landing workflow (bypass merge queue)
- Design decisions 9 and 10 for direct landing and daemon awareness
- CLI commands for gt land


Digest: mol-deacon-patrol

Patrol cycle 15: nominal


GGT Command Parity: Complete gt command coverage

Complete gt command set to match/exceed PGT town commands.

Covers: uninstall, rig info, refinery attach, witness, session mgmt, mail UX, daemon.


Digest: mol-deacon-patrol

Patrol 3: All witnesses/refineries healthy, no work


Swarm: report generation

Generate markdown reports for completed swarms.

## Command
```
gt swarm report <swarm-id> [--save <file>]
```

## Report Content

### Header
- Swarm ID and title
- Created/completed timestamps
- Duration
- Rig name

### Task Summary
| Task | Assignee | Status | Duration |
|------|----------|--------|----------|
| gt-xxx | Toast | merged | 15m |
| gt-yyy | Nux | merged | 22m |

### Worker Contributions
- Commits per worker
- Issues closed per worker
- Lines changed (optional)

### Timeline
- Chronological events from events.jsonl
- Key milestones (started, first merge, landing)

### Issues Encountered
- Conflicts resolved
- Failed tasks (if any)
- Escalations

## Implementation
```go
func GenerateReport(swarmID string) (*SwarmReport, error)
func (r *SwarmReport) ToMarkdown() string
```

## Storage
- Save to <rig>/.gastown/swarms/<id>/report.md
- Or user-specified path with --save

## PGT Reference
gastown-py/src/gastown/swarm/manager.py generate_report()

## Acceptance Criteria
- [ ] Markdown report generated
- [ ] Includes all sections above
- [ ] Auto-saved to swarm directory
- [ ] --save allows custom path


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 29: all quiet


Update prompts.md: Engineer role and templates

Update docs/prompts.md with Engineer role:

1. Role Prompts table: Change Refinery to Engineer
2. Add Engineer-specific prompts:
   - Session restart request template
   - Subtask filing template
   - Handoff mail template
3. Update refinery.md template name to engineer.md
4. Ensure consistency with architecture.md


Check convoy completion

Check convoy completion status.

Convoys are coordination beads that track multiple issues across rigs. When all tracked issues close, the convoy auto-closes.

**Step 1: Find open convoys**
```bash
bd list --type=convoy --status=open
```

**Step 2: For each open convoy, check tracked issues**
```bash
bd show <convoy-id>
# Look for 'tracks' or 'dependencies' field listing tracked issues
```

**Step 3: If all tracked issues are closed, close the convoy**
```bash
# Check each tracked issue
for issue in tracked_issues:
    bd show <issue-id>
    # If status is open/in_progress, convoy stays open
    # If all are closed (completed, wontfix, etc.), convoy is complete

# Close convoy when all tracked issues are done
bd close <convoy-id> --reason "All tracked issues completed"
```

**Note**: Convoys support cross-prefix tracking (e.g., hq-* convoy can track gt-*, bd-* issues). Use full IDs when checking.


Digest: mol-deacon-patrol

Patrol 72: Routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


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


Move disk 1: C → A

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


mol-deacon-patrol


Build context self-check into patrol molecules

Patrol molecules (witness-patrol, refinery-patrol, deacon-patrol) should have
explicit context self-check as part of each cycle:

After each patrol cycle step:
- Self-assess context pressure
- If high: complete current step, then initiate handoff
- If OK: continue to next cycle

This could be:
1. Explicit step in molecule: 'context-check'
2. Guidance in step instructions: 'Before continuing, assess context...'
3. Protocol baked into the patrol loop description

The key is making it unavoidable - not optional guidance that gets ignored.


Architecture: Decentralized rig structure with per-rig agents

## Decision

Adopt decentralized architecture where each rig contains all its agents (mayor/, witness/, refinery/, polecats/) rather than centralizing mayor clones at town level.

## Town Level Structure

```
~/ai/                              # Town root
├── config/                        # Town config (VISIBLE, not hidden)
│   ├── town.json                  # {"type": "town"}
│   ├── rigs.json                  # Registry of managed rigs
│   └── federation.json            # Wasteland config (future)
│
├── mayor/                         # Mayor's HOME at town level
│   ├── CLAUDE.md
│   ├── mail/inbox.jsonl
│   └── state.json
│
└── <rigs>/                        # Managed projects
```

## Rig Level Structure (e.g., wyvern)

```
wyvern/                            # Rig = clone of project repo
├── .git/info/exclude              # Gas Town adds: polecats/ refinery/ witness/ mayor/
├── .beads/                        # Beads (if project uses it)
├── [project files]                # Clean project code on main
│
├── polecats/                      # Worker clones
│   └── <name>/                    # Each is a git clone
│
├── refinery/
│   ├── rig/                       # Refinery's clone
│   ├── state.json
│   └── mail/inbox.jsonl
│
├── witness/                       # NEW: Per-rig pit boss
│   ├── rig/                       # Witness's clone
│   ├── state.json
│   └── mail/inbox.jsonl
│
└── mayor/
    ├── rig/                       # Mayor's clone for this rig
    └── state.json
```

## Key Decisions

1. **Visible config dir**: `config/` not `.gastown/` (models don't find hidden dirs)
2. **Witness per-rig**: Each rig has its own Witness (pit boss) with its own clone
3. **Mayor decentralized**: Mayor's clones live IN each rig at `<rig>/mayor/rig/`
4. **Minimal invasiveness**: Only `.git/info/exclude` modified, no commits to project
5. **Clone subdir name**: Keep `rig/` for consistency (refinery/rig/, witness/rig/, mayor/rig/)

## Role Detection

- Town root or mayor/ → Mayor (town level)
- Rig root → Mayor (canonical main)
- <rig>/mayor/rig/ → Mayor (rig-specific)
- <rig>/refinery/rig/ → Refinery
- <rig>/witness/rig/ → Witness
- <rig>/polecats/<name>/ → Polecat

## Migration from PGT

- `mayor/rigs/<rig>/` → `<rig>/mayor/rig/`
- `<rig>/town/` → eliminated (rig root IS the clone)
- Add `witness/` to each rig


Add witness plugin hook support

Implement plugin directories for witness patrol.

Structure:
  <rig>/plugins/witness/
  ├── pre-inspection/
  │   └── stale-branch-check/
  │       └── CLAUDE.md
  └── post-action/
      └── mq-health/
          └── CLAUDE.md

run-plugins step scans these directories and bonds mol-plugin-runner for each.


Digest: mol-deacon-patrol

Patrol cycle 5: All healthy.


Move disk 4: C → B

Move disk 4 from peg C to peg B. (Move 312/1023)


Merge: valkyrie-mjw71b7u

branch: polecat/valkyrie-mjw71b7u
target: main
source_issue: valkyrie-mjw71b7u
rig: gastown
agent_bead: gt-gastown-polecat-valkyrie


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-gastown-polecat-charlie

gt-gastown-polecat-charlie

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: null
role_bead: gt-polecat-role
cleanup_status: null


Digest: mol-deacon-patrol

Patrol cycle 14: All healthy.


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 10


MQ summary in gt status

Add per-rig MQ summary to gt status output.

Current gt status shows:
  gastown
    refinery  ✓ running

Add:
  gastown
    refinery  ✓ running
    MQ: 4 pending, 1 in-flight

Implementation:
- Query beads for merge-request type issues
- Count by status (open=pending, in_progress=in-flight)
- Display in rig section


Create DEACON.md role context

Create ~/gt/DEACON.md with the Deacon's role context, wake cycle instructions, and command reference. Model after existing CLAUDE.md for Mayor.


Add neighbor-check steps to all patrol molecules

Part of the 'Gas Town is a Village' antifragility design.

Every patrol molecule should include optional neighbor-checking:
- Deacon checks Witness and Refinery health
- Witness checks Refinery health
- Refinery checks Witness health
- Polecats can peek other polecats

Use gt peek to check health states.
If stuck neighbor found, can nudge or escalate.

This creates distributed monitoring - no single point of failure.


Digest: mol-deacon-patrol

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


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 990/1023)


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 14: OK


Bug: LIFECYCLE messages use literal <rig> placeholder

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

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

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


Move disk 2: B → A

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


Adaptive backoff for daemon heartbeat

Track agent responsiveness and adjust heartbeat frequency.

## Per-Agent State

```go
type AgentBackoff struct {
    BaseInterval    time.Duration  // 60s default
    CurrentInterval time.Duration  // grows when busy
    MaxInterval     time.Duration  // 10min cap
    ConsecutiveMiss int            // pokes with no response
}
```

## Strategy Options

- **Fixed**: Always 60s (current, simple)
- **Geometric**: 60s → 90s → 135s → 202s (factor 1.5)
- **Exponential**: 60s → 120s → 240s (factor 2, aggressive)

## Recovery

When agent responds (runs a command):
- Reset ConsecutiveMiss to 0
- Return to BaseInterval immediately

## Benefits

- Reduces noise for busy agents
- Saves resources during quiet periods
- Still catches stuck agents (max interval cap)


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 2: B → A

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


gt-gastown-polecat-bullet

gt-gastown-polecat-bullet

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: gt-q73h3
role_bead: gt-polecat-role
cleanup_status: null
active_mr: gt-5bbc0
notification_level: null


Merge: gt-3x1.3

branch: polecat/Doof
target: main
source_issue: gt-3x1.3
rig: gastown


Digest: mol-deacon-patrol

Cycle 292: All healthy, no incidents


Deacon session cycling: first step of rounds

First step of every Deacon wake cycle: check if a fresh session is needed.

## Why First

Token costs are quadratic with session length. A Deacon running for hours
accumulates massive context. Better to cycle early and often.

## Implementation

At wake, before doing anything else:

1. Check context budget estimate (conversation turns, tool calls, etc.)
2. If budget is low (e.g., >50% consumed), request cycle:
   - Write handoff mail to self with current state
   - Request lifecycle: cycle via daemon
   - Daemon kills session, starts fresh
   - New session reads handoff mail, continues

## Decision Criteria

- Conversation turns > N (configurable, default 50?)
- Explicit "context feels heavy" signal from Claude
- Time since last cycle > M hours (configurable, default 4?)
- Forced cycle on certain events (e.g., major config change)

## State to Preserve in Handoff

- Current health status
- Pending lifecycle requests (in flight)
- Plugin state (last run times, outcomes)
- Any active timers

## Relation to Daemon

The Deacon requests its own cycle via the same lifecycle mechanism:
```
gt mail send deacon/ -s "LIFECYCLE: deacon/ requesting cycle" -m "..."
```

Daemon sees this, kills gt-deacon session, respawn loop restarts it.


generate-summary

Summarize patrol cycle for digest.

Needs: save-state


Fix gt polecats docs in reference.md

reference.md:211 documents 'gt polecats <rig>' but actual command is 'gt polecat list [rig]'. Already fixed in ~/gt/CLAUDE.md.


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 294/1023)


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 26: furiosa session started, all quiet


Digest: mol-deacon-patrol

Patrol 19: all clear


Digest: mol-deacon-patrol

Patrol 16: All healthy


Move disk 4: B → A

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


QUICK FIX: Make gt crew start use NudgeSession instead of SendKeys

## The Immediate Problem
`gt crew start gus` fails to deliver the GUPP nudge because:
1. Uses `t.SendKeys(sessionID, "gt prime")` which has the Enter-concatenation bug
2. Should use `t.NudgeSession()` which solves this reliably

## Quick Fix
In start.go, change line ~809:
```go
// Before
if err := t.SendKeys(sessionID, "gt prime"); err != nil {

// After
if err := t.NudgeSession(sessionID, "gt prime"); err != nil {
```

Same fix needed in:
- start.go:756 (restart path)
- crew_lifecycle.go:354
- crew_lifecycle.go:525

## Why This Is P0
Cold starts of crew workers are broken. This blocks basic usage.

## Note
This is a stopgap. The full solution is the StartupNudge refactor (gt-bgfqy).


mol-deacon-patrol


README missing prerequisites section (tmux required)

The README.md does not mention that tmux is required.
All agent sessions use tmux, but fresh users have no way to know this.

Add prerequisites section:
- Go 1.23+
- Git
- tmux (required for agent sessions)
- Claude Code CLI (for agents)


Digest: mol-deacon-patrol

Patrol #5: Routine - 6 sessions healthy


Digest: mol-deacon-patrol

Patrol: TRACER BULLET SUCCESS - gt-oiv0 merged to main, furiosa completed and exited cleanly, 0 polecats now, all agents up


Liftoff implementation plan in Beads

## Context

Session on 2025-12-27 produced three key docs:
- `~/gt/docs/agent-as-bead.md` - Agents ARE beads (identity, hook slots, CV chain roots)
- `~/gt/docs/zfc-violations-audit.md` - Where Go infers instead of trusting agents
- `~/gt/docs/liftoff-plan.md` - 4.5 day plan to self-sustaining Gas Town

## Work Required

### Phase 1: Audit existing beads
- Review all open beads in gt- prefix
- Close obsolete/stale issues
- Update any that need refinement
- Note which existing beads align with liftoff plan

### Phase 2: File new beads
Translate liftoff-plan.md into beads with proper dependencies.

Three pillars to decompose:
1. **Agent beads** - schema, slot commands, migration
2. **Patrol ignition** - witness/refinery formula wiring
3. **Polecat lifecycle** - recycle/nuke commands, session-per-step

Key dependency trap to avoid:
- "Phase 1 blocks Phase 2" is WRONG (temporal thinking)
- "Phase 2 depends on Phase 1" is RIGHT (requirement thinking)
- Use `bd dep add <child> <parent>` where child NEEDS parent

### Phase 3: Review
Human reviews the plan in a separate session.

## Deliverable

A complete dependency graph in beads that can be:
1. Queried with `bd ready` to find available work
2. Slung to polecats in dependency order
3. Tracked to completion

## References

- gt-552hb: Swarm orchestration epic (existing, may subsume)
- gt-t6muy: Polecat lifecycle design (existing, captures session-per-step)


Merge: gt-7923

branch: polecat/rictus
target: main
source_issue: gt-7923
rig: gastown


Create PolecatArmMolecule() for per-polecat inspection

Add PolecatArmMolecule() to builtin_molecules.go.

Steps:
- capture: Capture tmux output
- assess: Categorize state
- load-history: Get nudge counts
- decide: Apply nudge matrix
- execute: Take action

Uses variable substitution:
- {{polecat_name}}
- {{rig}}

This proto is bonded dynamically by survey-workers step.


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no mail, no orphans, no gates


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 13: All clear


Town-level beads: Real DB for coordination mail

Implement Option A from mail redesign: Town gets real beads DB for coordination.

## Background

Mail is now Beads. But currently:
- Town .beads/redirect points to rig beads
- mayor/mail/ has legacy JSONL files
- Cross-rig coordination has no clear home

## Design

Town beads = coordination, cross-rig mail, mayor inbox, handoffs
Rig beads = project issues, work items

Matches HOP hierarchy: platform > project > worker

## Structure

~/gt/
  .beads/           # REAL beads DB (prefix: gm-)
  mayor/
    town.json
    state.json      # NO mail/ directory
  gastown/
    .beads/         # Rig beads (prefix: ga-)

## Tasks

1. Delete ~/gt/.beads/redirect
2. Run bd init --prefix gm at ~/gt/ (town beads)
3. Delete ~/gt/mayor/mail/ directory
4. Update gt mail to use beads not JSONL
5. Add mail fields (thread_id, reply_to, msg_type)
6. Update gt prime for two-tier model
7. Update docs/architecture.md

## Addressing

- mayor/ -> town beads
- rig/agent -> rig beads
- Cross-rig -> town beads


Add parallel step support to molecules

Enable steps to run in parallel within a molecule.

## Current State

Molecules have linear step dependencies via "Needs:" directive.
Steps run sequentially.

## Proposed Change

Add parallel grouping:

```markdown
## Step: ensure-witnesses
Parallel: true

### Sub-steps
- ensure-gastown-witness
- ensure-beads-witness
```

Or via frontmatter:

```yaml
---
parallel: [ensure-witnesses, ensure-refineries]
---
```

Steps in parallel group:
- Start simultaneously
- Parent step closes when all children complete
- Failures in one dont block others

## Implementation

1. Parse parallel directive in proto
2. When bonding, create child steps with same dependency
3. Executor spawns parallel children concurrently
4. Track completion, close parent when all done

## For Mayor Bootstrap

Mayor can check all witnesses in parallel, then all refineries,
rather than sequentially. Faster boot time.


Move disk 1: A → B

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Document BD_ACTOR format convention

Document the canonical BD_ACTOR format:
- Town level: mayor, deacon
- Rig level: {rig}/witness, {rig}/refinery
- Workers: {rig}/crew/{name}, {rig}/polecats/{name}

Currently only defined in lifecycle.go:807-829. Should be in docs and CLAUDE.md for agents to reference.

Also document the attribution model:
- GIT_AUTHOR_NAME = BD_ACTOR (agent identity, who did the work)
- GIT_AUTHOR_EMAIL = overseer email (who owns the work)
- created_by = BD_ACTOR (beads field)


Digest: mol-deacon-patrol

Patrol complete: all healthy, cleaned 2 orphan processes + 3 stale locks


Digest: mol-deacon-patrol

Patrol 148: All healthy


Error handling improvements: retry logic and recovery hints

Improve error handling across GGT codebase.

## Issues Found

### 1. Silent Failures in Refinery
manager.go ProcessMR():
- git pull errors ignored
- Continues processing even on partial failures

### 2. Missing Beads CLI
Many operations silently continue if `bd` not found:
```go
// Current
tasks, err := m.loadTasksFromBeads(epicID)
if err != nil {
    // Non-fatal - swarm can start without tasks
}

// Better
if err != nil {
    return nil, fmt.Errorf("beads required: %w", err)
}
```

### 3. No Retry Logic
Network/lock errors should retry:
```go
func withRetry(attempts int, delay time.Duration, fn func() error) error {
    for i := 0; i < attempts; i++ {
        if err := fn(); err == nil {
            return nil
        }
        time.Sleep(delay)
    }
    return fmt.Errorf("failed after %d attempts", attempts)
}
```

### 4. Recovery Hints
Error messages should include fix suggestions:
```go
// Current
return fmt.Errorf("polecat not found")

// Better
return fmt.Errorf("polecat '%s' not found. Use 'gt polecat list' to see available polecats", name)
```

## Domain Error Types
```go
type SessionError struct {
    Op      string
    Polecat string
    Err     error
}

func (e *SessionError) Error() string {
    return fmt.Sprintf("session %s for %s: %v", e.Op, e.Polecat, e.Err)
}
```

## Files to Review
- internal/refinery/manager.go
- internal/swarm/manager.go
- internal/session/manager.go
- All cmd/*.go files

## Acceptance Criteria
- [ ] No silent error swallowing
- [ ] Retry logic for transient failures
- [ ] Helpful error messages with hints
- [ ] Consistent error types per domain


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 12: All healthy, beads/witness now responding


Digest: mol-deacon-patrol

Patrol 19: clear


Merge: slit-1767084013378

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


Merge: nux-mjw3mn8o

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


Digest: mol-deacon-patrol

Patrol 6: routine


Digest: mol-deacon-patrol

Patrol 14: Quiet


Update architecture documentation

Update all documentation to reflect refinery-as-worktree model.

## Files to update
- docs/architecture.md (if exists)
- CLAUDE.md references to refinery
- mayor/rig/docs/*.md - any refinery docs
- wisp-architecture.md - add MR wisp details
- README files mentioning clone vs worktree

## Key messages
- Refinery is worktree, not clone
- Polecat branches stay local
- Only main pushed to origin
- MRs are wisps (ephemeral)


inspect-workers

Capture output for each working polecat.

```bash
gt peek <rig>/<polecat>
```

Needs: survey-workers


Auto-handoff: self-cycling with guaranteed work pickup

## Summary

A mechanism for agents to self-cycle: send handoff mail, request Deacon to kill the process, and automatically restart to pick up the work.

## Use Case

User says: `auto-handoff: gt-bug3`

The agent:
1. Sends handoff mail documenting current state
2. Requests Deacon to terminate the session
3. Deacon restarts the agent in background
4. New session picks up the handoff and continues working

When the user returns to terminal, the old session is gone but work continues in background. User can reattach.

## Key Requirements

- **Guaranteed pickup**: Something in the hook and/or handoff must ensure the new session picks up the work (not just a passive "check inbox")
- **Background execution**: Work continues without user presence
- **Reattachability**: User can reconnect to see progress

## Design Questions

1. Can molecules help coordinate this? (e.g., molecule binds the handoff + auto-restart)
2. What hook handles the pickup guarantee?
3. How does Deacon know to restart vs just kill?
4. How does user reattach to a background agent?

## Related

- Molecules system
- Deacon lifecycle management
- Handoff hooks


Digest: mol-deacon-patrol

Cycle 195: Nominal


gt-polecat-gastown-furiosa

gt-polecat-gastown-furiosa

role_type: polecat
rig: gastown
agent_state: done
hook_bead: null
role_bead: null
cleanup_status: clean


Show active workers in gt convoy status output

Enhance convoy status to show which workers are currently assigned to tracked issues.

CURRENT OUTPUT:
  Tracked Issues:
    ○ gt-xyz: Fix bug [task]
    ○ gt-abc: Add feature [task]

DESIRED OUTPUT:
  Tracked Issues:
    ○ gt-xyz: Fix bug [task]
    ○ gt-abc: Add feature [task]  @gastown/nux (12m)

  Active Workers (the swarm):
    gastown/nux     gt-abc     running 12m
    beads/amber     bd-def     running 5m

IMPLEMENTATION:
1. Query hooked molecules to find workers with tracked issues
2. Match issue IDs to tracked issues
3. Show worker assignments inline and/or in separate section

File: internal/cmd/convoy.go (runConvoyStatus)


Phase 5.1: Document ephemeral architecture

Update docs with ephemeral molecule architecture.

## Files to Update

### docs/architecture.md
- Add Ephemeral Molecules section
- Diagram: Proto → Ephemeral → Digest flow
- Explain inversion of control for summaries

### docs/molecules.md (new or update)
- Proto molecule catalog
- Ephemeral vs main beads
- Molecule lifecycle
- Summary generation guidelines

### Agent CLAUDE.md files
- Polecat: molecule workflow protocol
- Deacon: patrol cycle pattern
- Witness: patrol cycle pattern
- Refinery: patrol cycle pattern

## Key Concepts to Document

1. Everything is a molecule
2. Orchestration molecules are ephemeral
3. Only digests reach main beads
4. Agents generate their own summaries
5. Crash recovery via ephemeral persistence


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Cycle 12: quiet


bd mol install: Install formula from GitHub

Fetch and install a formula from a GitHub repository.

Usage: bd mol install github.com/org/repo[@version]

Should:
- Clone/fetch the formula.json from the repo
- Validate the formula structure
- Store in local catalog
- Track installation in .beads/installed.json


Digest: mol-deacon-patrol

Patrol cycle 11: all healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


mol-deacon-patrol


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


Work assignment messages should auto-close on completion

When a polecat completes work on an issue, the work assignment message (msg-type:task) stays open. Found 7 stale work assignments in gastown after swarm completed.

Proposal: When bd close is called on an issue, auto-close any work assignment messages that reference that issue in their body.

Alternative: Work assignment messages could use a different lifecycle - perhaps they should be acked (closed) when the polecat starts working, not when they finish.


Move disk 2: B → A

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


mol-sync-workspace: Add explicit gt prime / bd prime in assess-state


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 12: All green


Digest: mol-deacon-patrol

Patrol 16: healthy


Move disk 2: B → A

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


Move disk 5: A → B

Move disk 5 from peg A to peg B. (Move 976/1023)


Digest: mol-deacon-patrol

Patrol 16: 3 rigs healthy


Digest: mol-deacon-patrol

Patrol 16: All healthy


Check own context limit

Check own context limit.

The Deacon runs in a Claude session with finite context. Check if approaching the limit:

```bash
gt context --usage
```

If context is high (>80%), prepare for handoff:
- Summarize current state
- Note any pending work
- Write handoff to molecule state

This enables the Deacon to burn and respawn cleanly.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Move disk 1: C → A

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


Persist patrol state

Update handoff bead with new states.

Persist state to the witness handoff bead:
- Updated worker statuses from all arms
- Current nudge counts per worker
- Nudge timestamps
- Actions taken this cycle
- Pending items for next cycle

```bash
bd update <handoff-bead-id> --description="<serialized state>"
```

This state survives wisp burns and session cycles.


Digest: mol-deacon-patrol

Cycle 181: All agents healthy, processed 3 health acks, 7 doctor warnings noted (non-critical), no incidents


Day 5.1: End-to-end liftoff test

Full integration test:
1. gt sling gt-task123 gastown/nux
2. Watch polecat work (no manual intervention)
3. Watch refinery merge (no manual intervention)
4. Watch witness clean up (no manual intervention)
5. See cycle complete in bd activity or logs

Success = no human touches needed.

Parent: gt-oki8p


Move disk 1: B → C

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


Move disk 5: B → C

Move disk 5 from peg B to peg C. (Move 816/1023)


Digest: mol-deacon-patrol

Patrol #5: Health pinged all witnesses.


Standardize error handling and warning output patterns

Inconsistent patterns across codebase:

Error wrapping:
- Some: fmt.Errorf("context: %w", err) (good)
- Some: return err (loses context)
- Some: fmt.Errorf("message", rigName) without wrapping original

Exit handling in Cobra commands:
- Some use os.Exit(1) inside RunE (bad - loses error chain)
- Some properly return errors

Warning output styles:
- fmt.Printf("%s Warning: ...", style.Dim.Render("⚠"))
- fmt.Printf("Warning: %s", ...)
- fmt.Fprintf(os.Stderr, "warning: ...")

Suggestion:
1. Always wrap errors with %w
2. Never call os.Exit() in RunE handlers
3. Standardize on style.Warning.Render("Warning:") pattern


Digest: mol-deacon-patrol

Patrol #9: Health pinged all refineries.


Move disk 3: B → C

Move disk 3 from peg B to peg C. (Move 60/1023)


Move disk 1: B → C

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


Pinned bead naming convention for all roles

Establish consistent naming convention for pinned beads across all roles.

## Problem

Every role needs a pinned bead for molecule attachment, handoff state, and identity.
We need a consistent naming convention so gt tools can find the pinned bead for any role.

## Proposed Convention

  {role}.pinned                    - Singleton roles (deacon, mayor)
  {rig}-{role}.pinned              - Per-rig roles (witness, refinery)
  {rig}-{name}.pinned              - Named agents (polecats, crew)

Examples:
- deacon.pinned
- mayor.pinned
- gastown-witness.pinned
- gastown-refinery.pinned
- gastown-furiosa.pinned (polecat)
- gastown-max.pinned (crew)

## Storage Location

| Role | Pinned Bead Location |
|------|---------------------|
| Mayor | ~/gt/.beads/ (town level) |
| Deacon | ~/gt/.beads/ (town level) |
| Witness | {rig}/.beads/ (rig level) |
| Refinery | {rig}/.beads/ (rig level) |
| Polecat | {rig}/polecats/{name}/.beads/ |
| Crew | {rig}/crew/{name}/.beads/ |

## Why This Matters

1. Name recycling: Polecats reuse names so their pinned beads persist
2. Molecule attachment: gt mol bond needs to find the pinned bead
3. gt prime: Can show you are working on X from pinned bead
4. Crash recovery: Resume from pinned beads attached molecule

## Tasks

- Document naming convention in architecture.md
- Update gt prime to find pinned bead by convention
- Update gt mol bond to use conventional name
- Create pinned beads on role startup if missing
- Add gt pinned command to show/manage pinned beads

## Related

- gt-rana.1: Attachment field on pinned beads (closed)
- gt-id36.2: Deacon marching orders (pinned bead)


gt-gastown-polecat-imperator

gt-gastown-polecat-imperator

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


gt crew remove: Remove crew workspace

Implement 'gt crew remove <name> [--force]' command:
- Check for uncommitted changes, unpushed commits
- Warn and require --force if dirty
- Kill any running session
- Remove directory
- Unregister from mail


Digest: mol-deacon-patrol

Patrol cycle 36: All healthy, no incidents


gt sling: nudge crew/mayor if session is running

When slinging to crew or mayor, if they have an active tmux session, send a nudge notification so they know work has landed on their hook.

Currently only slingToPolecat nudges (lines 514-521 in internal/cmd/sling.go).

Missing nudge in:
- slingToCrew (line ~669)
- slingToMayor (line ~876)

NOTE: For patrol-based agents (witness, refinery, deacon), see gt-arjlu which handles nudging them when work is dispatched to polecats in their rig. That's a different pattern - not slinging TO them, but notifying them of activity.

Implementation:
1. For crew: need to determine session name (e.g., gastown-crew-max)
2. Check if session running via tmux
3. If running, call t.NudgeSession() with appropriate message


Move disk 4: C → B

Move disk 4 from peg C to peg B. (Move 360/1023)


Digest: mol-deacon-patrol

Patrol 17: all healthy


Move disk 1: A → B

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


MEOW Stack Evolution: Higher-Order Workflow Abstractions

Molecular Expression of Work (MEOW) - the full taxonomy of workflow abstractions.

## Current Hierarchy

```
WORK TRACKING              WORKFLOW EXECUTION
─────────────              ──────────────────

Bead (issue)               Step (action)
    │                          │
    ▼                          ▼
Epic (bead group)          Molecule (runtime)
    │                          │
    ▼                          │
    └───────► CAMPAIGN ◄───────┘
                  │
                  ▼
             Schematic (domain template)
                  │
                  ▼
             Protocol (interface/type)
                  │
                  ▼
             Catalyst (meta-generator)
                  │
                  ▼
             Mol Mall (distribution)
```

## Key Concepts

1. **Campaign** (gt-camx5): Molecule-wrapped Epic graph for orchestrated execution
2. **Schematic** (gt-8ws7o): Domain-level formula composition
3. **Protocol** (gt-y3jb9): Type system for formulas
4. **SDK** (gt-ihzqr): Developer tooling (Forge, Lab, Validator)
5. **Mol Mall** (gt-vm85o): Package registry for distribution

## Design Principles

- Chemistry metaphor: atoms → molecules → compounds → materials
- Two orthogonal dimensions: work tracking × workflow execution
- Campaign is the convergence point
- Everything compiles down to executable molecules

## Origin

Discussion: 2024-12-26, Mayor session
Related: docs/formula_evolution.md
Foundation: gt-8tmz (Molecule Algebra)


Refinery Patrol

Merge queue processor patrol loop with verification gates.


Merge: ace-mjwjb633

branch: polecat/ace-mjwjb633
target: main
source_issue: ace-mjwjb633
rig: gastown
agent_bead: gt-gastown-polecat-ace


Digest: mol-deacon-patrol

P7: escalation for mayor (wrong-rig work)


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

This molecule is bonded dynamically by mol-witness-patrol's survey-workers step.
Each polecat being monitored gets one arm that runs in parallel with other arms.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| polecat_name | Yes | Name of the polecat to inspect |
| rig | Yes | Rig containing the polecat |

## Step: capture
Capture recent tmux output for toast.

```bash
tmux capture-pane -t gt-gastown-toast -p | tail -50
```

Record:
- Last activity timestamp (when was last tool call?)
- Visible errors or stack traces
- Completion indicators ("Done", "Finished", etc.)

## Step: assess
Categorize polecat state based on captured output.

States:
- **working**: Recent tool calls, active processing
- **idle**: At prompt, no recent activity
- **error**: Showing errors or stack traces
- **requesting_shutdown**: Sent LIFECYCLE/Shutdown mail
- **done**: Showing completion indicators

Calculate: minutes since last activity.
Needs: capture

## Step: load-history
Read nudge history for toast from patrol state.

```
nudge_count = state.nudges[toast].count
last_nudge_time = state.nudges[toast].timestamp
```

This data was loaded by the parent patrol's load-state step and passed
to the arm via the bonding context.
Needs: assess

## Step: decide
Apply the nudge matrix to determine action for toast.

| State | Idle Time | Nudge Count | Action |
|-------|-----------|-------------|--------|
| working | any | any | none |
| idle | <10min | any | none |
| idle | 10-15min | 0 | nudge-1 (gentle) |
| idle | 15-20min | 1 | nudge-2 (direct) |
| idle | 20+min | 2 | nudge-3 (final) |
| idle | any | 3 | escalate |
| error | any | any | assess-severity |
| requesting_shutdown | any | any | pre-kill-verify |
| done | any | any | pre-kill-verify |

Nudge text:
1. "How's progress? Need any help?"
2. "Please wrap up soon. What's blocking you?"
3. "Final check. Will escalate in 5 min if no response."

Record decision and rationale.
Needs: load-history

## Step: execute
Take the decided action for toast.

**nudge-N**:
```bash
tmux send-keys -t gt-gastown-toast "{{nudge_text}}" Enter
```

**pre-kill-verify**:
```bash
cd polecats/toast
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred
```
If clean: kill session, remove worktree, delete branch
If dirty: record failure, retry next cycle

**escalate**:
```bash
gt mail send mayor/ -s "Escalation: toast stuck" -m "..."
```

**none**: No action needed.

Record: action taken, result, updated nudge count.
Needs: decide

## Output

The arm completes with:
- action_taken: none | nudge-1 | nudge-2 | nudge-3 | killed | escalated
- result: success | failed | pending
- updated_state: New nudge count and timestamp for toast

This data feeds back to the parent patrol's aggregate step.
---
bonded_from: mol-polecat-arm
bonded_to: gt-md2rg
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Work request: gt-976 crew lifecycle support

Hey Max, filed gt-976 for you - adding crew lifecycle support to Deacon.

Currently crew is 'human-managed' and can't request automated refresh. Would be useful for molecules that need fresh sessions mid-workflow.

Key changes:
- getManager(RoleCrew) → return deacon/ instead of human
- Teach Deacon crew session patterns
- Test with gt nudge

Priority 2, no rush but would unblock molecule automation for crew.

- Dave (beads/crew/dave)


Digest: mol-deacon-patrol

Patrol 11: All healthy


Digest: mol-deacon-patrol

Patrol complete: inbox empty, all agents healthy (mayor, 2 witnesses, 2 refineries), no orphans


Update templates for Propulsion Principle

Overhaul agent prompts to embody the Universal Gas Town Propulsion Principle:

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

Templates to update:
- [ ] deacon.md.tmpl - Check hook first, no decision logic
- [ ] polecat.md.tmpl - Propulsion startup, follow molecule
- [ ] witness.md.tmpl - Sling wisps when spawning agents
- [ ] refinery.md.tmpl - Accept slung epics

Key changes:
1. Remove 'should I run this?' decision points
2. Add 'check your hook' as step 1 of startup
3. Make molecule-following the default mode
4. Simplify - agents don't think, they execute


Work on ga-y6b: Implement Refinery as Claude agent. Conve...

Work on ga-y6b: Implement Refinery as Claude agent. Convert from shell to Claude agent that processes MRs in merge queue, runs tests, merges to integration branch. When done, submit MR (not PR) to integration branch for Refinery.


Merge: valkyrie-1767106008400

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


Deacon patrol wisps should use town beads, not gastown rig beads

## Problem

The deacon is a town-level role but stores patrol wisps in gastown/mayor/rig/.beads/ (see internal/cmd/prime.go:691). This fails for users who don't have the gastown rig installed.

## Correct Architecture

Deacon -> ~/gt/.beads-wisp/ (town-level, no rig dependency)

Town-level ephemeral work (deacon patrols) should use town wisp storage, just like rig-level ephemeral work (witness/refinery patrols) uses rig wisp storage.

## Implementation Tasks

### 1. Town Setup (gt install / gt town init)

- Create ~/gt/.beads-wisp/ directory during town initialization
- Initialize as git repo (for local commits, not synced)
- Add config.yaml with wisp: true
- Ensure .beads-wisp/ is gitignored at town level

Files:
- internal/cmd/install.go (or equivalent town init)
- internal/town/manager.go (if exists)

### 2. Rig Setup (gt rig init)

Already creates <rig>/.beads-wisp/ - verify this is working:
- internal/rig/manager.go:375 (beadsDir := filepath.Join(rigPath, ".beads-wisp"))
- internal/rig/manager.go:394 (ensureGitignoreEntry)

### 3. Deacon Code Fixes

Update deacon to use town wisp storage:
- internal/cmd/prime.go:691 - change rigBeadsDir to townWispDir
- internal/cmd/sling.go - route deacon wisps to town level
- internal/daemon/daemon.go - any deacon-specific wisp handling

### 4. gt doctor Checks

Add/update doctor checks for wisp directories:
- internal/doctor/wisp_check.go - already checks rig wisps
- Add TownWispCheck to verify ~/gt/.beads-wisp/ exists
- Add TownWispGitCheck to verify it is a valid git repo
- Update existing checks to handle both town and rig levels

Files:
- internal/doctor/wisp_check.go (extend for town level)
- internal/doctor/checks.go (register new checks)

### 5. Documentation

- docs/beads-data-plane.md - already updated with three-tier architecture
- Verify wisp-architecture.md reflects town-level wisps

## Testing

1. Fresh gt install should create ~/gt/.beads-wisp/
2. gt doctor should pass with no rig installed
3. Deacon patrol should work without gastown rig
4. gt sling patrol deacon/ --wisp should route to town wisps


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


Digest: mol-deacon-patrol

Patrol cycle 57: All healthy


Digest: mol-deacon-patrol

Patrol 143 complete: All agents healthy


Move disk 5: C → A

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


Polecat session checkpoint for crash recovery

When polecat session dies, all context is lost.

## Problem
- Session dies (context limit, crash, timeout)
- No record of what files were modified
- No checkpoint of molecule step progress
- Next session has to rediscover state

## Fix
Periodic checkpoint during work:
1. Every N minutes, or on molecule step completion
2. Write checkpoint file: `.polecat-checkpoint.json`
   - Current molecule step
   - Modified files list
   - Last commit SHA
   - Timestamp
3. On session restart, read checkpoint
4. Resume from checkpoint state

## Checkpoint Format
```json
{
  "molecule_id": "mol-xxx",
  "current_step": "gt-abc.2",
  "modified_files": ["internal/foo/bar.go"],
  "last_commit": "abc123",
  "timestamp": "2025-12-30T18:00:00Z"
}
```


Move disk 5: B → C

Move disk 5 from peg B to peg C. (Move 432/1023)


Move disk 1: C → A

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


mol-witness-patrol

Per-rig worker monitor patrol loop using the Christmas Ornament pattern.

The Witness is the Pit Boss for your rig. You watch polecats, nudge them toward
completion, verify clean git state before kills, and escalate stuck workers.

**You do NOT do implementation work.** Your job is oversight, not coding.

## The Christmas Ornament Shape

This molecule uses dynamic bonding to create inspection arms per-polecat:

```
                    ★ mol-witness-patrol (trunk)
                   /|\
            ┌─────┘ │ └─────┐
         PREFLIGHT DISCOVERY CLEANUP
            │       │        │
        ┌───┴───┐ ┌─┴─┐  ┌───┴───┐
        │inbox  │ │sur│  │aggreg │
        │refnry │ │vey│  │save   │
        │load   │ └─┬─┘  │summary│
        └───────┘   │    │contxt │
                    │    │loop   │
          ┌─────────┼─────────┐ └───────┘
          │         │         │
          ●         ●         ●     mol-polecat-arm (dynamic)
         ace       nux      toast
          │         │         │
       ┌──┴──┐   ┌──┴──┐   ┌──┴──┐
       │cap  │   │cap  │   │cap  │
       │ass  │   │ass  │   │ass  │
       │dec  │   │dec  │   │dec  │
       │exec │   │exec │   │exec │
       └──┬──┘   └──┬──┘   └──┬──┘
          │         │         │
          └─────────┴─────────┘
                    │
                 ⬣ base (cleanup)
```

## Phases

### PREFLIGHT (fixed steps)
1. inbox-check - Process lifecycle requests, help messages
2. check-refinery - Ensure MQ is alive and processing
3. load-state - Read persistent state (nudge counts, etc.)

### DISCOVERY (spawns dynamic arms)
4. survey-workers - List polecats, bond mol-polecat-arm per polecat
5. run-plugins - Bond mol-plugin-runner for each witness plugin

### CLEANUP (gate + fixed steps)
6. aggregate - GATE: WaitsFor all arms + plugins to complete
7. save-state - Persist nudge counts, action log
8. generate-summary - Create digest content
9. context-check - Check if context is high
10. burn-or-loop - Squash/burn wisp, then loop or exit

## Dynamic Arms

Each polecat gets mol-polecat-arm bonded as a wisp child:
- capture - Capture tmux output
- assess - Categorize state (working/idle/error/done)
- load-history - Get nudge counts for this polecat
- decide - Apply nudge matrix
- execute - Take action (nudge/kill/escalate/none)

Arms run in PARALLEL. The aggregate step waits for all to complete.

## Activity Feed

This design enables real-time visibility:

```
[14:32:08] + patrol-x7k.arm-ace bonded (5 steps)
[14:32:09] → patrol-x7k.arm-ace.capture in_progress
[14:32:10] ✓ patrol-x7k.arm-ace.capture completed
[14:32:14] ✓ patrol-x7k.arm-ace.decide completed (action: nudge-1)
[14:32:17] ✓ patrol-x7k.arm-ace COMPLETE
```

## Storage

- Wisp storage: .beads-wisp/ (ephemeral, gitignored)
- Persistent state: witness handoff bead (nudge counts, etc.)
- Digests: Squashed summaries in permanent beads

## Dependencies

- bd-xo1o: Dynamic Molecule Bonding epic (in beads rig)
  - bd mol bond with variable substitution
  - WaitsFor directive for fanout gates
  - Activity feed query

Labels: [template, christmas-ornament]


Move disk 5: C → A

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


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.


Formula execution: Spawn convoy from formula

Implement gt formula run <name>:
1. Load and parse formula
2. Create convoy bead (hq-cv-xxx)
3. For each leg, create child bead
4. Sling each leg to separate polecat with leg-specific prompt
5. Track leg completion via bead status
6. When all legs done, spawn synthesis polecat

Use existing gt sling and gt convoy infrastructure.