gt status: check daemon health first, attempt restart

If daemon not running, attempt to start it. If start fails, show warning but don't block status display. Currently falls back to slow direct mode silently.


Move disk 1: C → A

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


Add hook-singleton doctor check

Add gt doctor check to ensure each agent has at most one handoff bead.

Check: hook-singleton
Error if: Multiple pinned beads with same '{role} Handoff' title
Fix suggestion: Delete duplicate(s) with bd close


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol 47: All healthy


Merge: gt-5af.6

branch: polecat/Slit
target: main
source_issue: gt-5af.6
rig: gastown


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 16: All healthy


Move disk 2: B → A

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 2: all healthy, no incidents


Digest: mol-deacon-patrol

Patrol cycle 40: All healthy, 20 cycles complete - handoff per heuristic


gt convoy create/status/list commands

CLI for convoy management in Gas Town.

Commands:
- gt convoy create <name> <issues...> [--molecule <mol>] [--notify <addr>]
- gt convoy status [id]
- gt convoy list

Creates convoy beads in town-level beads (hq-* prefix).
Convoys track issues across project chains.

Depends on: bd-3roq (tracks relation), bd-hj0s (convoy type)
Related: hq-7h8jx (Convoy System epic in town beads)


Digest: mol-deacon-patrol

Patrol 121: All agents healthy, no incidents


Swarm package: Swarm, SwarmTask, SwarmState types

Define core swarm types.

## Types (in `internal/swarm/`)

```go
// SwarmState represents swarm lifecycle
type SwarmState string
const (
    SwarmCreated   SwarmState = "created"
    SwarmActive    SwarmState = "active"
    SwarmMerging   SwarmState = "merging"
    SwarmLanded    SwarmState = "landed"
    SwarmFailed    SwarmState = "failed"
    SwarmCancelled SwarmState = "cancelled"
)

// Swarm references a beads epic that tracks swarm work
type Swarm struct {
    ID          string      // matches beads epic ID
    RigName     string
    EpicID      string      // beads epic tracking this swarm
    BaseCommit  string      // git SHA all workers branch from
    Integration string      // integration branch name
    State       SwarmState
    CreatedAt   time.Time
    Workers     []string    // polecat names assigned
}

// SwarmTask represents a single task in the swarm (maps to beads issue)
type SwarmTask struct {
    IssueID   string  // beads issue ID
    Assignee  string  // polecat name
    Branch    string  // worker branch name
    State     string  // mirrors beads status
}
```

## Note

Swarm state is primarily stored IN beads. These types are in-memory representations for the SwarmManager to work with. No separate manifest.json files.


Digest: mol-deacon-patrol

Patrol 20 - handoff threshold reached


Digest: mol-deacon-patrol

Patrol 43: All healthy, 6 agents pinged


Digest: mol-deacon-patrol

Patrol 93: All healthy


Update architecture.md: Engineer role and Beads merge queue

Update docs/architecture.md with recent design decisions:

1. Agent table: Change "Refinery" role to "Engineer"
   - Refinery = place/module/directory
   - Engineer = role (agent that works in the Refinery)

2. Merge Queue section: Document Beads-native model
   - MRs are beads issues with --type=merge-request
   - gt mq commands (submit, list, next, process, reorder)
   - Ordering via depends-on links

3. CLI section: Add gt mq commands

4. Key Design Decisions: Add decisions for:
   - #15: Merge Queue in Beads
   - #16: Engineer role (distinct from Refinery place)
   - #17: Session restart protocol for Engineer


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 14


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]


Digest: mol-deacon-patrol

Patrol cycle 8: All healthy, 4 polecats active (furiosa, nux, rictus, slit)


Digest: mol-deacon-patrol

Patrol 4: 3 polecats working, all healthy


submit-merge

Submit to merge queue. Create branch if needed.
Verify CI passes.

gt done  # Signal work ready for merge queue

If there are CI failures, fix them before proceeding.

Depends: rebase-main


Merge: gt-qz2l

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


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'


Digest: mol-deacon-patrol

Patrol 20: All healthy. Handoff after 20 cycles.


Generate handoff summary

Summarize this patrol cycle for digest.

Include:
- Workers inspected (count, names)
- Nudges sent (count, to whom)
- Sessions killed (count, names)
- Escalations (count, issues)
- Issues found (brief descriptions)
- Actions pending for next cycle

This becomes the digest when the patrol wisp is squashed.


mol-deacon-patrol


Remove shell respawn loops from witness and deacon

Currently witness and deacon use shell loops (`while true; do claude; done`) to auto-respawn when Claude exits. This bypasses the proper lifecycle architecture.

## Current Behavior
- witness.go: ensureWitnessSession() wraps Claude in a shell loop
- deacon.go: runDeaconStart() wraps Claude in a shell loop
- When Claude exits, shell automatically restarts it

## Desired Behavior
- Agents should request lifecycle changes via LIFECYCLE mail to deacon
- Daemon processes lifecycle requests and handles restarts
- No shell loops - daemon and deacon's health-scan handle respawns

## Why Change
1. Shell loops bypass state verification (requesting_cycle flag)
2. Shell loops bypass handoff mail protocol
3. Shell loops make lifecycle tracking harder
4. Daemon already has infrastructure for this

## Migration
1. Remove shell loop from witness (daemon/deacon handles restart)
2. Remove shell loop from deacon (daemon handles restart via ensureDeaconRunning)
3. Verify daemon's health check properly restarts dead agents
4. Update templates if needed

## Risk
Low - we have gt witness restart and gt deacon restart as fallbacks


Per-epic config overrides: custom merge settings

Allow per-epic merge configuration overrides.

Epic can specify merge_config in its description:
  merge_config:
    run_tests: true
    test_command: 'go test -race ./...'
    on_conflict: assign_back

When processing MRs for an epic:
1. Load rig-level merge_queue config
2. Check if epic has merge_config
3. Merge epic config over rig config
4. Use merged config for processing

Use cases:
- Risky refactors: more thorough testing
- Urgent fixes: skip some checks
- Experimental work: different test suite

Reference: docs/merge-queue-design.md#per-epic-overrides


Merge: nux-mjxaphp6

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


Move disk 3: C → A

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


Digest: mol-deacon-patrol

Cycle 15: quiet, handoff for fresh context


Merge: toast-1767079830359

branch: polecat/toast-1767079830359
target: main
source_issue: toast-1767079830359
rig: gastown


gt polecat done should auto-stop running session

Currently 'gt polecat done' fails if session is running, requiring a separate 'gt session stop' first. This is unnecessary friction - done should just stop the session automatically since that's always what you want.


Create mol-install-go-binary molecule

Create a single-step molecule for building and installing the gt binary.

