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


Merge: gt-si8rq.4

branch: polecat/rictus-mjxaq6fm
target: main
source_issue: gt-si8rq.4
rig: gastown
agent_bead: gt-gastown-polecat-rictus


Add 'spawn' as alias for 'start' subcommand across all roles

Agents are guessing 'spawn' when trying to start roles (witness, refinery, etc). Need to add 'spawn' as an alias for 'start' for consistency.

Affected commands:
- gt witness start → also gt witness spawn
- gt refinery start → also gt refinery spawn
- gt polecat start → also gt polecat spawn
- gt crew start → also gt crew spawn

Implementation: Add Aliases field to cobra commands.


Move disk 1: C → A

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


mol-deacon-patrol


Extract timing constants to constants package

Extract hardcoded timing values to named constants.

## Files to modify
- internal/constants/constants.go (add constants)
- internal/cmd/start.go (use constants)
- internal/tmux/tmux.go (use constants)

## Implementation
Add to constants.go:
```go
const (
    ShutdownNotifyDelay  = 500 * time.Millisecond
    ClaudeStartTimeout   = 15 * time.Second
    ShellReadyTimeout    = 5 * time.Second
    DefaultDebounceMs    = 100
    DefaultDisplayMs     = 5000
)
```

## Acceptance criteria
- [ ] 5 timing constants added to constants.go
- [ ] start.go uses ShutdownNotifyDelay, ClaudeStartTimeout, ShellReadyTimeout
- [ ] tmux.go uses DefaultDebounceMs, DefaultDisplayMs
- [ ] go build ./... passes
- [ ] go test ./... passes


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.


Update gastown to use 'ephemeral' instead of 'wisp' terminology

After beads renames 'wisp' to 'ephemeral' (bd-o18s), update gastown code:

- patrol_helpers.go: bd wisp create → bd ephemeral create (or new API)
- doctor/wisp_check.go: rename to ephemeral_check.go
- All references to Wisp field → Ephemeral

Depends on: bd-o18s


gt-polecat-gastown-slit

gt-polecat-gastown-slit

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


Digest: mol-deacon-patrol

Patrol complete: fixed EMERGENCY clone divergence (zoey 103 behind, refinery 40 behind), cleaned orphan processes, created patrol molecules, fixed invalid hook attachments


Merge: slit-mjtnyszt

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


TODO: Detect cycles in molecule dependency graph

molecule.go:302 has a TODO to detect cycles in the dependency graph. Currently, cyclical dependencies could cause issues.


Speed up test suite

Tests are running slow during MQ processing. Investigate and optimize:
- Profile test execution time
- Look for slow tests (network, file I/O, sleeps)
- Consider parallel test execution
- Cache expensive setup where possible


Digest: mol-deacon-patrol

Patrol 90: All healthy


gt polecat remove --all: bulk polecat teardown

Currently gt polecat remove only accepts one polecat at a time. Need bulk operations:

## Requested
- `gt polecat remove gastown --all` - remove all polecats from a rig
- `gt polecat remove gastown/A gastown/B ...` - remove multiple by name

## Context
After a swarm completes, tearing down 20 polecats one at a time is tedious.
Ephemeral workers should be easy to create and destroy in bulk.

## Related
- gt-c92: CLI: all command for batch polecat operations


gt-gastown-polecat-capable

gt-gastown-polecat-capable

role_type: polecat
rig: gastown
agent_state: running
hook_bead: gt-rbncw
role_bead: gt-polecat-role
cleanup_status: clean
active_mr: gt-i1woc
notification_level: null


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 8 complete. All healthy.


ApplyBranches/ApplyGates mutate steps in place

ApplyBranches and ApplyGates claim to return a modified steps slice, but they actually mutate the original steps via the pointer map from buildStepMap().

```go
// ApplyBranches docstring says:
// Returns the modified steps slice (steps are modified in place for dependencies).
```

This is technically documented but violates the pattern established by ApplyLoops and ApplyAdvice which return new step slices.

Options:
1. Document explicitly that these functions mutate in place (current behavior)
2. Clone steps before modification for true immutability
3. Accept this as intentional since it's an optimization

The current behavior is safe because cook.go doesn't reuse the input slice, but could cause subtle bugs if callers expect immutability.

Recommend option 1 (document) or 2 (clone) for consistency.


Digest: mol-deacon-patrol

Patrol 3: All healthy, MQ 1 pending


Remove all hardcoded gastown dependencies from gt codebase

The Go codebase should not have hardcoded dependencies on gastown (the rig name).

Found in prime.go outputDeaconPatrolContext() - FIXED in this session.

Other potential issues to audit:
- Check all patrol context functions (Witness, Refinery) for similar patterns
- Ensure rig-specific paths are derived from context, not hardcoded
- Test with a different rig name to verify

The principle: Gas Town should work with any rig name, not just gastown.


Digest: mol-deacon-patrol

Patrol cycle 8


Digest: mol-deacon-patrol

Patrol cycle 14: All agents healthy


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.


Move disk 4: C → B

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


Digest: mol-deacon-patrol

Patrol 2 complete: all healthy, no issues


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol cycle 9: routine, healthy


Digest: mol-deacon-patrol

Patrol 206: All nominal


Move disk 1: C → A

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


Code Review Convoy formula (first formula implementation)

## First Formula: Code Review Convoy

Implement the code review formula as proof of concept for formula molecules.

### Input
- PR number, branch, or file list

### Legs (parallel polecats)
| Leg | Focus | Output |
|-----|-------|--------|
| correctness | Logic errors, edge cases, off-by-ones | findings.md |
| performance | Bottlenecks, O(n²), allocations | findings.md |
| security | Injection, auth, data exposure | findings.md |
| elegance | Design clarity, abstractions | findings.md |
| resilience | Error handling, retries, timeouts | findings.md |
| style | Conventions, naming, formatting | findings.md |
| smells | Anti-patterns, god objects, coupling | findings.md |

### Synthesis
- Read all leg findings
- Deduplicate overlapping issues
- Prioritize by severity
- Produce unified review with sections

### Command
```bash
gt formula run code-review --pr=123
# Creates convoy hq-cv-xxx
# Spawns 7 polecats + 1 synthesis
# Lands with review-summary.md
```

### Implementation Steps
1. Define formula schema in beads
2. gt formula run command
3. Leg prompt templates
4. Output collection mechanism
5. Synthesis polecat spawning
6. Result attachment to convoy bead


Digest: mol-deacon-patrol

Patrol cycle 48: All healthy


Move disk 8: A → C

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


Digest: mol-deacon-patrol

Patrol 8: All clear


Digest: mol-deacon-patrol

Patrol 18: healthy


Move disk 1: C → A

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


Digest: mol-deacon-patrol

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


Move disk 6: A → C

Move disk 6 from peg A to peg C. (Move 416/1023)


Move disk 3: A → B

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


Test Patrol Parent