## Molecule Definition
\`\`\`markdown
## Molecule: install-go-binary
Single step to rebuild and install the gt binary after code changes.

## Step: install
Build and install the gt binary locally.

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

Verify the installed binary is updated:
\`\`\`
which gt
gt --version  # if we have version command
\`\`\`
\`\`\`

## Implementation
1. Add to builtin_molecules.go
2. Update SeedBuiltinMolecules to include it
3. Run gt molecule seed

## Acceptance
- [ ] mol-install-go-binary exists in beads
- [ ] Can be instantiated standalone
- [ ] Can be included by other molecules


Digest: mol-deacon-patrol

Patrol: mayor handoff (Batch 1 complete, notifications working), 5 polecats now active (Batch 2)


Merge: rictus-mjw1g7ny

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


Merge: cal-mjufugtb

branch: polecat/cal-mjufugtb
target: main
source_issue: cal-mjufugtb
rig: gastown


gt mol command tree: status, catalog, burn, squash

Add gt mol subcommand as agent-side API for molecule operations.

Commands needed:
- gt mol status - What's on my hook? (pinned molecule, current step, progress)
- gt mol catalog - List available protos (delegate to bd mol catalog)
- gt mol burn - Burn current attachment
- gt mol squash - Squash current molecule to digest

This completes the agent-side API and makes the docs (sling-design.md, propulsion-principle.md) match reality.

Blocks: deacon.md.tmpl update (can't use gt mol status until it exists)


Move disk 5: A → B

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


Move disk 2: B → A

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


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol cycle 23: All healthy, no incidents


#channel resolution for real-time broadcast

Wire tmux scanner into nudge system for #channel addresses.

## Deliverables

1. Parse #channel syntax in nudge:
   - #rig/gastown → nudge all running gastown agents
   - #town → nudge all running agents
   - #witnesses → nudge all running witnesses

2. Broadcast logic:
   - Resolve #channel to running sessions
   - Nudge each session
   - Ephemeral (no storage)

## Dependencies
- Tmux session scanner (gt-???)

## Acceptance
- #rig/gastown nudges all running gastown agents
- Ephemeral, no message storage
- Graceful handling of no-sessions


gt convoy create: Default --notify to mayor/

When Mayor creates a convoy, --notify should default to mayor/ since:
1. Mayor dispatched the work
2. Mayor should know when it lands
3. Reduces flag boilerplate

Implementation: Check actor identity, if mayor, default notify to 'mayor/'


Digest: mol-deacon-patrol

Patrol 17: All healthy


Move disk 1: A → B

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


Move disk 4: C → B

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

Patrol 10: 17 sessions


Digest: mol-deacon-patrol

Patrol cycle 10: All 6 agents healthy


Move disk 2: B → A

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


Move disk 1: A → B

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 55: All healthy


Beads daemon cache stale - hook queries return wrong data

Root cause: Beads daemon has stale data. Multiple bd daemons running (4 instances). When gt hook status queries via daemon, it gets old hooked bead. When queried with --no-daemon, correct bead is shown. This is a daemon cache coherence issue, not an ID resolution bug. Workaround: Use bd --no-daemon commands or restart daemons.


Exclude deacon from tmux rig count in status displays

Deacon is a town-level patrol agent, not a project rig. It shows up in tmux session counts alongside actual rigs (gastown, beads, wyvern), which is confusing.

Fix: Status/tmux reporting should exclude deacon from rig counts. Deacon is infrastructure, not a workspace.

Affected: Any status displays that count tmux sessions as rigs.


Human escalation path design

Flesh out the human escalation mechanism for Gas Town errors. Currently: errors mail Mayor, Mayor startup prompts about escalations. Need: structured escalation channel, escalation severity levels, and clear documentation. All edge cases in molecular algebra can write warnings to this channel.


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 4: C → B

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


Digest: mol-witness-patrol

Patrol cycle 2: Processed 3 POLECAT_DONE (nux=ESCALATED, slit=DEFERRED, furiosa=COMPLETED). Wrong-rig issue escalated to Mayor. All 3 gastown polecat sessions stopped.


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol cycle 15: All healthy.


Plugin: plan-oracle (work decomposition)

Plugin that helps decompose epics/issues into sub-tasks. Analyzes scope, identifies dependencies, estimates complexity for parallelization, creates beads for sub-tasks with dependency links.


Day 2.2: Remove PID/tmux state inference

Remove ZFC violations where Go infers state from signals:
- No more PID file checks
- No more tmux session parsing
- No more branch pattern analysis

Daemon becomes pure transport layer.

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

Parent: gt-d0jqp

Removed PID/tmux state inference from refinery Status(), witness Status(), daemon ensureDeaconRunning(), and daemon pokeDeacon(). Daemon now trusts agent bead state per ZFC. Removed 78 lines of inference code.


Merge: gt-caih

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


mol-deacon-patrol


Move disk 2: C → B

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


Refinery Engineer: Role prompting and CLAUDE.md

Create refinery/CLAUDE.md with Chief Merge Engineer role context. Include:
- Role identity and responsibilities
- Decision authority (merge order, test frequency, binary rebuilds)
- Communication patterns (Witness, Deacon)
- Session lifecycle (handoff bead protocol)
- Key commands reference


Review PR #51: fix: Use hq prefix for agent beads to match town beads database

Review PR #51. Check hq prefix usage is consistent. Approve with gh pr review --approve if good.


Witness: Block nuke if polecat has unpushed work

Witness nukes polecats on MERGED signal without checking if work is actually safe to delete.

## Problem
If witness receives MERGED for polecat X, it nukes X. But:
- MERGED might be for a stale MR (already merged via different path)
- Polecat might have NEW unpushed work since the MR was created
- Race condition between merge and nuke

## Fix
Before nuke, verify:
1. Get polecat's cleanup_status from agent bead
2. If cleanup_status != 'clean', escalate to Mayor instead of nuke
3. Optionally: verify the specific commit SHA is reachable from main

## Location
internal/witness/handlers.go HandleMerged() or the witness patrol formula


Digest: mol-deacon-patrol

Patrol 10: 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.


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-3cns
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Digest: mol-deacon-patrol

Patrol 2: All healthy, no messages, quiet cycle


Check Witness and Refinery health

Check Witness and Refinery health for each rig.

**ZFC Principle**: You (Claude) make the judgment call about what is "stuck" or "unresponsive" - there are no hardcoded thresholds in Go. Read the signals, consider context, and decide.

For each rig, run:
```bash
gt witness status <rig>
gt refinery status <rig>
```

**Signals to assess:**

| Component | Healthy Signals | Concerning Signals |
|-----------|-----------------|-------------------|
| Witness | State: running, recent activity | State: not running, no heartbeat |
| Refinery | State: running, queue processing | Queue stuck, merge failures |

**Tracking unresponsive cycles:**

Maintain in your patrol state (persisted across cycles):
```
health_state:
  <rig>:
    witness:
      unresponsive_cycles: 0
      last_seen_healthy: <timestamp>
    refinery:
      unresponsive_cycles: 0
      last_seen_healthy: <timestamp>
```

**Decision matrix** (you decide the thresholds based on context):

| Cycles Unresponsive | Suggested Action |
|---------------------|------------------|
| 1-2 | Note it, check again next cycle |
| 3-4 | Attempt restart: gt witness restart <rig> |
| 5+ | Escalate to Mayor with context |

**Restart commands:**
```bash
gt witness restart <rig>
gt refinery restart <rig>
```

**Escalation:**
```bash
gt mail send mayor/ -s "Health: <rig> <component> unresponsive" \
  -m "Component has been unresponsive for N cycles. Restart attempts failed.
      Last healthy: <timestamp>
      Error signals: <details>"
```

Reset unresponsive_cycles to 0 when component responds normally.


Move disk 2: C → B

Move disk 2 from peg C to peg B. (Move 234/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


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.


gt mail inbox: identity auto-detection fails for refinery

When running from ~/gt/gastown/refinery or ~/gt/gastown/refinery/rig, 'gt mail inbox' detects identity as 'mayor/' instead of 'gastown/refinery'.

Workaround: Use --identity flag explicitly:
  gt mail inbox --identity gastown/refinery

This breaks the refinery patrol because it can't see its MERGE_READY messages.

Expected: Running from gastown/refinery should auto-detect identity as gastown/refinery.

Related: The refinery has 9 unread MERGE_READY messages that aren't being processed because of this bug.


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 9: Routine


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

This proto enables nondeterministic idempotence for polecat work.
A polecat that crashes after any step can restart, read its molecule state,
and continue from the last completed step. No work is lost.

Variables:
- gt-qwyu - The source issue ID being worked on


Merge: furiosa-mjw349y2

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


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.


Merge: furiosa-mjtj9d4g

branch: polecat/furiosa-mjtj9d4g
target: main
source_issue: furiosa-mjtj9d4g
rig: gastown


Digest: mol-deacon-patrol

Patrol cycle 16: routine


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff cycle


Move disk 3: B → C

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


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

Patrol 7: All healthy


Move disk 1: A → B

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


gt feed: Activity feed command with tmux-aware modes

## Context

`bd activity` exists and works well for streaming beads mutation events. However:
- It's not discoverable via `gt` (the agent coordination CLI)
- No tmux-aware behavior for when Gas Town is running in tmux
- The planned TUI (gt-rivr) was tombstoned - need a simpler approach

## Requirements

### Without tmux (standalone mode)
- `gt feed` streams activity to stdout (like `bd activity --follow`)
- Supports filtering by rig, time window, event type
- Works in any terminal

### With tmux (integrated mode)
- Could open/attach to a dedicated activity pane
- Or provide a way to send feed to a specific pane
- Integrate with existing gt tmux session management

## Design Questions

1. **Command name**: `gt feed` vs `gt activity` vs `gt watch`?
2. **Tmux integration**: Dedicated pane? Split? Popup?
3. **Cross-rig aggregation**: Merge events from multiple rig daemons?
4. **Filtering UX**: By rig, by molecule, by event type?

## Implementation Options

**Phase 1: Simple wrapper**
- `gt feed` shells out to `bd activity --follow`
- Add `--rig` flag for filtering
- Works identically with/without tmux

**Phase 2: Tmux-aware**
- Detect if running in gt tmux session
- Offer to open in dedicated pane
- `gt feed --pane` to force pane mode

**Phase 3: Cross-rig** (if needed)
- Aggregate from multiple rig daemons
- Unified activity stream across town

## Related

- gt-rivr (tombstoned) - Original TUI epic
- gt-22ng - Activity aggregator (blocked)
- bd activity command - The underlying implementation


Merge: gt-a95

branch: polecat/Ace
target: main
source_issue: gt-a95
rig: gastown


Digest: mol-deacon-patrol

Patrol 19: routine


Move disk 1: C → A

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


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

Patrol 15: All healthy


Verify feed signal sources emit events

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

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

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


Digest: mol-deacon-patrol

Patrol 8: Mayor OK, 11 sessions


Daemon sending heartbeat to Mayor - should not

Daemon appears to be sending heartbeat messages to Mayor, but Mayor should not receive heartbeats. Observed at least once or twice - needs investigation to confirm and fix.


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

This proto enables nondeterministic idempotence for polecat work.
A polecat that crashes after any step can restart, read its molecule state,
and continue from the last completed step. No work is lost.

Variables:
- gt-1wmw - The source issue ID being worked on


Digest: mol-deacon-patrol

Patrol 9: All healthy


mol-deacon-patrol


Polecat Mood Plugin (standard)

Standard witness plugin molecule that assesses polecat emotional state.

## Molecule Definition

```json
{
  "id": "mol-polecat-mood",
  "title": "Assess mood for {{polecat_name}}",
  "description": "Analyze captured output and determine emotional state.\n\nVars:\n- {{polecat_name}} - The polecat to assess\n- {{captured_output}} - Recent tmux capture\n\nOutput: gt polecat mood {{polecat_name}} <emoji>",
  "labels": ["template", "plugin", "witness", "tier:haiku"],
  "issue_type": "task"
}
```

## Mood Emojis

```
😺 working     Active tool calls, making progress
😸 productive  Completing tasks, tests passing
🐱 idle        Waiting at prompt, no recent activity
😼 confident   Self-reviewing, about to submit
😿 struggling  Repeated errors, test failures
🙀 stuck       No progress for 10+ min
😽 done        Work complete, requesting shutdown
😾 blocked     Explicitly waiting on dependency
```

## Bonding

During witness patrol plugin-run step:

```bash
bd mol bond mol-polecat-mood $PATROL_WISP \
  --ref mood-{{polecat_name}} \
  --var polecat_name=ace \
  --var captured_output="$TMUX_CAPTURE"
```

## Installation

```bash
bd mol install mol-polecat-mood  # From Mol Mall
```

## Customization

Fork the molecule and modify description to change assessment criteria or add custom moods. Install your fork to override.


Move disk 2: B → A

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


Move disk 3: B → C

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


Digest: mol-deacon-patrol

Patrol #8: nominal


Digest: mol-deacon-patrol

Patrol cycle 12: All 3 rigs healthy. No incidents.


gt crew at fails to detect existing crew session

## Summary
`gt crew at` started a new Claude session instead of attaching to an existing one for the same crew worker.

## Reproduction
1. Have a crew worker (joe) running in gastown/crew/joe (PID 27526 on tty s030)
2. Run `gt crew at` from the same directory (gastown/crew/joe)
3. Expected: Attach to existing session on s030
4. Actual: Started a brand new Claude session (PID 67618 on s026)

## Evidence
```
# Old joe still running:
PID 27526 on s030: /Users/stevey/gt/gastown/crew/joe (started 10:22AM)

# New joe spawned by 'gt crew at':
PID 67618 on s026: /Users/stevey/gt/gastown/crew/joe (started 10:39AM)
```

## Impact
- Duplicate crew workers cause confusion
- User expected to attach to existing session, not spawn a second one
- The original session was still functional (just stuck in feed display)

## Likely cause
`gt crew at` probably doesn't check for running Claude processes in the crew directory before spawning a new one. It should:
1. Check for existing tmux sessions for this crew worker
2. Check for running `claude` processes with cwd matching the crew directory
3. If found, attach to existing session instead of spawning new one


ensure-refineries

Parallel container: Start all rig refineries.

## Execution
Children execute in parallel. Container completes when all children complete.

## Children
- ensure-gastown-refinery
- ensure-beads-refinery

## Verify
All child refinery steps pass verification.


Digest: mol-deacon-patrol

Patrol 11: All clear


Move disk 1: A → B

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


Merge: gt-3x0z.1

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


Move disk 7: B → C

Move disk 7 from peg B to peg C. (Move 960/1023)


Add molecules.jsonl as separate catalog file for template molecules


Fix N+1 query problem in convoy status fetching

getTrackedIssueStatus spawns a new bd show for each tracked issue. With 10 convoys x 5 issues = 50+ subprocesses every 10s. Consider batching or caching.


Digest: mol-deacon-patrol

Patrol 2: All healthy, 12 polecats, nudged gastown (active work)


Polecat Lifecycle Events: Refinery-Witness Coordination

## Problem

Polecat work completion is currently treated as a single event (MR submission), but the true completion is when the Refinery merges the work. This creates a lifecycle gap:

1. Polecat submits MR → considered "done" by Witness
2. But MR might fail to merge (conflicts, test failures)
3. No one notifies anyone when merge actually succeeds

## Solution: Two-Event Lifecycle

**Event 1: MR Submitted**
- `gt mq submit` notifies Witness
- Witness verifies submission was clean
- Polecat can go idle (but worktree retained)
- If submission had issues, Witness can help

**Event 2: MR Merged**
- Refinery sends `LIFECYCLE: work merged` to Witness
- Witness updates polecat state to `merged`
- Worktree now eligible for full cleanup/recycling

## Village Sibling Watch

For robustness, patrol roles check on their siblings:
- Refinery checks Witness via `gt peek`
- Witness checks Refinery via `gt peek`
- Creates defense in depth - if primary notification fails, someone catches it

## Recovery

If Refinery misses sending lifecycle notification:
- Witness polecat-scan can detect: polecat in mr_submitted but MR shows merged
- Deacon orphan-check can detect: merged MRs with stale polecats


orphan-check

Find abandoned work. Check for in_progress issues with no active agent.


Digest: mol-deacon-patrol

Patrol cycle 13: all healthy


Digest: mol-deacon-patrol

Patrol 112: All healthy


gt-gastown-polecat-furiosa

gt-gastown-polecat-furiosa

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-csbjj
role_bead: gt-polecat-role
cleanup_status: has_stash
active_mr: gt-lcuxo


Mail coordination should use town-level database

gt mail send/inbox should use ~/gt/.beads (town root) not rig-local beads. Cross-rig mail coordination (Witness <-> Mayor, polecat <-> Witness) needs to be in a shared location.


Resource Beads: Leases, locks, and quotas

Resource beads represent reserved resources. Types: vm, lock, slot, quota. Fields: holder, expires, renewable. Daemon monitors for expiry and manages contention.


Move disk 2: A → C

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


Request shutdown

Send shutdown request to Witness.
Wait for termination.

The polecat is now ready to be cleaned up.
Do not exit directly - wait for Witness to kill the session.


Replace WaitForClaudeReady with gt peek for steady-state agent observation

## Problem

WaitForClaudeReady uses regex to detect Claude's prompt, which is a ZFC violation.

## Architectural Fix

**Bootstrap (ZFC violation acceptable):**
During cold town startup, no AI is available. Regex to get Deacon online is acceptable.

**Steady State (proper ZFC):**
Once any agent is running, AI should observe AI:
- Deacon starting polecats → Deacon uses gt peek
- Deacon restarting → Mayor watches via gt peek
- Mayor restarting → Deacon watches via gt peek

## Implementation

1. Keep WaitForClaudeReady for daemon bootstrap only
2. Update gt deacon trigger-pending to use gt peek
3. Document bootstrap vs steady-state distinction


Digest: mol-deacon-patrol

Patrol cycle 28: All healthy, no incidents


BUG: Cross-beads slot references silently fail

When slinging work from town beads (hq-*) to a polecat whose agent bead is in rig beads (gt-*), the hook_bead update silently fails.

**Reproduction:**
```
# From mayor (town root):
gt sling hq-oosxt gastown/polecats/nux