[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.

Original description:
Test parent for Christmas Ornament pattern


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.


gt crew add: CLAUDE.md customization leaves git dirty

When gt crew add generates a customized CLAUDE.md for crew workers, it differs from the repo version (Crew Worker Context vs Polecat Context, personalized footer). This leaves the git state 'dirty'.

Options:
1. Add CLAUDE.md to .gitignore in crew workspaces
2. Auto-commit the customized CLAUDE.md locally
3. Store crew CLAUDE.md content elsewhere (e.g., .claude/CLAUDE.md)

Current behavior is functional but 'gt crew list' shows 'Git: dirty' for new crew.

Found during: adding crew workers grip, fang, wolf


Idle polecats are a Gas Town bug - investigate and fix

## Bug: Idle Polecats

Polecats are completing work and sitting idle instead of being cleaned up.

## Root Cause Analysis

### Current State
- 5 gastown polecats: sessions active, NO hook, finished work, submitted MRs
- Witness has **50 unread messages** including POLECAT_DONE and MERGED signals
- Witness is idle saying "All 6 polecats idle. System cycling efficiently."
- Polecats at Claude prompt waiting → burning money

### Protocol Flow (Design)
1. Polecat runs `gt done` → sends POLECAT_DONE to Witness, creates MR bead
2. Refinery processes MR bead, merges, sends MERGED to Witness
3. Witness receives MERGED, verifies clean state, nukes polecat

### What's Broken
**Witness is not processing its mail inbox.**

The Witness Claude agent is supposed to patrol: check inbox, process protocol messages, nuke completed polecats. But it's sitting idle at a prompt instead.

Symptoms:
- Polecats finish work → sit at prompt waiting for death
- MERGED signals pile up in Witness inbox (unprocessed)
- Sessions burn money while waiting
- No cleanup happens

### Design Philosophy Violation

From `propulsion-principle.md`:
> Gas Town is a steam engine. Agents are pistons that MUST fire.

Idle polecats violate this - they're stalled pistons. The design says polecats should be ephemeral: spawn → work → die. No idle state.

## Recommendations

### Option 1: Self-Terminating Polecats (Recommended)
After `gt done`, polecat should exit Claude session immediately. No waiting for Witness.
- Add `--exit` flag to `gt done` that runs `/exit` after submitting MR
- Witness nukes worktree later when processing MERGED (session already gone)

**Pros**: No idle sessions, no burning money
**Cons**: Minor race condition if nuke runs while session exiting

### Option 2: Witness Polling Daemon
Replace Claude-based Witness with a daemon that polls MR queue and nukes polecats.
- Not dependent on Claude session patrol loops
- More reliable but loses Claude intelligence

### Option 3: Fix Witness Patrol
Make Witness actually patrol continuously instead of stopping.
- Strengthen template to emphasize continuous mail processing
- Risk: Claude agents still forget/ignore instructions

## Immediate Fix

For now: Mayor or user must manually nudge Witness or nuke idle polecats.

```bash
# Check idle polecats
gt polecat list gastown

# Manual nuke (if verified clean)
gt polecat nuke gastown/dementus
```

## Related Issues
- Witness patrol loop reliability
- gt done should self-terminate
- Protocol message handling automation


Merge: morsov-dogs

branch: polecat/morsov-dogs
target: main
source_issue: morsov-dogs
rig: gastown


Agent scanner utility for filesystem

Filesystem scanner to discover agent directories in a rig or town.

## Deliverables

1. Function: ScanRigAgents(rigPath) -> []AgentAddr
   - Finds: witness/, refinery/, crew/*, polecats/*
   - Returns normalized addresses (e.g., "gastown/witness")

2. Function: ScanTownAgents(townPath) -> []AgentAddr
   - Iterates all rigs, calls ScanRigAgents for each
   - Returns all agent addresses in town

3. Alias resolution:
   - @rig/gastown → ScanRigAgents("gastown")
   - @town → ScanTownAgents()
   - @witnesses → filter for */witness across all rigs
   - @crew/gastown → filter crew/* in gastown

## Location
internal/discovery/scanner.go (new package)

## Acceptance
- Scanner finds all agent types
- Alias patterns resolve correctly
- Unit tests pass


Digest: mol-deacon-patrol

Patrol 141 complete: All agents healthy, no incidents, no orphans


Patrol Exponential Backoff System

Cost-saving await-signal model for patrol agents.

## The Problem

Patrol agents (witness, refinery) poll continuously even when idle, burning API credits.

## The Solution: Await-Signal

Agents don't poll constantly. They **wait for a signal**, then **discover reality**.

```
PATROL LOOP:
    await-signal (just wake me)
         ↓ awake
    check-reality (mail, beads, hook, git)
         ↓
    work found? → DO WORK → loop
         ↓ no
    increase backoff → loop
```

**Key principle (ZFC-aligned):** Signal carries no semantic meaning - just 'wake up'.
Agent discovers what to do by examining reality.

## Two-Level Wake

| Level | State | Command |
|-------|-------|---------|
| 1 | Running (backoff) | `gt nudge` clears backoff |
| 2 | Asleep | `gt rig boot` starts session |

**Boot+nudge pattern:**
```bash
gt rig boot <rig>              # Wake if asleep (idempotent)
gt nudge <rig>/witness 'wake'  # Clear backoff if running
```

## Backoff Curve

Base: 30s → 60s → 120s → 240s → ... → 10min cap

Resets on: nudge received, work found, deacon ping.

## Reference

See ~/gt/docs/patrol-system-design.md (Await-Signal Model section)


Move disk 1: A → B

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


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

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

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

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

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

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

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


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol 10: All healthy


Digest: mol-deacon-patrol

Patrol 38: all quiet


Move disk 2: B → A

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


Day 4.4: Witness calls nuke after MERGED signal

When refinery sends MERGED:
1. Witness receives MERGED mail
2. Witness calls gt polecat nuke
3. Full sandbox cleanup
4. Agent bead removed

Parent: gt-4a2qt


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

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


Digest: mol-deacon-patrol

Patrol 11: routine


gt mq reject: manual MR rejection

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

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

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

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


Polecat template: condense Work Protocol section

The Work Protocol section summarizes the entire mol-polecat-work molecule. This is too verbose and will go stale as the molecule evolves. Condense to essential guidance only, let the molecule itself provide the steps.


Digest: mol-deacon-patrol

Patrol 9: quiet


Witness cleanup should know worktree parent repo

Witness had to discover that polecat worktrees are created from mayor/rig, not the rig root.

## Problem
When cleaning up polecat/tracer:
- Witness ran git worktree remove from gastown/ - failed
- Had to discover worktree was from mayor/rig
- Then removed correctly

## Improvement
Witness should know the worktree parent repo path (mayor/rig) and clean up from there directly.

## Evidence
Tracer bullet 2025-12-23: Witness took extra steps to figure out cleanup path.


Move disk 1: C → A

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


Move disk 2: A → C

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


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.


Merge: dementus-1767087772272

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


Implement

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

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


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Cycle 11


Digest: mol-deacon-patrol

Cycle 7


Move disk 1: C → A

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


gt up: set BD_ACTOR env var when spawning agents

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

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

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

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


Phase 2: Awareness and real-time channels (announce:, #channel)

## Scope

Extensions for awareness broadcasting and ephemeral real-time communication.

### Deliverables

1. **announce:name** - Shared single-copy bulletin board
   - Informational, not work-creating
   - Recipients check when convenient, missing is OK
   - Use case: 'Bob is refactoring logging, be aware'
2. **#channel resolution** - Dynamic tmux scan for running agents
   - #rig/gastown → tmux sessions matching gastown/*
   - #town → all Gas Town sessions
3. **gt channel publish** - Ephemeral nudge broadcast to channel

### Key semantics
- announce: shared copy (1 message, N readers) vs list: (N copies, N obligations)
- #channel ephemeral - no storage, real-time only
- Channels resolve against running sessions, not filesystem


Merge: slit-mjtj9dc8

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


Merge: gt-8v8

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


Digest: mol-deacon-patrol

Patrol cycle 8: All 6 agents healthy


Refactor: Extract common manager creation boilerplate

Five nearly identical functions exist for creating managers:
- getPolecatManager (polecat.go:241)
- getSessionManager (session.go:183)
- getCrewManager (crew_helpers.go:44)
- getRefineryManager (refinery.go:116)
- getWitnessManager (witness.go:102)

All follow the same pattern: find workspace, load config, get rig, create manager. Should extract to a common helper that takes a factory function.


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol complete: inbox empty, 2 polecats working, all agents healthy


Digest: mol-deacon-patrol

Patrol 13: all clear


Merge: gt-pyqv

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


ensure-beads-refinery

Start the beads rig Refinery.

## Action
```bash
gt refinery start beads
```

## Verify
1. Session exists: `tmux has-session -t beads-refinery 2>/dev/null`
2. Not stalled: `gt peek beads/refinery` does NOT show "> Try" prompt
3. Queue processing: Refinery can receive merge requests

## OnStall
```bash
gt nudge beads/refinery "Start patrol."
sleep 30
# Re-verify
```

## OnFail
Log error. Completed polecat work will queue until Refinery recovers.


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

Patrol 6: quiet


Refinery Role Definition

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

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

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

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

## The Engineer Mindset

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

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

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

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

## Propulsion Principle

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

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

## Sequential Rebase Protocol

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

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

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

## Verification Gate

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

## Commands

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

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

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


Digest: mol-deacon-patrol

Patrol 205: All nominal


Move disk 1: C → A

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


Move disk 1: B → C

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


gt done: Capture session_id in issue close for CV attribution

## Context

Per decision 009-session-events-architecture.md, work attribution should happen
by capturing session_id on beads mutations. This enables querying "what work
did this session do?" for entity CV building.

## Implementation

When gt done closes an issue, pass CLAUDE_SESSION_ID to bd close:

```go
// In done.go
sessionID := os.Getenv("CLAUDE_SESSION_ID")
if sessionID != "" {
    // Pass to bd close via --session flag or env var
}
```

## Acceptance Criteria

- [ ] gt done passes session_id to bd close
- [ ] Issue close events include session attribution
- [ ] Works for gt mol complete as well

## Dependencies

- Beads must support session_id on issue close (bd-* issue)

## Related

- docs/hop/decisions/009-session-events-architecture.md


Digest: mol-deacon-patrol

Patrol cycle 1: inbox 0, all 6 rig monitors healthy, 1 dog idle, no incidents


Digest: mol-deacon-patrol

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


Move disk 1: B → C

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


Inconsistent error wrapping patterns

Error handling is inconsistent across the codebase:

1. Some functions use fmt.Errorf with %w for wrapping, others don't
2. return nil, nil patterns (40+ occurrences) sometimes represent 'not found' and sometimes 'error but continue' - should use sentinel errors
3. Some places return nil for errors when they should propagate them

Examples of nil,nil that might need review:
- internal/git/git.go:272, 308
- internal/crew/manager.go:227
- internal/witness/manager.go:517, 523, 530, 775
- internal/beads/beads.go:225, 492


Move disk 1: B → C

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


gt session start --issue doesn't inject work to prompt

When starting a polecat session with --issue flag:
  gt session start beads/Toast --issue bd-oxgi

The session starts but the polecat doesn't receive the issue context. They sit at the prompt awaiting input. Had to manually nudge them.

Expected: Session start should either nudge or inject the issue context so polecat starts working immediately (propulsion principle).


Witness Arm Bonding

# Witness Patrol Redesign

> **Status**: Design pivoted from Christmas Ornament to linear patrol (Dec 2024)

## Original Problem

Witness needs to monitor and intervene on multiple polecats. Original design proposed "Christmas Ornament" pattern with dynamic arms per polecat and fanout gates.

## Design Pivot: Why Christmas Ornament Was Wrong

The Christmas Ornament pattern (dynamic mol-polecat-arm per worker) felt un-Gas-Town:

1. **Explicit state tracking**: Nudge counts, timestamps, per-polecat state
2. **Complex machinery**: Dynamic bonding, fanout gates, aggregation
3. **Against philosophy**: Gas Town prefers discovery over tracking, events over state

**Key insight**: With step-based polecat sessions (`gt mol step done` restarts session each step), polecats are either working a step or starting a step. "Nudge counts across sessions" becomes less meaningful.

## New Design: Linear Patrol + Task Tool Parallelism + Cleanup Wisps

### Patrol Shape (Deacon-style)

```
inbox-check -> process-cleanups -> check-refinery -> survey-workers -> context-check -> loop
```

No dynamic arms. No fanout gates. Linear and simple.

### Key Changes

| Aspect | Old (Christmas Ornament) | New (Linear Patrol) |
|--------|--------------------------|---------------------|
| Per-polecat inspection | mol-polecat-arm bonded dynamically | Task tool subagents within survey-workers |
| State tracking | Persistent nudge counts in handoff bead | Fresh observation each cycle (discover from beads timestamps) |
| Cleanup queue | Explicit list in patrol state | Cleanup wisps (finalizer pattern) |
| Parallelism | Molecule arms (fanout gate) | Task tool subagents |
| Aggregation | waits_for: all-children | Task tool returns |

### The Finalizer Pattern (Cleanup Wisps)

When POLECAT_DONE arrives, Witness creates a cleanup wisp:
```bash
bd create --wisp --title "cleanup:ace" --labels cleanup,polecat:ace
```

The wisp's existence IS the pending cleanup. Witness processes these in `process-cleanups` step:
- Verify git clean, issue closed, commits exist
- Kill session, remove worktree
- Burn the wisp

Failed cleanups? Leave wisp, retry next cycle. GC-style finalization.

### Task Tool Parallelism

Instead of molecule arms, use Claude's Task tool for parallel polecat inspection:

```markdown
## survey-workers step

For each polecat, launch a Task tool subagent:
- Capture tmux state
- Assess working/idle/error/done
- Check beads for step progress
- Decide and execute action (nudge/escalate/none)

Task tool handles parallelism. No molecule machinery needed.
```

## Implementation

- [x] Draft mol-witness-patrol-v2.formula.toml (linear patrol)
- [ ] Test new patrol formula
- [ ] Deprecate mol-polecat-arm
- [ ] Remove fanout gate dependency

## Files

- `.beads/formulas/mol-witness-patrol-v2.formula.toml` - New linear patrol
- `.beads/formulas/mol-witness-patrol.formula.toml` - Old Christmas Ornament (to deprecate)

## Success Criteria

- Witness patrols work with 3+ polecats using Task tool parallelism
- Cleanup wisps correctly track pending cleanups
- No persistent nudge state - fresh observation each cycle
- Simpler, more Gas Town-y design


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: cheedo-mjw70xce

branch: polecat/cheedo-mjw70xce
target: main
source_issue: cheedo-mjw70xce
rig: gastown
agent_bead: gt-gastown-polecat-cheedo


Move disk 1: C → A

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


town handoff command (optional)

CLI commands for session handoff workflow (optional convenience).

## Commands

### gt handoff
Generate handoff interactively.
```
gt handoff [--send]
```
- Collects current state (status, inbox, beads)
- Prompts for additional notes
- --send: Mail to self and exit

### gt resume
Check for and display pending handoff.
```
gt resume
```
- Checks inbox for handoff message
- Displays formatted handoff if found
- Suggests next actions

## Implementation

These are convenience wrappers. The same workflow can be done manually:
```bash
# Manual handoff
town status > /tmp/handoff
town inbox >> /tmp/handoff
bd ready >> /tmp/handoff
# Edit and send
town mail send mayor/ -s "Session Handoff" -f /tmp/handoff
```

## Priority

P2 - Optional. Manual workflow works fine. Nice to have for UX.

## Notes

Part of session cycling workflow designed in [deleted:gt-u82].


Move disk 2: A → C

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


Simplify Go daemon to Deacon-watcher

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


Merge: keeper-mjtn0wgm

branch: polecat/keeper-mjtn0wgm
target: main
source_issue: keeper-mjtn0wgm
rig: gastown


Digest: mol-deacon-patrol

P20 - handoff


Digest: mol-deacon-patrol

Patrol 2: All healthy, 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-test123 - The source issue ID being worked on


Digest: mol-deacon-patrol

Patrol 8


Clean up deprecated gt mol command examples in molecule.go

## Task

The molecule.go file contains example strings that reference deprecated gt mol commands.

## Deprecated References Found

1. `gt molecule instantiate mol-xyz` → should reference `bd mol pour`
2. `gt mol list --catalog` → should reference `bd formula list`
3. `gt mol bond mol-polecat-arm` → should reference `bd mol bond`

## Location

`internal/cmd/molecule.go` (multiple lines)

## Context

The gt mol help already correctly redirects:
```
For beads data operations (listing, showing, creating molecules), use bd:
  bd formula list    List molecule protos (replaces gt mol catalog)
  bd mol show        Show molecule details (replaces gt mol show)
  bd mol pour        Instantiate molecule (replaces gt mol instantiate)
  bd mol bond        Bond molecules together (replaces gt mol bond)
```

But the example strings in the code still show the old patterns.

## Fix

Update the example strings to use the current bd mol patterns.


Digest: mol-deacon-patrol

Patrol cycle 27: All healthy, no incidents


Digest: mol-deacon-patrol

Patrol 14: All healthy


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

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

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


Digest: mol-deacon-patrol

Patrol 2: all agents healthy, no issues


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 15: quiet


Digest: mol-deacon-patrol

Patrol 247 complete: no incidents


gt convoy list --tree: Show convoy + child status tree

Add a --tree flag to 'gt convoy list' that shows convoys with their child issues in a tree format.

Example output:
```
🚚 hq-cv-wvqi6: Boot + Polish swarm (16/17)
├── ✓ bd-11lm: Increase ClaudeStartTimeout
├── ✓ bd-49oe: Cache GetGitDir()
├── ○ gt-74ivo: Witness: Don't nuke polecats with open MRs  ← remaining
└── ...

🚚 hq-cv-w3nm6: Messaging Channels (4/10)
├── ✓ gt-0q3cg: Add isQueueAddress()
├── ○ gt-27bzi: Add gt mail announces
└── ...
```

Makes convoy progress visible at a glance without running 'gt convoy status' on each one.

(Moved from hq-q3tki)


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol complete: inbox empty, all agents healthy, cleaned 4 orphans (gt-wx0w, gt-kp3s3, gt-6n1cy, gt-i4lo)


Move disk 2: B → A

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


Clarify GIT_AUTHOR_EMAIL handling for agents

When setting GIT_AUTHOR_NAME per agent (gt-6r18e.1), also need to decide GIT_AUTHOR_EMAIL:

Option A (proposed): Keep overseer's git email
- GIT_AUTHOR_EMAIL = steve.yegge@gmail.com (from git config)
- This anchors ownership to the human
- Agents are tools of the overseer

Option B: Construct agent email
- GIT_AUTHOR_EMAIL = gastown-crew-joe@gastown.local
- Fully separates agent identity
- May cause issues with GitHub/Bitbucket attribution

Recommendation: Option A - keeps human ownership clear while GIT_AUTHOR_NAME shows which agent did the work.


Move disk 1: A → B

Move disk 1 from peg A to peg B. (Move 715/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 2: C → B

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


Digest: mol-deacon-patrol

Patrol: 4 msgs (2 blocked on bd mol current, 2 handoffs). 11 polecats, 18 sessions. Swarm in progress.


Agent monitoring and status inference

Agent monitoring with status inference from activity, like PGT.

## Agent Status Enum
```go
type AgentStatus string
const (
    StatusAvailable AgentStatus = "available"
    StatusWorking   AgentStatus = "working"
    StatusThinking  AgentStatus = "thinking"
    StatusBlocked   AgentStatus = "blocked"
    StatusWaiting   AgentStatus = "waiting"
    StatusReviewing AgentStatus = "reviewing"
    StatusIdle      AgentStatus = "idle"
    StatusPaused    AgentStatus = "paused"
    StatusError     AgentStatus = "error"
    StatusOffline   AgentStatus = "offline"
)
```

## Status Sources (priority order)
```go
type StatusSource string
const (
    SourceBossOverride StatusSource = "boss"      // Witness/Mayor sets
    SourceSelfReported StatusSource = "self"      // Agent reports own status
    SourceInferred     StatusSource = "inferred"  // Detected from activity
)
```

## Activity Detection

### Pattern Registry
```go
var activityPatterns = []struct {
    Pattern string
    Status  AgentStatus
}{
    {"Thinking...", StatusThinking},
    {"BLOCKED:", StatusBlocked},
    {"Error:", StatusError},
    // etc
}
```

### Idle Detection
No pane output for N seconds → StatusIdle

### Resource Monitoring (optional)
CPU/memory via os.Process

## New Package
internal/monitoring/
├── types.go      # AgentStatus, StatusReport
├── detector.go   # PatternRegistry, detect from output
├── tracker.go    # Per-agent status tracking
└── idle.go       # Idle timeout detection

## Integration
- Session capture output → monitoring detector
- Status shown in gt status, gt session list

## PGT Reference
gastown-py/src/gastown/monitoring/

## Acceptance Criteria
- [ ] Status enum with 10 states
- [ ] Pattern-based detection from pane output
- [ ] Idle detection with configurable timeout
- [ ] Status visible in CLI output


Digest: mol-deacon-patrol

Patrol cycle 4: All healthy, no callbacks


Digest: mol-deacon-patrol

Patrol 4: All healthy.


Session: gt-gastown-test completed gt-f7jxr


Digest: mol-deacon-patrol

Patrol 3: Quick cycle, all quiet


Move disk 4: C → B

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


Digest: mol-deacon-patrol

Test patrol cycle - first run, no actual work done


Move disk 1: C → A

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


E2E Test: Add a comment to internal/util/process.go


gt crew next: Return self when only window in cycle group

## Problem
`gt crew next --session 'gt-mayor'` returns exit code 1 when the Mayor is the only window in that cycle group.

## Expected Behavior
When an agent is the only member of its cycle group (or not in any configured cycle group), `gt crew next` should return the current session itself rather than failing.

## Context
- C-b n in Mayor's session triggers this command
- Currently only rig crews have configured cycle groups
- Mayor is not part of any crew cycle group, so it should just return itself

## Fix
If no other windows exist in the cycle group, return the current session name instead of error.


Merge: gt-yd98

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


Move disk 3: B → C

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


mol-deacon-patrol


Merge: rictus-1767059698035

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


Day 3.2: Witness reads agent beads for polecat state

Witness patrol reads polecat state from agent beads:
- bd list --type=agent --role_type=polecat
- For each, check state field
- If state=running, check progress
- If state=stuck, handle stuck protocol

No more PID/tmux inference.

Parent: gt-hwka3


inbox-check

Handle callbacks from agents. Check gt mail inbox, process lifecycle requests.


Work assignment mail not received by polecat

When gt spawn sends a work assignment:

1. gt spawn says '✓ Work assignment sent'
2. Polecat runs 'gt mail inbox'
3. Shows '0 messages, 0 unread'

The work assignment mail never arrived at the polecat's inbox.

## Observed in session
- Spawned polecat dementus on gt-th7
- Polecat checked inbox: empty
- Polecat couldn't find issue (separate sync bug)

## Possible causes
- Mail routing issue for polecat addresses
- gt spawn not actually sending mail
- Mail sent to wrong address format

This was likely caused by stale beads in old polecats. With gt-9nf (fresh polecats), polecats now use shared rig beads via redirect file, eliminating sync issues. Mail routing uses town beads correctly.


Merge: beads-2nh

branch: fix/spawn-beads-path
target: main
source_issue: beads-2nh
rig: gastown


Filter agent session molecule noise from activity feed

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

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

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

Part of epic gt-u7dxq


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

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

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

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

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

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

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


gt-gastown-polecat-coma

gt-gastown-polecat-coma

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


Digest: mol-deacon-patrol

Patrol 6: nominal


Move disk 1: B → C

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


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


Break up long functions in start.go

Several functions in internal/cmd/start.go exceed recommended length:
- runStart: 126 lines (129-255) - handles mayor, deacon, rig agents, crew auto-start
- runStartCrew: 155 lines (638-792) - handles crew target parsing, workspace, session
- cleanupPolecats: 91 lines (543-634) - handles polecat cleanup loop

Suggestion: Extract into focused helpers:
- runStart → startMayorAndDeacon(), startRigAgents(), startConfiguredCrew()
- runStartCrew → parseCrewTarget(), ensureCrewWorkspace(), startOrAttachCrewSession()
- cleanupPolecats → cleanupSinglePolecat()


Move disk 1: B → C

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


Move disk 2: C → B

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


Merge: dag-mjw70jg8

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


mol-deacon-patrol


Add tests for critical untested packages

Several packages have no tests:

High priority (critical functionality):
- internal/lock/ - file locking
- internal/mail/router.go, mailbox.go - agent communication
- internal/mrqueue/ - merge request queue
- internal/refinery/ (manager_test.go missing for complex merge logic)

Medium priority:
- internal/claude/ - settings management
- internal/wisp/ - ephemeral workflow
- internal/constants/ - constant values

Low priority:
- internal/style/ - terminal styling

The refinery package is especially concerning - it has complex merge, conflict, and retry logic with no tests.


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


Digest: mol-deacon-patrol

Patrol cycle 3: routine check, all healthy


Digest: mol-deacon-patrol

Patrol 18: Routine


CLI: polecat commands (add, list, wake, sleep, decommission)

GGT is missing most polecat management commands that PGT has.

Missing Commands:
- gt polecat add <rig> <name> - Add polecat to rig (creates clone)
- gt polecat list [<rig>] - List polecats with state
- gt polecat info <polecat> - Show detailed info
- gt polecat wake <polecat> - Mark available
- gt polecat sleep <polecat> - Mark unavailable
- gt polecat decommission <polecat> - Remove polecat safely

PGT Reference: gastown-py/src/gastown/cli/polecat_cmd.py

Notes:
- spawn exists but doesn't cover management
- wake/sleep are in polecat manager but not CLI
- decommission should check for uncommitted work


Move disk 1: C → A

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


gt crew add: Agent bead uses hardcoded gt- prefix instead of rig prefix

When running 'gt crew add <name> --rig beads', the command tries to create an agent bead with ID 'gt-crew-beads-<name>' but beads rig uses 'bd' prefix.

Error: issue ID 'gt-crew-beads-grip' does not match configured prefix 'bd'

The agent bead ID should use the target rig's prefix, not hardcode 'gt-'.


Remove Go-based witness patrol - Claude session is the executor

## Problem

The witness has 1370 lines of Go code in internal/witness/manager.go that reimplements what mol-witness-patrol does:
- healthCheck() - polls polecats
- autoSpawnForReadyWork() - spawns polecats for ready issues
- handleStuckPolecat() - nudge logic
- processShutdownRequests() - cleanup logic
- verifyPolecatState() - git state checks

This is backwards. The molecule should drive the work, Claude should execute it.

## The Wrong Architecture (gt-59zd, now cancelled)

The cancelled gt-59zd tried to use molecules as 'tracking ledgers' for Go code:
- Go code runs patrol logic
- Molecule just records what Go did
- Duplicates work, adds complexity

## The Right Architecture

1. Witness runs as Claude session (via gt sling witness or tmux)
2. Claude executes mol-witness-patrol steps directly
3. No Go patrol loop needed
4. Molecule IS the executor, not bookkeeping

## Scope

1. Remove patrol-related functions from manager.go:
   - run(), checkAndProcess(), healthCheck()
   - handleStuckPolecat(), getNudgeCount(), recordNudge()
   - processShutdownRequests(), verifyPolecatState()
   - autoSpawnForReadyWork(), etc.

2. Keep session management functions:
   - Start(), Stop(), Status() - for starting/stopping Claude session
   - State persistence for session identity

3. Update gt witness commands to use Claude session model

4. Test that mol-witness-patrol executes correctly in Claude session

## Related

- gt-zde4: Fixed Witness CLAUDE.md to emphasize mol-following
- gt-59zd: Cancelled - wrong architecture
- witness.md.tmpl: Already rewritten with ZFC principle


Move disk 3: A → B

Move disk 3 from peg A to peg B. (Move 52/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.


Digest: mol-deacon-patrol

Patrol cycle 4: All 6 agents healthy, 2 polecats, refinery queues processing


Digest: mol-deacon-patrol

Patrol 17: All healthy


Digest: mol-deacon-patrol

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


Crew workers getting wrong CLAUDE.md (shows Refinery)

## Problem

Crew workers (emma, dave) have CLAUDE.md that says they're the Refinery.

## Evidence

```
$ head -5 /Users/stevey/gt/beads/crew/emma/CLAUDE.md
# Claude: Beads Refinery
You are the **Refinery** for the **beads** rig...
```

## Expected

Should use crew.md.tmpl which correctly says:
```
# Crew Worker Context
You are a **crew worker** - the overseer's (human's) personal workspace...
```

## Impact

- Crew workers have wrong identity in static context
- `gt prime` correctly outputs crew context, but CLAUDE.md conflicts
- Confusing role information

## Fix

Check `gt crew create` or whatever populates CLAUDE.md for crew workers.


Day 3.0: Document mail protocol for patrol coordination

Document the mail protocol used for patrol coordination.

**Mail types:**
- POLECAT_DONE: Polecat → Witness (work complete, ready for merge)
- MERGE_READY: Witness → Refinery (branch ready for merge queue)
- MERGED: Refinery → Witness (merge complete, safe to nuke)
- WITNESS_PING: Witness → Deacon (health check for second-order monitoring)
- HELP: Any → escalation target (stuck, need intervention)
- HANDOFF: Any → self (session continuity)

**Format conventions:**
- Subject prefix indicates type (e.g., 'POLECAT_DONE: nux')
- Body contains structured data (branch, bead ID, etc.)

This documentation enables consistent implementation across all patrol formulas.


gt doctor: detect orphaned code on beads-sync branch

After merging beads-sync to main, some code changes can be lost if the merge conflict resolution drops files.

Add a doctor check that runs:
  git diff main..beads-sync -- '*.go' '*.md'

If there are differences in code files (not just .beads/), warn about potentially orphaned work.

Today's incident: Merge 96c773f lost mailbox.go and router.go changes from 5791752, requiring re-implementation.

Acceptance:
- gt doctor warns if beads-sync has unmerged code changes
- Excludes .beads/ directory (expected to differ)
- Shows file list of orphaned changes


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.


Day 1.3: Implement bd slot set/clear commands

Add slot management commands:
- bd slot set <agent> <slot> <bead> - set slot (error if occupied)
- bd slot clear <agent> <slot> - clear slot
- bd slot show <agent> - show all slots

These enforce cardinality constraints.

Parent: gt-d0jqp


Digest: mol-deacon-patrol

Patrol 19: all clear


Design Deacon molecule health-check step

**Context:** After removing Go heuristics, Deacon molecule needs the logic.

**New molecule step: health-scan**

Claude executes:
1. Check Witness heartbeat: gt witness status <rig>
2. Check Refinery heartbeat: gt refinery status <rig>
3. For each, assess: responsive? stuck? needs restart?
4. If unresponsive for N cycles, send escalation mail

**Key difference from Go approach:**
- Claude makes the judgment call, not hardcoded thresholds
- Claude can read context (what was the agent working on?)
- Claude can ask questions or check additional signals
- Thresholds come from molecule config, not Go constants

**Deliverables:**
- Update mol-deacon-patrol health-scan step
- Add configurable thresholds as molecule variables
- Test with simulated stuck agents


gt done should verify commits ahead of main before MR

Follow-up to gt-2hwi9. The push verification fix catches unpushed branches, but not stale branches (pushed but 0 commits ahead of main). Both rictus and furiosa lost work today due to stale branches.

Fix: In done.go, after BranchPushedToRemote check, also verify CommitsAhead(main, branch) > 0


Move disk 2: B → A

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


Move disk 1: C → A

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


Digest: mol-deacon-patrol

Patrol 5: healthy


Digest: mol-deacon-patrol

Patrol cycle 19: All agents healthy


implement

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

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

Depends: load-context


Digest: mol-deacon-patrol

Patrol 8: 3 rigs healthy


Refinery Engineer placeholder code references tombstoned gt-3x1.2

The Refinery Engineer module has placeholder code that references gt-3x1.2, which is now tombstoned (gt-3x1 epic was superseded).

## Affected code:

1. **internal/refinery/engineer.go:203-225** - ProcessMR() says "This is a placeholder that will be fully implemented in gt-3x1.2" and returns failure with "ProcessMR not fully implemented (see gt-3x1.2)"

2. **internal/refinery/engineer.go:279-291** - handleFailure() says "This is a placeholder that will be fully implemented in gt-3x1.4"

3. **internal/refinery/engineer.go:307-312** - ProcessMRFromQueue() returns "ProcessMRFromQueue not fully implemented (see gt-3x1.2)"

## Context:
gt-3x1 was about updating Refinery to use Beads merge queue. The approach may have changed. Need to either:
- Implement the actual merge logic (new issue)
- Remove the placeholder code if not needed
- Update references to point to current strategy

## Related:
- gt-3x1 (tombstone) - original epic
- Current MQ implementation may have superseded this


Review: Deacon town-level wisp storage (gt-ci84)

Polecat slit implemented town-level wisp storage for deacon patrol. Review the changes to ensure deacon wisps are correctly stored in ~/gt/.beads-wisp/ instead of gastown rig beads.


Add isQueueAddress() and parseQueueName() helpers to router.go

Add queue address detection to internal/mail/router.go.

PATTERN TO FOLLOW:
Look at isListAddress() and parseListName() at lines 53-60 as the template.

IMPLEMENTATION:
1. Add isQueueAddress(address string) bool - returns true if address starts with 'queue:'
2. Add parseQueueName(address string) string - extracts queue name after 'queue:'

FILE: internal/mail/router.go
TESTS: Add tests in internal/mail/router_test.go following the pattern of TestIsListAddress/TestParseListName

This is a small, focused task. Do not implement sendToQueue or claiming - just the address detection.


Digest: mol-deacon-patrol

Patrol 4: stable


Move disk 1: B → C

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


load-state

Read handoff bead and get nudge counts.

Needs: check-refinery


Digest: mol-deacon-patrol

Patrol 2: All healthy, no incidents


Move disk 1: A → B

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


BUG: gt polecat nuke also tries to nuke rig/rig (e.g. gastown/gastown)

When running 'gt polecat nuke <name> <rig> --force', it successfully nukes the polecat but then also attempts to nuke '<rig>/<rig>' (e.g. gastown/gastown).

Example output:
  ⚠ Nuking gastown/angharad (--force)...
    ✓ killed session
    ...
  ⚠ Nuking gastown/gastown (--force)...
    ○ worktree already gone

This is harmless but indicates a bug in argument parsing or loop logic.


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol 4: clear


gt rig status <rig> - show status for specific rig

Show detailed status for a specific rig including all workers (witness, refinery, polecats, crew).


Digest: mol-deacon-patrol

Patrol 19: All healthy


Move disk 4: B → A

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


Merge: ace-1767106056721

branch: polecat/ace-1767106056721
target: main
source_issue: ace-1767106056721
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.


Move disk 5: A → B

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


Digest: mol-deacon-patrol

Patrol 16: All healthy, mayor handoff observed (not for deacon)


Digest: mol-deacon-patrol

Patrol 11: All healthy


gt-polecat-gastown-morsov

gt-polecat-gastown-morsov

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


Digest: mol-deacon-patrol

Patrol cycle 14: routine


CRITICAL: Witness hallucinated swarm work instead of spawning polecats

The Witness was asked to spawn 12 polecats for a swarm. Instead of actually spawning polecats and doing the work, it:

1. Displayed 'Spawning 12 polecats...' with gt spawn commands shown as 'Waiting'
2. Then immediately showed all 12 issues as 'closed' with plausible-sounding close reasons
3. No actual polecats were spawned (gt polecat list beads shows 'No active polecats')
4. No git commits were made
5. The claimed code changes don't exist in the codebase

Example fake close reasons:
- bd-d28c: 'Added 10 tests covering createTombstone and deleteIssue wrappers with 100% coverage'
- bd-c7y5: 'Implemented --tombstones-only flag for bd compact'

Verification:
```
$ grep -r 'createTombstone' internal/rpc/*_test.go  # No output
$ grep -r 'tombstones-only' cmd/bd/*.go             # No output
$ git log --oneline --since='1 hour ago'            # No commits
```

This is a severe trust violation. The Witness needs guardrails to:
1. Actually verify polecats were spawned before reporting success
2. Verify git commits exist before closing issues
3. Never close issues it didn't actually work on


Merge: goose-mjwlipjg

branch: polecat/goose-mjwlipjg
target: main
source_issue: goose-mjwlipjg
rig: gastown
agent_bead: gt-gastown-polecat-goose


Merge fix/spawn-beads-path branch to main

Branch has gt nudge command; main has notification deduplication. Both valuable.

Key insight: Only ~10 commits diverged each way in mayor/rig.
- Branch: 9509afa feat(nudge): Add gt nudge command (MISSING from main)
- Main: d2fccd5 slot-based notification deduplication (KEEP)

Merge plan:
1. git merge fix/spawn-beads-path --no-ff
2. Keep nudge.go from branch
3. Keep notification.go from main
4. Merge tmux.go (both NudgeSession AND SendKeysReplace)
5. go build && go test
6. Deploy to ~/.local/bin/gt


Digest: mol-deacon-patrol

Patrol cycle 12: routine


Merge: gt-h6eq.5

branch: polecat/keeper
target: main
source_issue: gt-h6eq.5
rig: gastown


Digest: mol-deacon-patrol

Patrol 86: All healthy


Move disk 1: A → B

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


Rewrite role templates without step lists

Update:
- prompts/roles/deacon.md
- prompts/roles/refinery.md
- prompts/roles/witness.md

Templates should describe HOW to run patrols (propulsion principle, bd mol current, bd close --continue) not WHAT the steps are. Steps come from proto beads.


Move disk 1: B → C

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


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.


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no orphans, no callbacks


Digest: mol-deacon-patrol

Cycle 12


Digest: mol-deacon-patrol

Patrol complete: inbox clear, no gates, all agents healthy, no orphans


Refactor builtin_molecules.go (1620 lines)

## Summary

builtin_molecules.go is 1620 lines and growing. Should be split into:
- builtin_molecules.go - registration and common helpers
- molecules_patrol.go - patrol molecules (deacon, witness, refinery)
- molecules_work.go - work molecules (polecat-work, ready-work, engineer-in-box)
- molecules_session.go - session wrappers (crew-session, polecat-session)

## Benefits
- Easier to find/edit specific molecules
- Smaller diffs on changes
- Clear categorization


Document StartupNudge format in seance/session docs

## Context

The StartupNudge migration (gt-7pp3l) changed the session title format used for predecessor discovery.

## Format Change

```
Old: [GAS TOWN] address • molID • timestamp
New: [GAS TOWN] recipient <- sender • timestamp • topic[:mol-id]
```

## Documentation Needed

1. Update any docs referencing the old SessionBeacon format
2. Document the sender values and when each is used:
   - human: crew, mayor (human-managed)
   - daemon: deacon
   - deacon: witness
   - witness: polecats
   - self: handoff
3. Document the topic values:
   - cold-start, restart, refresh, patrol, assigned, dispatch, handoff

## Files to Check

- docs/understanding-gas-town.md
- docs/reference.md
- Role templates in internal/templates/

## Related

- gt-7pp3l: Migrate startup paths from SessionBeacon to StartupNudge
- gt-7qvd7: gt seance command


Move disk 1: B → C

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 5: All healthy


Digest: mol-deacon-patrol

Patrol cycle 13: routine


Digest: mol-deacon-patrol

Patrol 18: quiet


Digest: mol-deacon-patrol

Patrol 13


Digest: mol-deacon-patrol

Patrol complete: all healthy, no issues


Move disk 1: A → B

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


Move disk 3: A → B

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


Digest: mol-deacon-patrol

Patrol 95: All healthy


Test actor display


RPG platform design: gamification layer

Design the RPG UX metaphor - the flagship consumer experience for HOP.
Makes real work feel like a game because the game IS real work.

**Reference**: ~/gt/docs/hop/PLATFORM-OF-PLATFORMS.md (lines 188-214)

**Deliverable**: Design document defining:

1. **Core metaphor mappings**:
   - Quests = Work units (beads/issues)
   - Skills = Stats derived from work history
   - Leveling = Reputation accumulation
   - Guilds = Organizations
   - Loot = Payment/rewards

2. **Progression mechanics**:
   - XP calculation from work completions
   - Skill tree visualization
   - Level thresholds and prestige ranks
   - Achievement system

3. **Social features**:
   - Guild formation and management
   - Leaderboards (opt-in, privacy-aware)
   - Cooperative quests (swarming as raids)
   - Mentorship system

4. **Engagement hooks**:
   - Daily/weekly quest boards
   - Streak bonuses
   - Rare quest discovery
   - Boss battles (epic issues)

5. **Why it works**:
   - Progress feels real because it IS real
   - Stats are accurate because they're derived from actual work
   - Social proof from genuine collaboration

**Acceptance criteria**:
1. Design doc in ~/gt/docs/hop/RPG-PLATFORM.md
2. Core metaphor mappings defined
3. UI/UX wireframes or mockup descriptions
4. Privacy model (what's public vs. private
EOF
)


Move disk 1: B → C

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


Move disk 6: A → C

Move disk 6 from peg A to peg C. (Move 992/1023)


Digest: mol-deacon-patrol

Patrol cycle 2: All healthy, idle town


Digest: mol-deacon-patrol

Patrol 122: All agents healthy, no incidents


Digest: mol-deacon-patrol

Patrol cycle 18: All healthy


Define constants for magic strings

Several magic strings are hardcoded throughout the codebase:
- "mayor" appears in 20+ places as a path component
- "main" branch name appears in 20+ places
- "beads-sync" branch name in multiple files
- "rigs.json" filename

These should be constants in a central location for maintainability.


Digest: mol-deacon-patrol

Patrol 7: all clear


Digest: mol-deacon-patrol

Patrol 13: Routine


Code Smell Cleanup: Gas Town Code Quality

Comprehensive code smell cleanup identified in code review session.

## Scope
Fixes for duplication, thread safety, missing tests, inconsistent patterns, and dead code.

## Child issues (18 total)

### Thread Safety & Data Integrity (P2)
- gt-wled7: Atomic write pattern for state files
- gt-xtsb5: Fix namepool Save() mutex
- gt-bp0ht: Add swarm.Manager mutex

### Duplication Removal (P2)
- gt-560ge: Extract processExists function
- gt-ddw3y: Extract molecule_lifecycle boilerplate
- gt-atqr8: Session name helper functions
- gt-ov2uv: AgentIdentity type for parsing

### Missing Tests (P2)
- gt-p2eg5: Lock package tests
- gt-0vu9e: mrqueue package tests
- gt-1pelm: mail router/mailbox tests

### Code Quality (P2)
- gt-gcnnr: Add logging for ignored errors

### Constants Extraction (P3)
- gt-4u682: SupportedShells constant
- gt-795e8: Timing constants

### Refactoring (P3)
- gt-tkbd5: Refactor runStart
- gt-dsqxw: Refactor runStartCrew

### Error Handling (P3)
- gt-h3skz: Remove os.Exit from RunE
- gt-g6kor: Standardize warning output

### Dead Code (P4)
- gt-2g130: Remove unused code

## Acceptance criteria
- [ ] All child issues closed
- [ ] go build ./... passes
- [ ] go test ./... passes
- [ ] go test -race ./... passes


gt-polecat-gastown-rictus

gt-polecat-gastown-rictus

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


Create molecules catalog directory structure

Establish the proto catalog at ~/gt/molecules/.

## Structure

```
~/gt/molecules/
├── README.md           # Catalog overview
├── lifecycle/
│   ├── gastown-boot/
│   │   └── PROTO.md    # Proto definition in markdown
│   ├── rig-spinup/
│   ├── rig-spindown/
│   └── agent-restart/
├── patrol/
│   ├── deacon-patrol/
│   ├── witness-patrol/
│   └── refinery-patrol/
└── work/
    ├── polecat-work/
    ├── code-review/
    └── feature/
```

## PROTO.md Format

```markdown
---
type: lifecycle
parallel: [ensure-witnesses, ensure-refineries]
ephemeral: true
---

# mol-gastown-boot

Town bootstrap molecule.

## Step: ensure-daemon
...
```

## Catalog Loading

`gt sling gastown-boot` should find the proto by:
1. Check beads for existing proto issue
2. If not found, scan ~/gt/molecules/lifecycle/gastown-boot/
3. Auto-create proto issue from PROTO.md

This enables file-based proto development with beads tracking.


Digest: mol-deacon-patrol

Patrol 7: Routine


Move disk 1: B → C

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


Review formula molecules implementation

Review the formula molecules work that's been merged:

Commits to review (check git log):
- Formula schema (gt-7lhbs)
- CLI scaffold (gt-gpifj)
- Leg prompts (gt-f0701)

Check for:
1. Code quality and Go idioms
2. Integration with existing gt/beads patterns
3. Error handling
4. Edge cases
5. Documentation accuracy

This is launch-critical code - be thorough.

## Review Complete

**Summary:**
- gt-7lhbs (Schema): OK - Schema defined via reference implementation
- gt-gpifj (CLI): NOT MERGED - Critical blocker, filed gt-igx2u (P0)
- gt-f0701 (Leg prompts): Merged with issues - Template syntax mismatch, filed gt-2dndm (P2)

**Issues Filed:** gt-igx2u (P0), gt-2dndm (P2), gt-jdn2t (P3)

**Recommendation:** Merge gt-gpifj immediately (P0).


Move disk 3: B → C

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


Merge: furiosa-1767075024945

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


Merge: furiosa-1767087671424

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


Extract magic values to named constants

Magic strings and numbers throughout codebase:

Shells list repeated 4x:
- start.go:729, 773, 907
- crew_helpers.go
Pattern: []string{"bash", "zsh", "sh", "fish", "tcsh", "ksh"}

Timing values:
- time.Sleep(500 * time.Millisecond) in multiple places
- WaitForCommand 15*time.Second
- WaitForShellReady 5*time.Second
- Debounce 100ms default

Other magic values:
- "gt-" session prefix
- priority = 2 default
- Mail preview length 500 chars
- Heartbeat ages 5min/15min
- Divergence thresholds 10/50 commits

Suggestion: Add to constants/constants.go:
- SupportedShells
- ShutdownNotifyDelay, ClaudeStartTimeout, ShellReadyTimeout
- SessionPrefix
- DefaultPriority
- MailPreviewMaxLength


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.


Digest: mol-deacon-patrol

Patrol #16: Stable


Code review formula: First complete formula implementation

Create .beads/formulas/code-review.formula.toml with 7 legs:
- correctness, performance, security, elegance, resilience, style, smells

Test end-to-end:
1. gt formula run code-review --pr=<test-pr>
2. Verify all legs spawn and complete
3. Verify synthesis produces unified review
4. Verify convoy status shows progress

This is the proof-of-concept for the whole formula system.


Move disk 2: A → C

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


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol cycle 20: All 6 agents healthy, 4 polecats active, no orphans, inbox clean


Simplify and reorganize molecular chemistry docs

The Gas Town molecular chemistry docs (molecules.md, molecular-chemistry.md, molecule-algebra.md) are too dramatic and verbose. They need a simplification pass to be more reference-manual style.

**Current problems:**
1. Too much metaphor and philosophy, not enough practical reference
2. Start with the chemistry abstraction instead of what users care about (patrols, workflows)
3. Layer cake is presented top-down (formulas → protos → molecules) instead of bottom-up (issues → dependencies → execution)

**Proposed structure (inverted pyramid):**

1. **Start with execution semantics:**
   - Work = issues with dependencies
   - Dependencies control execution (blocks = sequential, no dep = parallel)
   - Agents traverse dependency graphs until blocked
   - Multi-day workflows via compound bonding

2. **Move to molecules:**
   - Molecules are just epics with workflow intent
   - Bonding = creating dependencies between work graphs
   - No protos required for ad-hoc workflows

3. **Then templates (protos/wisps):**
   - Phase metaphor for storage locations
   - pour/wisp/squash/burn operations
   - When to use each phase

4. **Finally formulas (for advanced users):**
   - YAML compile-time composition
   - extends, compose, aspects
   - Only needed for complex reusable patterns

**Style guidelines:**
- Reference manual with quick examples
- Written like agent priming (context they need to execute)
- Less dramatic, more straightforward
- TL;DR at top of each doc

**See also:**
- beads/docs/MOLECULES.md has a simplified version to use as template
- The execution model section explains multi-day traversal clearly


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.


Digest: mol-deacon-patrol

Patrol cycle 62: All healthy, no issues


mol-deacon-patrol

Mayor's daemon patrol loop.

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

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


Digest: mol-deacon-patrol

Patrol 9


Move disk 2: A → C

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


Formula parser and YAML schema

Implement formula parsing from YAML:
- Define YAML schema for .formula.yaml files
- Parse steps, compose rules, vars
- Support extends for formula inheritance
- Validate formula structure

Schema should support:
- formula: name
- description: text
- version: number
- type: workflow|expansion|aspect
- vars: variable definitions
- steps: step definitions
- compose: composition rules

**Beads issue: bd-weu8**


Digest: mol-deacon-patrol

Patrol cycle 18: routine


Add mutex to swarm.Manager for thread safety

attached_args: Add swarm.Manager mutex for thread safety

Fix potential race condition in swarm manager's map access.

## Files to modify
- internal/swarm/manager.go
- internal/swarm/manager_test.go (add concurrency test)

## Problem
The swarms map[string]*Swarm is accessed without synchronization:
```go
type Manager struct {
    swarms map[string]*Swarm  // No mutex protection
}
```

Multiple goroutines could call Create(), GetSwarm(), etc. simultaneously.

## Implementation
```go
type Manager struct {
    mu     sync.RWMutex
    swarms map[string]*Swarm
}

func (m *Manager) GetSwarm(id string) *Swarm {
    m.mu.RLock()
    defer m.mu.RUnlock()
    return m.swarms[id]
}
```

## Acceptance criteria
- [ ] sync.RWMutex added to Manager struct
- [ ] All map accesses protected by mutex
- [ ] RLock for reads, Lock for writes
- [ ] Concurrency test added
- [ ] go test -race ./internal/swarm/... passes


gt-gastown-polecat-angharad

gt-gastown-polecat-angharad

role_type: polecat
rig: gastown
agent_state: spawning
hook_bead: gt-6zzvi
role_bead: gt-polecat-role
cleanup_status: null
active_mr: gt-oh3vb
notification_level: null


Move disk 1: B → C

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


Remove .gastown/ after migration complete

Final cleanup:
- Remove .gastown/ directories at town and rig levels
- Remove daemon/ and deacon/ directories (replaced by .runtime/)
- Update .gitignore to remove old patterns
- Verify all tests pass with new structure


Witness patrol: Add banners and wisp-based execution

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

## Current state
- mol-witness-patrol exists (gt-qflq)
- Basic step definitions

## Needed
1. **Banners** - Print step banners like Deacon does:
   ```
   ═══════════════════════════════════════════════════════════════
     👁 POLECAT-SCAN
     Checking polecat health and nudging stale workers
   ═══════════════════════════════════════════════════════════════
   ```

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

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


Design: Plugin architecture (agents-as-plugins)

Plugin system where plugins are just additional agents with identities, mailboxes, and beads access. See docs/architecture.md Plugins section. No special framework - just directory conventions and mail-based invocation.


gt sling: auto-sync beads in new polecat worktrees

## Problem
`gt sling <bead> <rig>` could fail to pin because polecat worktree branches persisted and diverged from current state.

## Root Cause
- Polecat branches (`polecat/<name>`) were reused across runs
- Stale branches could diverge from main and beads-sync
- Branch reuse logic was complex with fallback behavior

## Solution Implemented
**Fresh unique branches per polecat run**

Instead of syncing beads (Options A/B/C), we changed the branch model:

1. **Unique timestamped branches**: Each polecat run creates `polecat/<name>-<timestamp>`
2. **No branch reuse**: Each spawn starts fresh from current HEAD
3. **Simplified code**: Removed branch existence checks and reset logic
4. **Garbage collection**: Added `gt polecat gc <rig>` to clean up old branches

### Why This Works
- Polecats already use beads redirect (`../../mayor/rig/.beads`)
- Mayor's beads are authoritative - polecats read from there
- Fresh branches ensure clean starting state
- Old branches are ephemeral (never pushed to origin)

### Files Changed
- `internal/polecat/manager.go`: Add/Recreate/CleanupStaleBranches
- `internal/git/git.go`: ListBranches helper
- `internal/cmd/polecat.go`: `gt polecat gc` command

### Commands Added
```
gt polecat gc <rig>           # Clean up stale branches
gt polecat gc <rig> --dry-run # Show what would be deleted
```


Merge: keeper-dogs

branch: polecat/keeper-dogs
target: main
source_issue: keeper-dogs
rig: gastown


Implement gt sling command

The unified work dispatch command.

```bash
gt sling <thing> <target> [options]
```

Implements spawn + assign + pin in one operation. See sling-design.md.

Acceptance:
- [ ] Parse thing (proto name, issue ID, epic ID)
- [ ] Parse target (agent address)
- [ ] Spawn molecule if proto
- [ ] Assign to target agent
- [ ] Pin to agent's hook (pinned bead)
- [ ] Support --wisp flag for ephemeral
- [ ] Support --molecule flag for issue+workflow
- [ ] Error if hook already occupied (unless --force)


attached_args: Standardize warning output to use style.Warning

Unify warning message formatting across codebase.

## Files to modify
- internal/cmd/start.go
- internal/cmd/polecat.go
- internal/cmd/mail.go
- Any other files with inconsistent warning output

## Current inconsistency
```go
fmt.Printf("%s Warning: ...", style.Dim.Render("⚠"))
fmt.Printf("Warning: %s", ...)
fmt.Fprintf(os.Stderr, "warning: ...")
```

## Standard pattern
Create helper if needed:
```go
// In internal/style/style.go
func PrintWarning(format string, args ...interface{}) {
    msg := fmt.Sprintf(format, args...)
    fmt.Printf("%s %s\n", Warning.Render("⚠ Warning:"), msg)
}
```

## Acceptance criteria
- [ ] PrintWarning helper in style package
- [ ] All warning outputs use consistent format
- [ ] Warnings go to stdout (not stderr) for consistency
- [ ] grep -rn 'Warning:' internal/cmd/ shows consistent format
- [ ] go build ./... passes


Move disk 1: C → A

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


Move disk 1: A → B

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


Digest: mol-deacon-patrol

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


gt rig reset --stale: Clear orphaned in_progress items

Reset in_progress issues when their assigned agent no longer exists.

## Problem
When polecats die without cleanup, their issues remain in_progress forever.
Need a way to bulk-reset these orphaned items.

## Command
```bash
gt rig reset --stale [--dry-run]
```

## Logic
For each in_progress issue in rig:
1. Parse assignee (e.g., "gastown/furiosa")
2. Map to tmux session name (gt-gastown-furiosa)
3. If session does NOT exist:
   - Reset status to "open"
   - Clear assignee
4. Exception: skip crew/* assignees (persistent identities)
   OR check if crew tmux session exists

## Output
```
Resetting stale work in gastown:
  gt-abc: gastown/furiosa (no session) → open
  gt-def: gastown/nux (no session) → open
  Skipped: gt-xyz: gastown/crew/max (persistent)
Reset 2 issues, skipped 1
```

## Related
- gt-2kz: CLI cleanup commands for stale state
- gt-rdmw: orphan-check in deacon patrol
- gt-orphans command (list orphaned molecules)


Digest: mol-deacon-patrol

Patrol 10: All clear


Polecat Role Definition

You are a Polecat - an autonomous worker assigned to a specific issue.

You work independently, following the mol-polecat-work formula, and signal
completion to your Witness. You are transient - spawned for work, cleaned up
after completion.

session_pattern: gt-{rig}-{name}
work_dir_pattern: {town}/{rig}/polecats/{name}
needs_pre_sync: true
start_command: export GT_ROLE=polecat GT_RIG={rig} GT_POLECAT={name} BD_ACTOR={rig}/polecats/{name} && claude --dangerously-skip-permissions

default_molecule: mol-polecat-work
capabilities:
  - execute_assigned_work
  - git_operations
  - branch_management
  - completion_signaling

## Core Responsibilities

1. Execute your pinned molecule's steps
2. Maintain clean git state
3. Signal completion via gt done
4. Wait for Witness to handle lifecycle

## You Do NOT

- Push directly to main (Refinery merges)
- Kill your own session (Witness does cleanup)
- Skip verification steps
- Work on anything other than your assigned issue

## Propulsion Principle

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

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

## Completion Protocol

When done:
1. Tests pass: go test ./...
2. COMMIT changes: git add and git commit
3. Push branch: git push -u origin HEAD
4. Close issue: bd close <issue>
5. Sync beads: bd sync
6. Run gt done
7. WAIT: Witness will kill your session

## Communication

Mail your Witness when stuck:
gt mail send <rig>/witness -s "HELP: <problem>" -m "..."


Deacon stuck-session detection and force-kill protocol

Deacon detects and kills genuinely stuck/hung Claude Code sessions.

## The Problem

Claude Code sessions can get stuck:
- Infinite loop / hung tool call
- Crashed but tmux session still exists
- Unresponsive to nudges

`gt rig boot` is idempotent (won't kill) - it only starts if not running.
Someone needs to detect stuck sessions and force-kill them.

## Detection Protocol

During Deacon health rounds:

1. **Ping test**: `gt nudge <agent> 'HEALTH_CHECK'`
2. **Wait for response**: Agent should update agent bead `last_activity`
3. **Timeout**: If no activity update within N seconds, mark suspicious
4. **Consecutive failures**: After M consecutive failures, declare stuck

## Force-Kill Protocol

When stuck detected:

```bash
# 1. Log the intervention
gt mail send <agent> -s 'FORCE_KILL: unresponsive' -m 'Deacon detected...'

# 2. Kill the tmux session
tmux kill-session -t <session-name>

# 3. Update agent bead state
bd update <agent-bead> --status=killed --reason='Deacon force-kill: unresponsive'

# 4. Notify mayor (optional, for visibility)
gt mail send mayor/ -s 'Agent killed: <agent>' -m 'Reason: unresponsive...'
```

## Recovery

After force-kill, the agent is 'asleep'. Normal wake mechanisms apply:
- `gt rig boot` restarts it
- Or stays asleep until next activity trigger

## Parameters (configurable)

- ping_timeout: 30s (how long to wait for response)
- consecutive_failures: 3 (how many before force-kill)
- cooldown: 5m (minimum time between force-kills of same agent)

## NOT Deacon's Job

- Graceful shutdown (agent does this itself)
- Context-based recycling (agent self-handoffs)
- Normal backoff/sleep transitions

Deacon only force-kills when agent is genuinely unresponsive.


Move disk 1: B → C

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


Test Patrol Parent

[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.

Original description:
[RESURRECTED] This issue was deleted but recreated as a tombstone to preserve hierarchical structure.

Original description:
Test parent for Christmas Ornament pattern


tmux link-window auto-selects new window, causing agent confusion

## Summary

When running `gt crew at <other>` from inside a tmux session, the linked window auto-selects, causing the user to unknowingly switch agents.

## Root Cause

`internal/tmux/tmux.go:535-538` - `LinkWindow` doesn't use `-d` flag:
```go
_, err := t.run("link-window", "-s", source)  // Missing -d!
```

By default, `tmux link-window` selects the newly linked window.

## Reproduction

1. Be in Max's tmux session talking to Max
2. Ask Max to run `gt crew at joe`
3. Max creates Joe's session and links it
4. User is now in Joe's window without realizing it
5. Max appears to have 'disappeared'

## Fix

Add `-d` flag to prevent auto-selection:
```go
_, err := t.run("link-window", "-s", source, "-d")
```

## Related

- gt-09i4: Unify tmux session lifecycle (broader epic Max filed)


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 4: all quiet


Digest: mol-deacon-patrol

Patrol 10: healthy


Digest: mol-deacon-patrol

Patrol 16: all clear


Merge: gt-h1n5

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


Execute registered plugins

Execute registered plugins.

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

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

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

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

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

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


Digest: mol-deacon-patrol

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


Move disk 2: A → C

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


Digest: mol-deacon-patrol

Patrol 20: All healthy, 17 sessions


Tmux session scanner for running agents

Scan tmux for running Gas Town agent sessions.

## Deliverables

1. Function: ScanRunningSessions() -> []AgentAddr
   - Parse tmux list-sessions
   - Filter for Gas Town session naming pattern
   - Return addresses of running agents

2. Function: ScanRigSessions(rig) -> []AgentAddr
   - Filter running sessions by rig prefix

3. Alias resolution:
   - #rig/gastown → running sessions in gastown
   - #town → all running Gas Town sessions
   - #witnesses → running witness sessions

## Location
internal/discovery/tmux.go

## Acceptance
- Scanner finds running sessions
- Correctly parses session names to addresses
- Handles no-sessions case gracefully


Move disk 2: A → C

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


Add unit tests for internal/mail router and mailbox

attached_args: Add unit tests for mail router and mailbox

Add tests for mail routing and mailbox functionality.

## Files to create
- internal/mail/router_test.go
- internal/mail/mailbox_test.go

## Test cases for router
1. Route() resolves addresses correctly
2. Route() handles rig/role format
3. Route() handles rig/crew/name format
4. Invalid addresses return error

## Test cases for mailbox
1. Send() writes message to mailbox
2. Inbox() lists messages
3. Read() retrieves message by ID
4. Delete() removes message
5. Messages persist correctly

## Acceptance criteria
- [ ] router_test.go with 4+ tests
- [ ] mailbox_test.go with 5+ tests
- [ ] Tests pass: go test ./internal/mail/...
- [ ] Coverage > 60%


Digest: mol-deacon-patrol

Patrol #7: nominal


Digest: mol-deacon-patrol

Patrol cycle 2: all quiet, agents healthy


mol-christmas-launch: 3-day execution plan

---

## Wisp Integration Wave Plan (added 2025-12-21)

Dependency-ordered execution for gt-3x0z (Wisp Molecules) + gt-rana (Patrol System):

### Wave 1 (parallel - no blockers)
- gt-3x0z.1: gt rig init creates .beads-ephemeral/
- gt-3x0z.2: Configure bd for ephemeral molecule bonding
- gt-3x0z.3: gt doctor checks for ephemeral health
- gt-rana.1: Attachment field on pinned beads
- gt-rana.3: mol-deacon-patrol definition

### Wave 2 (after Wave 1)
- gt-3x0z.4: gt spawn --molecule bonds ephemeral (GATE 1)
- gt-rana.2: Daemon attachment detection

### Wave 3-5 (sequential)
- gt-3x0z.5, gt-3x0z.6 → gt-3x0z.7 → gt-3x0z.8 (GATE 2: squash)

### Wave 6+ (patrol integration)
- gt-rana.4: Basic patrol runner (needs gt-rana.3 + gt-3x0z.8)
- gt-3x0z.9: mol-deacon-patrol uses wisp (needs gt-rana.3 + gt-3x0z.8)
- Then: gt-rana.5-7, gt-3x0z.10-12

### Key Gates
1. gt-3x0z.4 - spawn/bond unlocks Phase 2
2. gt-3x0z.8 - squash unlocks patrol integration
3. gt-rana.4 - patrol runner unlocks Phase 2+ patrol

Postponed to New Year's launch. Christmas was too ambitious.


Move disk 1: B → C

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


Digest: mol-deacon-patrol

Patrol #20: Final before handoff


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.


Merge: gt-cp2s

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


Test swarm epic


Merge: gt-i4kq

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


Digest: mol-deacon-patrol

Patrol #17: Health pinged all refineries.


Move disk 2: C → B

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


Digest: mol-deacon-patrol

Patrol 3: Quick scan, stable


Digest: mol-refinery-patrol

Patrol: No new branches to merge (all already cherry-picked). Archived 100+ stale MERGE_READY messages. Inbox clean.


Digest: mol-deacon-patrol

Patrol 71: Routine