# This runs (in updateAgentHookBead):
bd slot set gt-gastown-polecat-nux hook hq-oosxt
# FAILS: can't find hq-oosxt (different beads directory)
# Error is silently ignored!
```

**Result:**
- Agent bead keeps stale hook_bead value
- gt hook shows wrong/old work
- Agent doesn't know what they're actually assigned

**Root cause:**
sling.go line 812-814 silently ignores UpdateAgentState errors:
```go
if err := bd.UpdateAgentState(agentBeadID, "running", &beadID); err != nil {
    // Silently ignore - agent bead might not exist yet
    return
}
```

**Fix options:**
1. Log warnings instead of silent ignore
2. Support cross-beads slot references (store as 'hq-oosxt@town' or similar)
3. Use external: prefix for cross-beads hooks
4. Always store hook in the WORK bead's directory, not agent bead

Discovered during investigation of stale hook issue.


Digest: mol-deacon-patrol

Patrol 124: All healthy


Digest: mol-deacon-patrol

Patrol 10


Digest: mol-deacon-patrol

Patrol 3: All healthy, no incidents


Witness Patrol Molecule

Create mol-witness-patrol molecule for witness heartbeat loop.

Similar to DeaconPatrolMolecule but for per-rig witness duties.

## Steps
1. inbox-check - Process witness mail
2. survey-workers - List polecats, check status
3. inspect-workers - Capture pane output, assess state
4. plugin-run - Execute plugins from <rig>/plugins/witness/
5. decide-actions - Determine nudges, escalations
6. execute-actions - Send nudges, process shutdowns
7. context-check - Check own context, handoff if needed
8. loop-or-exit - Continue or cycle

The plugin-run step enables user customization of the patrol loop.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Digest: mol-deacon-patrol

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


Polecat template not found for non-gastown rigs

When adding a polecat to beads rig, warning shows:
  Warning: polecat template not found at /Users/stevey/gt/beads/mayor/rig/templates/polecat-CLAUDE.md

The template lookup should check the rig's template location, or fall back to a town-level default.


Digest: mol-deacon-patrol

Patrol cycle 7: All agents healthy


Digest: mol-deacon-patrol

Patrol 19: quick pass


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 363/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.

## 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


Self-review

Review your own changes. Look for:
- Bugs and edge cases
- Style issues
- Missing error handling
- Security concerns

Fix any issues found before proceeding.


Fanout gate runtime evaluation

Aggregate step uses waits-for: all-children. Deacon must evaluate this gate by checking if all dynamically-bonded arm children are complete. If no children bonded, gate passes immediately.


Merge: gt-ldk8

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


Digest: mol-deacon-patrol

Patrol #20: Final before handoff


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol 145: All healthy


Digest: mol-deacon-patrol

Patrol 20: healthy - handoff cycle


Digest: mol-deacon-patrol

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


Merge: gt-8v8

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


gt swarm: Not discovering tasks from epic dependents

gt swarm create/start shows '0 tasks loaded' even when epic has dependents.

Repro:
1. Create epic gt-hw6
2. Create tasks and add deps: bd dep add gt-xxx gt-hw6
3. gt swarm create gastown --epic gt-hw6 --worker Toast
4. Swarm shows 'Tasks: 0'

Expected: Swarm should discover tasks that depend on the epic.
Actual: Shows '(no tasks loaded)'


MR ID generation: prefix-mr-hash convention

Generate merge-request IDs following the convention: <prefix>-mr-<hash>

Example: gt-mr-abc123 for a gastown merge request.

This distinguishes MRs from regular issues while keeping them in the same namespace.
The hash should be derived from branch name + timestamp for uniqueness.

Implement: GenerateMRID(prefix, branch string) string

Reference: docs/merge-queue-design.md#id-convention


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)


Digest: mol-deacon-patrol

Cycle 13: quiet


gt-polecat-gastown-nux

gt-polecat-gastown-nux

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-2g130
role_bead: null


Merge: slit-1767059695613

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


Verify final state

All 10 disks now on peg C. Tower intact, all moves were legal.


Implement gt mol status command

Show what's on an agent's hook.

```bash
gt mol status [target]
```

Output:
- What's slung (molecule name, associated issue)
- Current phase and progress
- Whether it's a wisp
- Next action hint

If no target, shows current agent's status.

Acceptance:
- [ ] Read pinned bead attachment
- [ ] Display molecule/issue info
- [ ] Show phase progress
- [ ] Indicate wisp vs durable


Merge: dag-mjxm10sv

branch: polecat/dag-mjxm10sv
target: main
source_issue: dag-mjxm10sv
rig: gastown
agent_bead: gt-gastown-polecat-dag


Merge: furiosa-1767075886199

branch: polecat/furiosa-1767075886199
target: main
source_issue: furiosa-1767075886199
rig: gastown


Merge: dementus-mjxemx4j

branch: polecat/dementus-mjxemx4j
target: main
source_issue: dementus-mjxemx4j
rig: gastown
agent_bead: gt-gastown-polecat-dementus
Note: Session stopped without DONE - Witness cleanup


Digest: mol-deacon-patrol

Patrol 157 complete


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 801/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.

## Idle Town Principle

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

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

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

## Second-Order Monitoring

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

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


Move disk 3: A → B

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


Move disk 4: B → A

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


Bug: gt sling doesn't update agent bead hook_bead field

gt sling marks task as pinned with assignee, but doesn't update the agent bead's hook_bead field. Agent beads show hook_bead: null even after slinging. This prevents agents from knowing they have work on their hook.


Digest: mol-deacon-patrol

Patrol 94: All healthy


gt sling --on flag for wisp scaffolding

Add --on flag to gt sling for applying forms to existing work:
  gt sling shiny gastown/Toast --on gt-abc123

When --on is specified, implies --wisp (scaffolding existing work).
The form shapes execution of the target bead.


Digest: mol-deacon-patrol

Patrol 10: healthy


Digest: mol-deacon-patrol

Patrol cycle 76: All healthy


Merge: furiosa-1767084006859

branch: polecat/furiosa-1767084006859
target: main
source_issue: furiosa-1767084006859
rig: gastown


Move disk 2: B → A

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


Digest: mol-deacon-patrol

Patrol 13: all clear


Move disk 2: C → B

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


Move disk 1: C → A

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


Move disk 1: C → A

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


Merge: rictus-1767138835254

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


gt prime should detect mayor role from any rig's mayor/ folder

Currently gt prime only detects the Mayor role when run from town root (~/gt). It should also detect Mayor when run from:
- ~/gt/gastown/mayor/rig (rig's internal mayor dir)
- Any path containing /mayor/ under a rig

This would allow the mayor session to work correctly regardless of which rig directory it's attached to.


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.


context-check

Assess own context usage. If high, prepare for handoff.


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.


Task C: Second feature


Digest: mol-deacon-patrol

Patrol 40: all quiet


Witness patrol: stale MR queue detection needs state tracking

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

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

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

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


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.


Remove gt mail dependency on bd mail commands

Replaced bd mail send/inbox/read/ack with bd create/list/show/close. Messages are now stored as beads issues with type=message.


Move disk 4: C → B

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


mol-deacon-patrol


Merge: capable-mjw47ef9

branch: polecat/capable-mjw47ef9
target: main
source_issue: capable-mjw47ef9
rig: gastown
agent_bead: gt-gastown-polecat-capable


Move disk 3: B → C

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


Move disk 8: A → C

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


Digest: mol-deacon-patrol

Patrol 25: all quiet


Deacon patrol refactor: detect → dispatch

Refactor Deacon patrol to delegate heavy work to dogs:
- check-conditions → sling to dog (not inline execution)
- Pool maintenance step (spawn/retire/refresh)
- Completion mail handling from dogs
- Keep patrol lightweight (detection only)


Test issue 1 for displacement


Merge: gt-s7t1h

branch: polecat/dag-mjxm10sv
target: main
source_issue: gt-s7t1h
rig: gastown
agent_bead: gt-mayor


Digest: mol-deacon-patrol

Patrol 10: All clear


Digest: mol-deacon-patrol

Patrol cycle 8: all healthy


Digest: mol-deacon-patrol

Patrol 11: routine, all healthy


Digest: mol-deacon-patrol

Patrol 143 complete: All agents healthy


Verify witness patrol loop executes

Verify witnesses run their patrol formula:

1. Check witness session: `gt session status gastown/witness`
2. If not running: `gt session start gastown/witness`
3. Watch witness: `tmux attach -t gt-gastown-witness`
4. Verify it cycles through:
   - inbox-check
   - process-cleanups
   - check-refinery
   - survey-workers
   - context-check
   - loop-or-exit

Test for both rigs: gastown and beads.


Merge: gt-4u49x

branch: polecat/furiosa-mjxn8bl8
target: main
source_issue: gt-4u49x
rig: gastown
agent_bead: gt-gastown-polecat-furiosa


Move disk 1: A → B

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


Move disk 1: B → C

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


bd mol current: soft cursor showing current/next step

Add bd mol current command for molecule navigation orientation.

## Usage

bd mol current [mol-id]

If mol-id given, show status for that molecule.
If not given, infer from in_progress issues assigned to current agent.

## Output

You're working on molecule gt-abc (Feature X)

  [checkmark] gt-abc.1: Design
  [checkmark] gt-abc.2: Scaffold
  [checkmark] gt-abc.3: Implement
  [arrow] gt-abc.4: Write tests [in_progress] <- YOU ARE HERE
  [circle] gt-abc.5: Documentation
  [circle] gt-abc.6: Exit decision

Progress: 3/6 steps complete

## Key behaviors
- Shows full molecule structure with status indicators
- Highlights current in_progress step
- If no in_progress, highlights first ready step
- Works without explicit cursor tracking (inferred from state)

## Implementation notes
- Query children of mol-id
- Sort by dependency order
- Find first in_progress or first ready
- Format with status indicators

## Beads feature
This is a bd command - needs implementation in beads repo.


mol-deacon-patrol

Mayor's daemon patrol loop.

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

## Second-Order Monitoring

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

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


Digest: mol-deacon-patrol

Patrol 20: clear, handoff


Move disk 4: A → C

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


Merge: gt-5af.1

branch: polecat/Ace
target: main
source_issue: gt-5af.1
rig: gastown


Add NODE_OPTIONS crash logging to claude invocations

## Background

Investigation in bd-6df0 found that NODE_OPTIONS can enable Node.js crash reporting for Claude Code:

```bash
NODE_OPTIONS="--report-on-fatalerror --report-uncaught-exception --report-directory=$HOME/.claude/crash-reports"
```

## Proposal

Modify gt to set NODE_OPTIONS when spawning claude sessions. Key locations in gastown:

- `internal/cmd/up.go` - deacon, witness, crew, polecat spawning
- `internal/cmd/start.go` - refinery, crew spawning
- `internal/cmd/mayor.go` - mayor spawning
- `internal/cmd/handoff.go` - handoff respawning
- `internal/cmd/crew_helpers.go` - execClaude()
- `internal/daemon/lifecycle.go` - daemon-managed spawns

## Implementation

1. Create helper function to build NODE_OPTIONS string
2. Set env var before each claude invocation
3. Ensure ~/.claude/crash-reports/ directory exists
4. Optionally add `gt doctor` check to clean old reports

## Benefits

- Crash diagnostics without user config changes
- All gt-managed sessions automatically covered
- Reports available for debugging unexpected terminations


Digest: mol-deacon-patrol

Patrol cycle 17: all healthy


Move disk 1: C → A

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


Move disk 1: A → B

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


SessionStart hook should pass session_id to gt prime

## Context

The seance discovery system relies on session_start events emitted by gt prime.
Currently, gt prime falls back to actor-PID when CLAUDE_SESSION_ID is not set.

## Enhancement

The SessionStart hook receives session_id in its stdin JSON:
```json
{
  "session_id": "abc123",
  "transcript_path": "...",
  "source": "startup|resume|clear|compact"
}
```

The hook should parse this and pass it to gt prime via environment variable:
```bash
SESSION_ID=$(cat /dev/stdin | jq -r ".session_id")
CLAUDE_SESSION_ID=$SESSION_ID gt prime
```

## Benefits

- Accurate session tracking for seances
- Can resume exact sessions via `claude --resume <id>`
- Events correlate with Claude Code session history

## Implementation

1. Update SessionStart hook in CLAUDE.md templates
2. Have gt prime read CLAUDE_SESSION_ID env var (already done)
3. Emit proper session_id in session_start events

Related: gt-7qvd7 (seance implementation)


Digest: mol-deacon-patrol

Patrol 6: all healthy


Phase 4.2: Witness/Refinery patrol molecules

Extend ephemeral patrol pattern to Witness and Refinery.

## Witness Patrol Cycle

mol-witness-patrol-cycle:
1. scan-polecats: Check each polecat status
2. detect-stalls: Find stuck/idle polecats
3. nudge-or-escalate: Take action on stalls
4. log-status: Record cycle results
→ Squash with summary

## Refinery Patrol Cycle

mol-refinery-patrol-cycle:
1. scan-queue: Check merge queue
2. process-ready: Merge ready MRs
3. handle-failures: Deal with conflicts/failures
4. log-status: Record cycle results
→ Squash with summary

## Quiescent Mode

When no work: just log 'no activity' summary.
Witness and Refinery can sleep between cycles until triggered.


Implement await type handlers (gh:run, gh:pr, timer, human, mail)

Implement condition checking for each await type.

## Handlers Needed
- gh:run:<id> - Check GitHub Actions run status via gh CLI
- gh:pr:<id> - Check PR merged/closed status via gh CLI
- timer:<duration> - Simple elapsed time check
- human:<prompt> - Check for human approval (via mail?)
- mail:<pattern> - Check for mail matching pattern

## Interface
```go
type AwaitHandler interface {
    Check(awaitID string) (completed bool, result string, err error)
}
```

## Moved from beads
Originally bd-2l03. Deacon handlers belong in gastown.


Day 4.5: Test multi-step molecule lifecycle

Integration test (UPDATED for self-managed handoffs):
1. Sling work with molecule to polecat
2. Polecat works through all steps (self-handoffs as context fills)
3. Polecat calls gt done when work complete
4. Witness verifies clean state and sends MERGE_READY to refinery
5. Refinery merges branch
6. Refinery sends MERGED to witness
7. Witness calls gt polecat nuke for full cleanup
8. Verify clean state (no worktree, no branch, agent bead closed)

**VALIDATED**: rictus lifecycle worked end-to-end: gt done → witness → refinery → merged

Parent: gt-4a2qt


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.


Digest: mol-deacon-patrol

Patrol 5: all clear


CRITICAL: Merge formula CLI scaffold (gt-gpifj)

Commit 60da7926 (formula CLI scaffold) is on branch polecat/nux-mjw18ii8 but NOT merged to main. This blocks formula execution functionality. Main still has old formulas.go that just delegates to bd formula list.


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.


Test swarm epic


Merge: slit-mjtj9dc8

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


Epic: Patrol parity - Witness and Refinery match Deacon sophistication

Bring Witness and Refinery patrols up to Deacon's level of sophistication.

## Deacon has
1. Defined patrol molecule with clear steps
2. Wisp-based execution (spawn, run, squash, loop)
3. Daemon monitoring with auto-nudge on naked state
4. Handoff bead attachment mechanism
5. Banners for observability
6. Context-aware loop-or-exit

## Children
- gt-h1n5: Witness patrol: Add banners and wisp-based execution
- gt-qz2l: Refinery patrol: Add banners and wisp-based execution
- gt-poxd: Create handoff beads for Witness and Refinery roles

## Success criteria
- Tailing a Witness or Refinery session shows clear banners
- Patrols spawn as wisps and squash to digests
- Each role has a handoff bead with attached_molecule
- Daemon monitors Witness/Refinery nakedness (stretch goal)


Add bulk session stop command (gt session stop --all)

When decommissioning a rig, need to stop multiple sessions one at a time. A --all or --rig flag would allow: gt session stop --rig gastown


Digest: mol-deacon-patrol

Patrol 12: all quiet


Test message

Test body


Digest: mol-deacon-patrol

Patrol cycle 2: all healthy, no action required


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

This proto enables nondeterministic idempotence for polecat work. A polecat that crashes after any step can restart, read its molecule state, and continue from the last completed step. No work is lost.

## Variables

| Variable | Required | Description |
|----------|----------|-------------|
| issue | Yes | The source issue ID being worked on |


Digest: mol-deacon-patrol

Patrol cycle 10: All agents healthy


gt doctor: Add Boot health check (vet mode)

gt doctor should check Boot health:
- Is Boot directory present?
- Is Boot session alive?
- Last execution status (success/error)
- Marker file freshness

The vet checks on the dog.


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 19: All agents healthy


gt mq integration status: show integration branch status

Implement 'gt mq integration status <epic>' command.

Display:
- Integration branch name and creation date
- Commits ahead of main
- MRs merged to integration (closed)
- MRs pending (open, targeting integration)
- Comparison: main..integration/<epic>

Output example:
  Integration: integration/gt-auth-epic
  Created: 2025-12-17
  Ahead of main: 5 commits

  Merged MRs (3):
    gt-mr-001  Fix login timeout
    gt-mr-002  Fix session expiry
    gt-mr-003  Update auth config

  Pending MRs (1):
    gt-mr-004  Update auth tests (in_progress)

Reference: docs/merge-queue-design.md#integration-branches


Merge: gt-jhr85

branch: polecat/slit-mjxlyyte
target: main
source_issue: gt-jhr85
rig: gastown
agent_bead: gt-mayor


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)


Enhance Mayor CLAUDE.md with GGT milestone tracking

Update ~/ai/CLAUDE.md (Mayor startup context) with:

1. GGT Self-Hosting Milestone section
   - Track progress toward gt replacing town
   - Key blockers: gt-h5n (merge queue), gt-974 (daemon)
   - What "self-hosting" means (GGT working on itself)

2. Recent Architecture Decisions
   - Engineer = role, Refinery = place
   - Merge queue in Beads (not branch discovery)
   - Session restart protocol

3. Transition Plan
   - Current: use town commands (PGT)
   - Target: use gt commands (GGT)
   - Switch criteria: gt-b1g closed

Keep it concise - Mayor context should be quick to scan.


Digest: mol-deacon-patrol

Patrol 15: all healthy, doctor pass


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.


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


Boot needs CLAUDE.md and directory setup

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

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

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


Digest: mol-deacon-patrol

P11: stable


Move disk 1: C → A

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


Merge: gt-r6td

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


Digest: mol-deacon-patrol

Patrol 2: all agents healthy, no issues


Digest: mol-deacon-patrol

Patrol 10: Quiet


Merge: gt-pnv61

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


Digest: mol-deacon-patrol

Patrol 7: Interrupted, routine


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

Patrol 20: All healthy


Update config location: .gastown/ → config/

Move rig configuration from hidden .gastown/ to visible config/:
- config/rig.json: Rig configuration
- config/engineer.json: Engineer settings (test command, etc.)
- config/witness.json: Witness settings (heartbeat interval, etc.)

Hidden directories are poorly discovered by AI agents.


Digest: mol-deacon-patrol

Patrol 6: 3 rigs healthy


Merge: nux-1767079896198

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


Digest: mol-deacon-patrol

Patrol 6: routine, all healthy


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 13: clear


CI: GitHub Actions workflow for integration tests

Set up CI to run integration tests:

## Requirements
- Run on PRs touching: internal/cmd/install.go, internal/cmd/rig.go, internal/config/
- Use build tag: //go:build integration
- Timeout: 5 minutes max
- Cache Go modules

## Workflow structure
```yaml
name: Integration Tests
on:
  pull_request:
    paths:
      - 'internal/cmd/install.go'
      - 'internal/cmd/rig.go'
      - 'internal/config/**'
      - 'internal/routing/**'
jobs:
  integration:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
      - run: go test -tags=integration ./...
```


Merge: gt-x4ad3

branch: polecat/furiosa-mjxeatgb
target: main
source_issue: gt-x4ad3
rig: gastown
agent_bead: gt-gastown-polecat-furiosa


Merge: capable-mq

branch: polecat/capable-mq-events
target: main
source_issue: capable-mq
rig: gastown


Merge: dementus-1767073385126

attached_args: Code review this merge request

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


VC Pattern Integration: Bring validated ideas to Gas Town

Analysis of ~/src/vc identified 6 validated patterns from the 2nd orchestrator attempt that map cleanly to Gas Town primitives. VC achieved 254 issues closed, 90.9% gate pass rate, and 24 successful missions.

Key insight: VC built ~4300 lines of Go for features that become ~65 lines of YAML + CLI flags in Gas Town's architecture.

Child tasks track each pattern to integrate.


Digest: mol-deacon-patrol

Cycle 196: Nominal


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).


Move disk 2: C → B

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


TIDY UP: Your previous work (gt-odvf: bd mol CLI docs) wa...

TIDY UP: Your previous work (gt-odvf: bd mol CLI docs) was already merged to main. Check your git status is clean, sync beads, and if nothing to do, just run 'gt done'.


Merge: nux-1767080427756

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


Digest: mol-deacon-patrol

Patrol cycle 38: All healthy, no incidents


Digest: mol-deacon-patrol

Patrol 20: final check, all healthy, handoff threshold


Move disk 1: B → C

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


Move disk 2: B → A

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


Move disk 5: B → C

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


Add gt hook command (wrapper for bd hook)

Add a thin wrapper command `gt hook` that calls `bd hook` to inspect what's pinned to an agent's hook.

## Usage

```bash
gt hook                    # Show what's on current agent's hook
gt hook --agent deacon     # Show Deacon's hook
gt hook --agent gastown/furiosa  # Show polecat's hook
```

## Implementation

Thin wrapper in gt that:
1. Determines current agent identity
2. Calls `bd hook [--agent <name>]`
3. Formats output for gt context

## Why gt wrapper?

- Consistent with gt ecosystem (gt mail, gt status, etc.)
- Can add gt-specific context (session status, etc.)
- Easier discovery for gt users

## Related

- bd hook command (implemented by Dave)
- Chemistry UX design: gastown/mayor/rig/docs/chemistry-design-changes.md


Digest: mol-deacon-patrol

Patrol cycle 14: routine


Session ended: gt-gastown-slit


Digest: mol-deacon-patrol

Patrol 18: all healthy


Merge: furiosa-1767141944421

branch: polecat/furiosa-1767141944421
target: main
source_issue: furiosa-1767141944421
rig: gastown


Digest: mol-deacon-patrol

Patrol 17: Green


Digest: mol-deacon-patrol

Patrol 9: All green


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol cycle 13: All agents healthy


Move disk 2: A → C

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


Move disk 1: A → B

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


Move disk 1: B → C

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


Swarm beads naming convention and auto-filing

Beads naming convention for swarm lifecycle events.

## Bead IDs

- swarm-started:<swarm-id>     # Filed when swarm begins
- swarm-task-merged:<swarm-id>:<task-id>  # Filed per task merge
- swarm-landed:<swarm-id>      # Filed when merged to main
- swarm-failed:<swarm-id>      # Filed on unrecoverable failure

## swarm-started Bead

Filed by: Mayor/Refinery at swarm creation
Contains:
- Swarm title and description
- List of tasks (issue IDs)
- List of workers (polecat names)
- Base commit SHA

## swarm-task-merged Bead

Filed by: Refinery after each successful merge
Contains:
- Task issue ID and title
- Polecat name
- Merge commit SHA
- Test results summary

## swarm-landed Bead

Filed by: Refinery after landing to main
Contains:
- Final merge commit SHA
- Stats: tasks completed, time taken
- List of all merged task beads
- Integration branch name (now deleted)

## swarm-failed Bead

Filed by: Refinery on unrecoverable failure
Contains:
- Failure reason
- Tasks merged vs not merged
- Recovery guidance

## Why Beads (not just mail)

- Persistent, queryable, synced to git
- Other agents can check status without mail
- Creates audit trail
- Works when agents offline


Move disk 1: C → A

Move disk 1 from peg C to peg A. (Move 503/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.


Add merge queue observability

## Problem

The per-rig merge queue (refinery) lacks visibility into its operational state.
Operators can't easily tell:
- When the queue is backing up (items waiting)
- When it's empty/idle
- Queue depth over time
- Processing rate

## Requirements

- Surface queue depth (pending items count)
- Show current processing state (idle, processing, blocked)
- Indicate when queue is backing up (growing faster than draining)
- Make this accessible via `gt status` or similar command

## Possible Approaches

1. Add queue stats to `gt status` output
2. Create dedicated `gt mq status` command
3. Emit metrics/events that can be consumed
4. Add to witness monitoring scope


Fix convoy refresh scheduling causing duplicates

model.go:191-197 schedules both fetchConvoys() and convoyRefreshTick() on every update, potentially causing duplicate refreshes. The tick should only be scheduled once initially.


Digest: mol-deacon-patrol

Patrol 20: routine, handoff triggered


Merge: gt-rana.4

branch: polecat/ace
target: main
source_issue: gt-rana.4
rig: gastown


Digest: mol-deacon-patrol

Patrol: dave handoff (vision docs, 7 design gaps filed), furiosa tracer bullet on gt-oiv0, all agents up


Aspects: AOP cross-cutting concerns

Implement aspect-oriented composition:
- Define aspects with pointcuts and advice
- Apply aspects at bond time: bd bond mol --with-aspect security
- Pointcuts use glob patterns to match join points

Enables security-audit, logging, etc. as reusable concerns.


Move disk 3: A → B

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


Review: Refinery patrol template changes (gt-qz2l)

Polecat dementus implemented refinery template changes: banners, wisp-based execution, propulsion protocol. Review for correctness and consistency with witness/deacon patterns.


Digest: mol-deacon-patrol

Patrol 154: All healthy


gt handoff should accept full session paths like gastown/crew/max

Currently gt handoff only accepts role shortcuts like 'crew', 'witness', etc. and tries to auto-detect the rig/name from environment. User tried 'gt handoff gastown/crew/max' and got 'unknown session type'. Should parse paths like '<rig>/crew/<name>' or '<rig>/<role>' directly into session names like 'gt-<rig>-crew-<name>'.


Refinery agent: merge queue processing loop

The Refinery agent processes the merge queue, merging polecat work to main.

## Interface

```go
type Refinery struct {
    rig    *Rig
    queue  *MergeQueue
    git    *Git
    mail   *Mailbox
    config RefineryConfig
}

type RefineryConfig struct {
    AutoMerge     bool          // Auto-merge passing MRs
    RunTests      bool          // Run tests before merge
    TestCommand   string        // Command to run tests
    RequireReview bool          // Require review before merge (future)
}

func NewRefinery(rig *Rig, ...) *Refinery

// Lifecycle
func (r *Refinery) Start() error
func (r *Refinery) Stop() error
func (r *Refinery) IsRunning() bool

// Processing
func (r *Refinery) ProcessQueue() error
func (r *Refinery) ProcessMR(mr *MergeRequest) error
```

## Processing Loop

1. Check queue for pending MRs
2. For each pending MR:
   a. Fetch polecat branch
   b. Attempt merge to refinery/rig (local main)
   c. Run tests if configured
   d. If pass: push to origin, mark merged
   e. If fail: mark rejected, notify polecat
3. Sleep, repeat

## Merge Strategy

- Fast-forward when possible
- Merge commit when not
- On conflict: reject MR, polecat must rebase

## Test Integration

If tests configured:
```bash
cd refinery/rig
git merge polecat/branch
<test_command>  # e.g., go test ./...
```
Result determines merge/reject.

## Notifications

On merge success:
- Mail to polecat: "Your work merged"
- Update bead if issue tracked

On merge failure:
- Mail to polecat: "Merge failed: <reason>"
- Include conflict details if applicable

## Dependencies

Needs: Rig management, Git wrapper, Mail system, Merge queue


Witness role describes incorrect commands

prompts/roles/witness.md line 44 shows:
  gt polecat list {{ rig }}

But polecats are worktrees managed by Refinery/Mayor's clone,
not a separate polecat manager. The witness shouldn't manage
polecats directly.

Review and update witness role to match actual architecture.


mol-deacon-patrol


Merge: gt-lnji

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


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
```

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


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.


Evaluate pending async gates

Evaluate pending async gates.

Gates are async coordination primitives that block until conditions are met.
The Deacon is responsible for monitoring gates and closing them when ready.

**Timer gates** (await_type: timer):
Check if elapsed time since creation exceeds the timeout duration.

```bash
# List all open gates
bd gate list --json

# For each timer gate, check if elapsed:
# - CreatedAt + Timeout < Now → gate is ready to close
# - Close with: bd gate close <id> --reason "Timer elapsed"
```

**GitHub gates** (await_type: gh:run, gh:pr) - handled in separate step.

**Human/Mail gates** - require external input, skip here.

After closing a gate, the Waiters field contains mail addresses to notify.
Send a brief notification to each waiter that the gate has cleared.


Digest: mol-deacon-patrol

Patrol 7: 3 rigs healthy


Move disk 1: B → C

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


Move disk 2: B → A

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


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.


Digest: mol-deacon-patrol

Patrol 1: All healthy. 3 rigs, 6 agents pinged. No incidents.


Digest: mol-deacon-patrol

Patrol 2: 1 msg (Nux done), health OK


Merge: slit-mjw3n5iw

branch: polecat/slit-mjw3n5iw
target: main
source_issue: slit-mjw3n5iw
rig: gastown
agent_bead: gt-gastown-polecat-slit


Digest: mol-deacon-patrol

Patrol cycle 51: All healthy


gt doctor: detect tmux session anomalies (linked panes, etc.)

Add a tmux health check to gt doctor that detects:

1. **Linked panes between sessions** - The bug where gt-deacon and gt-mayor shared pane @283, causing heartbeat crosstalk
2. **Session naming anomalies** - Sessions that don't match expected patterns
3. **Orphaned panes** - Panes in gt-* sessions with no running process

Detection approach:
- List all gt-* sessions
- For each session, get window/pane IDs
- Check for duplicate pane IDs across different sessions
- If found, report which sessions are linked and suggest fix

Auto-fix: Could offer to kill and recreate the offending session.

Reference: gt-rt6g documented a case where this caused the daemon's Deacon heartbeats to appear in the Mayor's input, eating user prompts.


Move disk 3: A → B

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


Default crew name should be something better than 'main'

When creating a new rig, the default crew worker name is 'main'. This is confusing since:

1. 'main' is also the git branch name
2. It doesn't convey that this is the user's personal workspace
3. Crew names should feel more personal/distinct

Consider alternatives like:
- 'home' - the user's home base
- 'desk' - their personal desk
- 'joe/max/etc' - actual name-based defaults
- Let user pick during rig init


Formula SDK: Developer Tooling for Workflow Authors

SDK for creating, testing, debugging, and validating formulas.

## Components

### Forge (Creation)
```bash
mol forge new my-workflow        # Scaffold new formula
mol forge extend base-workflow   # Create variant
mol forge lint my-workflow       # Check syntax/style
```

### Lab (Testing)
```bash
mol lab run my-workflow --dry-run   # Mock execution
mol lab test my-workflow            # Run formula tests
mol lab trace my-workflow           # Step-through debug
```

### Validator (Verification)
```bash
mol validate my-workflow                    # Check well-formedness
mol validate my-workflow --protocol=Reviewable  # Check protocol compliance
mol validate my-workflow --schematic=shiny  # Check schematic compatibility
```

### Analyzer (Static Analysis)
```bash
mol analyze my-workflow --deps     # Dependency graph
mol analyze my-workflow --coverage # Step coverage
mol analyze my-workflow --cycles   # Detect cycles
```

## Relationship to Other Concepts

The SDK operates on:
- Formulas (source level)
- Protos (compiled level)
- Molecules (runtime level)

And validates against:
- Protocols (type system)
- Schematics (domain composition)

## Open Questions

1. Bundled vs separate - mol subcommands or formula-kit binary?
2. IDE integration - LSP for formula files?
3. Test harness - how to mock steps? fixtures?

## Related

- docs/formula_evolution.md - "SDK Question" section
- gt-8tmz.30 - Proto debugging tools (subset)
- gt-8tmz.31 - Formula validation (subset)


Add workspace metadata file (.town.json)

Create ~/gt/.town.json with owner email, workspace name, and public name. Anchors workspace to entity identity for federation.


Merge: gt-rana.3

branch: polecat/dementus
target: main
source_issue: gt-rana.3
rig: gastown


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-ie33
bonded_ref: arm-toast
bonded_at: 2025-12-23T10:00:00Z


Move disk 1: A → B

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


gt-gastown-polecat-slit

gt-gastown-polecat-slit

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-bho9
role_bead: gt-polecat-role
cleanup_status: clean
active_mr: gt-1kuox
notification_level: null


Move disk 1: C → A

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


gt spawn pins mol-polecat-work

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

## Current Behavior

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

## New Behavior

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

## Molecule Bonding

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

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

## Hook Pinning

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

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

## Files

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


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 387/1023)


Update Hanoi formula with agent-actionable instructions

Update towers-of-hanoi.formula.toml description to include:
- Clear execution protocol for agents
- What each step means
- What to do on resume
- Explicit DO/DO NOT guidance


Merge: nux-1767075895486

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


Digest: mol-deacon-patrol

Patrol cycle 5: all healthy


Move disk 2: B → A

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


Witness: instantiate mol-witness-patrol on start

When witness starts, create a mol-witness-patrol instance and pin it to the witness hook.

## Changes to witness/manager.go

In Start() or run():
1. Check if patrol instance exists on hook
2. If not, call beads.InstantiateMolecule(mol-witness-patrol, handoffBead)
3. Store instance ID for later reference

## Hook Structure

The witness handoff bead gets:
- attached_molecule: gt-patrol-xyz
- attached_at: timestamp

## Idempotency

If patrol already exists (from previous session), reuse it.
Don't create duplicate instances on restart.


Refinery: Implement mechanical rebase in-place

Update refinery to handle mechanical rebases without dispatching.

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

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

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

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


Move disk 1: B → C

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


Move disk 1: C → B

Move disk 1 from peg C to peg B.


bd mol search: Find formulas using GitHub API

Search for formulas across GitHub.

Usage: bd mol search <query>

Should:
- Use GitHub API to search repos with formula.json
- Filter by topics (e.g., beads-formula)
- Display results with descriptions and stars
- Support pagination


Move disk 1: C → A

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


mol-deacon-patrol


Dynamically discover rigs in checkStaleAgents

In internal/daemon/lifecycle.go:734-735, the rig list is hardcoded:

```go
// Add rig-specific agents (witness, refinery) for known rigs
// For now, we check gastown - could be expanded to discover rigs dynamically
rigs := []string{"gastown", "beads"}
```

This should use gt rigs or similar to dynamically discover configured rigs instead of hardcoding.

Affects: checkStaleAgents() which checks for dead agents that stopped updating their bead state.


Move disk 5: B → C

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


Pinned beads should appear first in mail inbox

Currently bd mail inbox sorts by priority then date, but pinned beads (handoff context) should always appear at the top.

**Current behavior:**
- Pinned beads mixed in with regular mail based on priority/date

**Expected behavior:**
- Pinned beads always first in inbox (before priority sorting)
- This enables handoff beads to be the default first item an agent sees

**Implementation:**
1. In mail.go runMailInbox(), after filtering, sort pinned beads to top
2. Within pinned and non-pinned groups, maintain priority/date sort

**Related:**
- gt-r8ej: Implement pinned beads for handoff state
- gt-8h4: Pinned Beads epic

**Acceptance criteria:**
- bd mail inbox shows pinned beads first
- Pinned beads still sorted by priority/date among themselves
- Non-pinned mail sorted normally after pinned section


Digest: mol-deacon-patrol

Patrol cycle 11: All 6 agents healthy


Digest: mol-deacon-patrol

Patrol 3: all clear, hook fix applied


Merge: gt-3x0z.2

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


Phase 4.1: mol-deacon-patrol uses ephemeral

Deacon patrol cycles run as ephemeral molecules.

## Current Deacon Loop

```
while running:
    check_heartbeat()
    check_mail()
    sleep(interval)
```

## Molecule-Based Loop

```
while running:
    mol = bd mol bond mol-deacon-patrol-cycle --ephemeral
    execute_cycle(mol):
        check_heartbeat()
        check_mail()
        log_status()
    summary = generate_cycle_summary()
    bd squash mol --summary summary
    sleep(interval)
```

## Benefits

- Each cycle is tracked
- Digests show daemon health over time
- Can query: 'show me patrol cycles from last hour'
- Crash mid-cycle → ephemeral shows where we were


Digest: mol-deacon-patrol

Patrol cycle 18: routine


Update gt doctor to check new config locations

Doctor should validate new structure:
- Check mayor/config.json exists and is valid
- Check settings/ exists for each rig
- Warn if old .gastown/ files still exist
- Offer --fix to migrate old locations to new


Move disk 1: B → C

Move disk 1 from peg B to peg C. (Move 657/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.


Move disk 1: B → C

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


Move disk 1: C → A

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


Move disk 3: C → A

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


Mol Mall: Formula marketplace using GitHub as backend

Create a marketplace for sharing molecule formulas using GitHub repos as the hosting backend.

## Architecture

Formulas ──cook──→ [ephemeral proto] ──pour/wisp──→ Mol/Wisp
    ↑                                                    │
    └────────────────── distill ─────────────────────────┘

- Formulas: JSON source files (.formula.json) - the thing you share
- Protos: Transient compilation artifacts - auto-deleted after use
- Mols/Wisps: Execution instances - not shared directly

## Key operations
- bd distill <mol-id> → Extract formula from completed work
- bd mol publish <formula> → Share to GitHub
- bd mol install <url> → Fetch from GitHub
- bd pour <formula> → Cook and spawn (proto is ephemeral)

## Migrated from beads rig (bd-1dez)
Completed: distill, formula add, versioning, installation tracking
Remaining: install, update, search, publish


gt sling: Support batch slinging multiple beads

Currently `gt sling` only accepts one bead at a time:

```
gt sling gt-abc gastown        # works
gt sling gt-abc gt-def gastown # fails: accepts between 1 and 2 arg(s)
```

## Proposed

Allow multiple beads in a single command:
```
gt sling gt-abc gt-def gt-ghi gastown
```

This would spawn a polecat for each bead (or reuse existing ones).

## Use case

Slinging related work from a convoy - want to parallelize without running gt sling N times manually.


Review: Beads Universal Data Plane documentation

Review new docs/beads-data-plane.md (275 lines) for accuracy.

## Commit
- 54c8269: Add Beads Universal Data Plane documentation

## Review focus
- Accuracy of beads architecture description
- Correct field mappings (mail → beads fields)
- Two-level architecture (town vs rig beads) correctly explained


Digest: mol-deacon-patrol

Patrol 1: inbox clear, gates clear, no pending spawns, witnesses/refineries healthy, no orphans


Digest: mol-deacon-patrol

Patrol #13


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.


Digest: mol-deacon-patrol

Patrol 2: All healthy, routine


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 12: nominal


Merge: rictus-mjw3nj1a

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


Digest: mol-deacon-patrol

Patrol 19 complete


Digest: mol-deacon-patrol

Cycle 10: quiet


Move disk 1: A → B

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


Move disk 3: A → B

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


Nudge newly spawned polecats

Nudge newly spawned polecats that are ready for input.

When polecats are spawned, their Claude session takes 10-20 seconds to initialize. The spawn command returns immediately without waiting. This step finds spawned polecats that are now ready and sends them a trigger to start working.

**ZFC-Compliant Observation** (AI observes AI):

```bash
# View pending spawns with captured terminal output
gt deacon pending
```

For each pending session, analyze the captured output:
- Look for Claude's prompt indicator "> " at the start of a line
- If prompt is visible, Claude is ready for input
- Make the judgment call yourself - you're the AI observer

For each ready polecat:
```bash
# 1. Trigger the polecat
gt nudge <session> "Begin."

# 2. Clear from pending list
gt deacon pending <session>
```

This triggers the UserPromptSubmit hook, which injects mail so the polecat sees its assignment.

**Bootstrap mode** (daemon-only, no AI available):
The daemon uses `gt deacon trigger-pending` with regex detection. This ZFC violation is acceptable during cold startup when no AI agent is running yet.


Move disk 1: B → C

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