Comprehensive help text and examples

Improve help text with examples and cross-references.

## Improvements

### 1. Examples Section
Add to Long description:
```go
var spawnCmd = &cobra.Command{
    Long: `Spawn a polecat with work assignment.

Examples:
  gt spawn gastown/Toast --issue gt-abc
  gt spawn gastown --issue gt-def          # auto-select polecat
  gt spawn gastown/Nux -m "Fix the tests"  # free-form task`,
}
```

### 2. Cross-References
Reference related commands:
```
See also:
  gt polecat list    List available polecats
  gt session attach  Attach to spawned session
```

### 3. Flag Descriptions
More detail on flags:
```go
cmd.Flags().StringVar(&issue, "issue", "",
    "Beads issue ID to assign. The polecat will work on this issue.")
```

### 4. Common Workflows
Add workflow docs to gt --help:
```
Common Workflows:
  Start a swarm:
    gt swarm preflight
    gt swarm create gastown --epic gt-abc --worker Toast --worker Nux --start
    gt refinery start gastown

  Check status:
    gt status
    gt swarm status <id>
```

## Files to Update
All internal/cmd/*.go files

## Acceptance Criteria
- [ ] All commands have Examples
- [ ] Related commands cross-referenced
- [ ] Flags have detailed descriptions
- [ ] Root help shows workflows


gt refinery start: doesn't actually start a session

## Problem

`gt refinery start gastown` reports success but doesn't start a tmux session.

## Evidence

```
$ gt refinery start gastown
Starting refinery for gastown...
✓ Refinery started for gastown

$ tmux list-sessions | grep refinery
(nothing)

$ gt refinery status gastown
State: ○ stopped
```

## Expected

Should start a tmux session (e.g., gt-gastown-refinery) with Claude processing the merge queue.

## Related

- gt-kcee: Witness commands also need implementation
- The refinery 'start' may just be updating state.json without spawning a session


Go scaffolding: cmd/gt, go.mod, Cobra setup

Set up Go project structure with CLI framework.

**Stack:**
- Cobra for command/flag handling
- Lipgloss for styled terminal output

**Deliverables:**
- cmd/gt/main.go with Cobra root command
- Basic subcommands: version, help
- Lipgloss styles for status output (success, warning, error)
- go.mod with dependencies


gt prime: Refinery context detection and output

Update gt prime to detect Refinery role:
- Detect from directory: refinery/rig/ = Refinery
- Show handoff bead reference
- Show merge queue status
- Show polecat branches with unmerged commits
- Show last actions summary


Merge: gt-ay1r

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


Run the test suite.

Run the test suite.

```bash
go test ./...
```

Track results: pass count, fail count, specific failures.

instantiated_from: mol-refinery-patrol
step: run-tests


Fix role detection for nested rig structures

When gastown/ has its own mayor/ dir, workspace detection finds it as town root instead of ~/ai. This breaks polecat/refinery/witness detection when running from within a rig.


gt park command for parking molecules on external deps

Add `gt park` command for when polecat hits external dependency:

```bash
gt park --step=gt-mol.3 --waiting="beads:mol-run-assignee"
```

This command:
1. Adds blocked_by: external:beads:mol-run-assignee to the step
2. Clears assignee on the step
3. Clears assignee on molecule root
4. Sends handoff mail to self with context
5. Shuts down polecat session

The molecule enters "parked" state (derived: in_progress + no assignee + blocked step).

Part of cross-project dependency system.
See: docs/cross-project-deps.md

Depends on Beads: bd-om4a (external: blocked_by support)


Merge: gt-yd98

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


Per-epic config overrides: custom merge settings

Allow per-epic merge configuration overrides.

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

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

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

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


gt crew at: auto-prime when exec'ing Claude in-session

When running 'gt crew at <name>' from inside the target session, we exec Claude directly. But this means we can't send 'gt prime' afterward since we ARE the process.

Possible solutions:
1. Claude startup hook that runs gt prime
2. Pass prompt as argument to claude CLI
3. Wrapper script approach

Related: crew resume prompt also can't be sent in this path.


LocalOutpost: Refactor current polecat spawning

## Overview

Refactor current local polecat spawning to implement the Outpost interface.

## Current State

Polecat spawning is ad-hoc. This task wraps it in LocalOutpost.

## Implementation

```go
type LocalOutpost struct {
    name       string
    maxWorkers int
    tmux       *Tmux
    workers    map[string]*LocalWorker
}

func NewLocalOutpost(config OutpostConfig) *LocalOutpost

func (o *LocalOutpost) Type() OutpostType { return OutpostLocal }

func (o *LocalOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {
    // Create tmux session
    // Start claude in pane
    // Return LocalWorker
}
```

## LocalWorker

```go
type LocalWorker struct {
    id      string
    session string  // tmux session name
    issue   string
    status  WorkerStatus
}

func (w *LocalWorker) Attach() error {
    // tmux attach-session
}
```

## Notes

- This should be a refactor, not new functionality
- Existing polecat code becomes LocalOutpost internals
- Tests should pass before and after

Depends on: gt-9a2.1 (interfaces)


Patrols: Cyclic molecules for autonomous maintenance

## Vision

Patrols are **cyclic molecules** - workflow loops that give Gas Town its autonomous nervous system. While regular molecules are DAGs that terminate, patrols loop forever, performing maintenance tasks at varying cadences.

This is the "steam engine" of Gas Town: converting episodic Claude sessions into continuous autonomous operation.

## Core Concepts

### 1. Cyclic Molecules

Regular molecule:     A -> B -> C -> done
Patrol molecule:      A -> B -> C --+
                      ^             |
                      +-------------+

Patrols have a loop_to field specifying where to restart.

### 2. Cooldown-Aware Steps (Atoms)

Steps encode their own cadence. When patrol reaches a step:
1. Check: now - last_run > cooldown?
2. If yes: execute, update last_run
3. If no: skip (immediately close)

The patrol runner is simple - steps self-skip. Complexity distributed into atoms.

### 3. The Beacon

The heartbeat that fires patrol triggers:
- Internal ticker in Deacon (goroutine)
- Or external cron firing gt deacon tick
- Or mail-based triggers

Without beacon, nothing proactive happens.

### 4. Session Reset as Patrol Step

Connects to auto-handoff (gt-bcwn). Session reset is a patrol step, not a separate mechanism.

### 5. Multi-Role Patrols

Each supervisor has its own patrol:

**Deacon patrol:** health-check (30s), session-gc (5m), beacon-tick (10s)
**Witness patrol:** orphan-scan (10m), stuck-check (2m), molecule-progress (1m)
**Refinery patrol:** queue-check (30s), pr-status (1m), merge-ready (30s)

### 6. Cadence Tiers

- Critical (10-30s): Health checks
- Active (1-5m): Progress, nudges
- Maintenance (10-30m): Orphans, GC
- Periodic (1h+): Reports

### 7. Best-Effort Scheduling

Not real-time - more like cron. No hard deadlines. Catch-up, dont pile-up.
Priority preemption (mail interrupts patrol). Graceful degradation under load.

## Open Questions

1. State persistence: Beads (self-describing) or file (faster)?
2. Interruption: How does urgent mail preempt patrol?
3. Error recovery: Backoff? Escalate? Circuit breaker?
4. Coordination: Can patrols send mail to trigger other patrols?

## Related

- gt-bcwn: Auto-handoff (session reset is a patrol step)
- Molecule system (patrols extend molecules with loops)
- Deacon lifecycle management

## Metaphor

Claude was fire. Claude Code was steam. Gas Town is the steam engine. Beads is the train tracks.

The steam engine converts episodic combustion into continuous rotary motion.
Gas Town converts episodic Claude sessions into continuous autonomous work.


Merge polecat/slit: docs bd mol bond/squash/burn CLI

Branch: polecat/slit

## Summary
Added comprehensive CLI reference documentation for the three molecule lifecycle commands to molecules.md:

- **bd mol bond**: Instantiate proto into Mol (durable) or Wisp (ephemeral)
- **bd mol squash**: Complete molecule and generate digest
- **bd mol burn**: Abandon molecule without digest

Includes argument tables, behavior descriptions, examples, and a lifecycle diagram showing the steam engine metaphor mapping.

Closes: gt-odvf


Mail CLI: archive, purge, search, mark

GGT mail CLI needs more commands for mail management.

## Commands to Add

### gt mail check
Check for new mail without full inbox display.
```
gt mail check [--quiet] [--inject]
```
- --quiet: Only output if new mail (for scripts)
- --inject: Send notification to running session

### gt mail mark
Change read status.
```
gt mail mark <id> --read
gt mail mark <id> --unread
```

### gt mail delete
Remove message from inbox.
```
gt mail delete <id> [--force]
```
- Confirm unless --force

### gt mail archive
Move old/read messages to archive.
```
gt mail archive [--older-than DAYS] [--all-read] [--dry-run]
```
- Creates inbox.jsonl.archive or separate archive.jsonl

### gt mail purge
Permanently delete archived messages.
```
gt mail purge [--older-than DAYS] [--dry-run] [--force]
```

### gt mail search
Find messages by content.
```
gt mail search <query> [--from SENDER] [--subject] [--body]
```

### gt mail reply
Reply to a message.
```
gt mail reply <id> -m BODY
```
- Auto-sets reply_to and thread_id
- Auto-addresses to original sender

## Files to Modify
- internal/cmd/mail.go: Add commands
- internal/mail/mailbox.go: Add Archive(), Search(), Delete()

## Acceptance Criteria
- [ ] All commands implemented
- [ ] Archive stores in separate file
- [ ] Search supports regex patterns
- [ ] Delete confirms by default


Work on ga-ct2: Add MR workflow to polecat completion. Wh...

Work on ga-ct2: Add MR workflow to polecat completion. When polecat completes work, auto-create MR to integration branch. When done, submit MR (not PR) to integration branch for Refinery.


Workspace doctor checks: Config, state, mail, Mayor, rigs

Workspace-level doctor checks.

## Checks

### ConfigExists
- Verify config/ directory exists
- Verify config/town.json exists
- Fix: Cannot auto-fix (need gt install)

### ConfigValid
- Parse town.json
- Verify required fields (type, version, name)
- Verify type == "town"
- Fix: Cannot auto-fix

### RigsRegistryValid
- Parse config/rigs.json
- Verify each registered rig directory exists
- Warn on missing rigs
- Fix: Remove missing rigs from registry

### MayorExists
- Verify mayor/ directory exists
- Verify mayor/CLAUDE.md exists
- Fix: Create from template

### MayorMailboxExists
- Verify mayor/mail/ directory exists
- Verify mayor/mail/inbox.jsonl exists (can be empty)
- Fix: Create directory and empty file

### MayorStateValid
- Parse mayor/state.json if exists
- Verify valid JSON
- Fix: Reset to default state

## Implementation

```go
var WorkspaceChecks = []Check{
    &ConfigExistsCheck{},
    &ConfigValidCheck{},
    &RigsRegistryValidCheck{},
    &MayorExistsCheck{},
    &MayorMailboxExistsCheck{},
    &MayorStateValidCheck{},
}
```


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 OK: archived old handoff, all agents up, furiosa on gt-oiv0


gt handoff deadlock at handoff.go:125

When running 'gt handoff -m "message"' after successful MR submit, go panics with 'fatal error: all goroutines are asleep - deadlock\!' at handoff.go:125. The shutdown request still appears to be sent successfully but the command crashes. Stack trace shows issue is in runHandoff select statement.


Phase 4: Polish and observability

Production readiness.

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

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

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

Depends: Phase 3


Improve test coverage in low-coverage packages

Several packages have low test coverage:
- internal/cmd: 6.8%
- internal/mail: 3.6%
- internal/daemon: 12.1%
- internal/doctor: 14.5%
- internal/refinery: 20.6%
- internal/session: 27.8%
- internal/git: 28.8%

Priority should be given to mail, cmd, and daemon packages which handle critical functionality.


ensure-gastown-witness

Start the gastown rig Witness.

## Action
```bash
gt witness start gastown
```

## Verify
1. Session exists: `tmux has-session -t gastown-witness 2>/dev/null`
2. Not stalled: `gt peek gastown/witness` does NOT show "> Try" prompt
3. Heartbeat fresh: Last patrol cycle < 5 min ago

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

## OnFail
Log error. Rig polecats will be unmonitored until Witness recovers.


mol-gastown-boot

Mayor bootstraps Gas Town via a verification-gated lifecycle molecule.

## Purpose
When Mayor executes "boot up gas town", this proto provides the workflow.
Each step has action + verification - steps stay open until outcome is confirmed.

## Key Principles
1. **Verification-gated steps** - Not "command ran" but "outcome confirmed"
2. **gt peek for verification** - Capture session output to detect stalls
3. **gt nudge for recovery** - Reliable message delivery to unstick agents
4. **Parallel where possible** - Witnesses and refineries can start in parallel
5. **Ephemeral execution** - Boot is a wisp, squashed to digest after completion

## Step Structure
Each step has Action/Verify/OnStall/OnFail sections.

## Execution
```bash
bd mol spawn mol-gastown-boot  # Create wisp
bd mol run <wisp-id>           # Execute
```


CLI: core commands (status, prime, version, init)

Essential CLI commands for Gas Town operation.

## Commands

### gt status
Show overall town status.
```
gt status [--json]
```
Output:
- Town name and location
- Number of rigs
- Active polecats across all rigs
- Witness status per rig
- Recent activity summary

### gt prime
Output role context for current directory.
```
gt prime
```
Detects role from directory:
- Town root or mayor/ → Mayor context
- <rig>/witness/rig/ → Witness context
- <rig>/refinery/rig/ → Refinery context
- <rig>/polecats/<name>/ → Polecat context

### gt version
Show version information.
```
gt version [--short]
```
Output: version, git commit, build date.

### gt init
Initialize current rig for Gas Town (alternative to gt install for existing repos).
```
gt init [--force]
```
Creates Gas Town structure in existing git repo.

## Implementation

Each command is a Cobra subcommand under root:
```go
var statusCmd = &cobra.Command{...}
var primeCmd = &cobra.Command{...}
var versionCmd = &cobra.Command{...}
var initCmd = &cobra.Command{...}
```

Register in cmd/gt/main.go.


Work on gt-role-template: Refine witness/CLAUDE.md role t...

Work on gt-role-template: Refine witness/CLAUDE.md role template. Run 'bd show gt-role-template' to see the full issue.


CLI: workspace commands (init, add, list)

GGT needs workspace management commands beyond install.

## Commands (beyond gt-f9x.3 install)

### gt workspace list
List all rigs in current workspace.
```
gt workspace list [--json]
```
Essentially `gt rig list` but framed as workspace view.

### gt workspace add
Add existing rig to workspace (alternative to gt rig add).
```
gt workspace add <git-url> [--name NAME]
```

### gt onboard
Interactive first-time setup wizard.
```
gt onboard
```
- Prompts for workspace location
- Creates structure via gt install
- Offers to add first rig

## Note
May be redundant with gt-f9x.3 (install) and gt-u1j.16 (rig commands).
Consider if this is needed or should be closed as covered by those.

## PGT Reference
gastown-py/src/gastown/cli/workspace_cmd.py


gt session capture: Support positional line count argument

Make 'gt session capture gastown/Toast 50' work.

Currently requires: gt session capture gastown/Toast -n 50
Should also accept: gt session capture gastown/Toast 50

Agent UX principle: commands should work the way agents guess they work.


Digest: mol-deacon-patrol

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


gt session restart/status: Complete session management

Add missing session subcommands:

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

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


session stop: --force flag is defined but not used


Refinery startup: bond mol-refinery-patrol on start

Wire up Refinery to automatically bond its patrol molecule on startup.

## Current state
- mol-refinery-patrol exists in builtin_molecules.go
- prompts/roles/refinery.md describes the protocol
- Refinery doesn't auto-bond on startup

## Desired behavior
On Refinery session start:
1. gt prime detects RoleRefinery
2. Check for existing in-progress patrol: bd list --status=in_progress --assignee=refinery
3. If found: resume from current step
4. If not found: bd mol bond mol-refinery-patrol --wisp
5. Output patrol context to agent

## Implementation options
A) Add to gt prime (outputRefineryPatrolContext)
B) Add startup hook in refinery CLAUDE.md
C) Both (prime detects, template reinforces)

## Testing
- Start refinery session
- Verify patrol bonds automatically
- Kill mid-patrol, restart, verify resumes

## Depends on
- gt-3x0z.10 (existing issue for Refinery patrol)


Merge: gt-3x1

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


gt handoff: Deadlock bug in runHandoff

Running 'gt handoff' from a polecat causes a deadlock:

Stack trace shows:
- goroutine 1 [select (no cases)] in runHandoff
- File: internal/cmd/handoff.go:125

The command successfully sends the shutdown request but then hangs with 'fatal error: all goroutines are asleep - deadlock!'


implement

Implement the solution for gt-test123. 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


Add harness overview to Mayor priming

Update gt prime Mayor context to explain the harness concept: umbrella repo for GT installation, rigs underneath, Mayor sits above all rigs


Add crew lifecycle support to Deacon

Currently crew sessions (like gastown/crew/max, beads/crew/dave) are marked as 'human-managed' and excluded from automated lifecycle.

## Current State
- `getManager(RoleCrew)` returns `"human"` (handoff.go:273)
- `gt handoff` for crew just prints a message, no lifecycle request sent
- Crew cannot request automated refresh from Deacon

## Desired State
Crew members should be able to request lifecycle actions from Deacon:
- `gt handoff --cycle` sends request to Deacon, which kills/restarts the crew session
- Useful when: context full, running molecules that need fresh session, automation

## Implementation
1. Change `getManager(RoleCrew)` to return `"deacon/"` (or new crew manager)
2. Teach Deacon to recognize crew session naming pattern
3. Add crew to Deacon's respawn loop handling
4. Test with `gt nudge` for reliable message delivery

## Use Case
Running a molecule (e.g., version-bump) and discovering mid-workflow that a fresh session is needed. Agent should be able to request refresh automatically rather than requiring human intervention.

## Related
- gt nudge: reliable message delivery to Claude sessions
- bd mol bond: molecule instantiation (coming in beads)


Merge: gt-rana.4

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


gt daemon: Background service management

## Summary

ONE daemon for all Gas Town - a simple Go process (not a Claude agent) that:
1. Pokes agents periodically (heartbeat)
2. Processes lifecycle requests
3. Restarts sessions when agents request cycling

## Architecture

Daemon (gt daemon)
- Pokes Mayor: "HEARTBEAT: check your rigs"
- Pokes each Witness: "HEARTBEAT: check your workers"
- Has inbox at daemon/ for lifecycle requests
- Restarts sessions on cycle requests

## NOT the daemon's job:
- Making decisions (Witnesses do that)
- Running Claude (it's a Go process)
- Processing work (polecats do that)
- Direct polecat management (Witnesses do that)

The daemon is a **dumb scheduler** - poke things, execute lifecycle requests. All intelligence is in agents.

## Commands

- gt daemon start: Start daemon (background)
- gt daemon stop: Stop daemon
- gt daemon status: Show daemon status
- gt daemon logs: View daemon logs

## Daemon Loop

Every heartbeat interval:
1. Poke Mayor
2. For each rig: Poke Witness
3. Process lifecycle requests from daemon/ inbox
4. Check for dead sessions, restart if cycle requested

## Lifecycle Request Handling

Daemon checks its inbox (daemon/) for lifecycle requests:
- From Mayor: cycle/restart Mayor session
- From Witnesses: cycle/restart Witness session

On request:
1. Verify agent state shows requesting_cycle
2. Kill session
3. Start new session
4. Clear requesting_cycle flag

## Poke Protocol

Poke = tmux inject "HEARTBEAT: do your job"
- Agent ignores if already working
- Agent wakes up if idle
- Idempotent - multiple pokes are fine

## Lifecycle Hierarchy

- Daemon manages: Mayor, all Witnesses
- Witness manages: Polecats, Refinery (per rig)
- Crew: self-managed (human workspace)

## Related Issues

- gt-kmn.11: Daemon heartbeat details
- gt-gby: gt handoff command (unified lifecycle)
- gt-u1j.9: Fold witness daemon into this


MQ config schema: merge_queue section in rig config.json

Define and implement merge_queue configuration in rig config.

Schema:
{
  "merge_queue": {
    "enabled": true,
    "target_branch": "main",
    "integration_branches": true,
    "on_conflict": "assign_back",  // or "auto_rebase"
    "run_tests": true,
    "test_command": "go test ./...",
    "delete_merged_branches": true,
    "retry_flaky_tests": 1,
    "poll_interval": "30s",
    "max_concurrent": 1
  }
}

Implement:
- Config loading in rig package
- Default values
- Validation

Reference: docs/merge-queue-design.md#configuration


Polecat management: add, remove, list, state

Polecat lifecycle: add, remove, list, state tracking.

## Data Model

```go
type Polecat struct {
    Name      string          `json:"name"`
    Rig       string          `json:"rig"`
    State     PolecatState    `json:"state"`
    ClonePath string          `json:"clone_path"`
    Branch    string          `json:"branch"`
    Issue     string          `json:"issue,omitempty"`
    CreatedAt time.Time       `json:"created_at"`
    UpdatedAt time.Time       `json:"updated_at"`
}

type PolecatState string
const (
    StateIdle       PolecatState = "idle"
    StateActive     PolecatState = "active"
    StateWorking    PolecatState = "working"
    StateDone       PolecatState = "done"
    StateStuck      PolecatState = "stuck"
)
```

## Interface

```go
type PolecatManager struct {
    rig *Rig
    git *Git
}

func NewPolecatManager(rig *Rig, git *Git) *PolecatManager

// Lifecycle
func (pm *PolecatManager) Add(name string) (*Polecat, error)
func (pm *PolecatManager) Remove(name string) error
func (pm *PolecatManager) List() ([]*Polecat, error)
func (pm *PolecatManager) Get(name string) (*Polecat, error)

// State
func (pm *PolecatManager) SetState(name string, state PolecatState) error
func (pm *PolecatManager) AssignIssue(name, issue string) error
func (pm *PolecatManager) ClearIssue(name string) error

// Convenience
func (pm *PolecatManager) Wake(name string) error   // idle → active
func (pm *PolecatManager) Sleep(name string) error  // active → idle
```

## Add Flow

1. Create directory: `<rig>/polecats/<name>/`
2. Clone rig repo into it (or copy from rig root)
3. Create new branch: `polecat/<name>`
4. Initialize polecat state file
5. Create mail inbox

## Remove Flow

1. Verify session not running
2. Check for uncommitted changes (warn/error)
3. Remove directory
4. Clean up state

## State Persistence

Store in `<rig>/polecats/<name>/state.json`


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

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


Auto-handoff: self-cycling with guaranteed work pickup

## Summary

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

## Use Case

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

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

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

## Key Requirements

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

## Design Questions

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

## Related

- Molecules system
- Deacon lifecycle management
- Handoff hooks


Recover stale polecat work: 4 branches with unpushed commits

During observation of polecat workflow, found 4 polecats with unpushed work:

## Branches Pushed (preserved)
- polecat/capable: 3 commits (molecule catalog, doctor orphan detection, gt done)
- polecat/dementus: 4 commits (Witness MVP, handoff fixes)
- polecat/furiosa: 2 commits (bulk polecat removal, spawn handoff)
- polecat/rictus: 1 commit (molecule docs)

## Action Required
1. Review each branch for merge-worthiness
2. Either:
   a. Create PRs for valuable work
   b. OR discard if superseded
3. After decision, clean up polecats properly

## Root Cause
Polecats were not cleaned up after previous work sessions. This is exactly why we need:
- gt-u1k: gt shutdown should fully cleanup polecats
- gt-8v8: Refuse to lose uncommitted work
- gt-9nf: Always create fresh polecats


Session cycling: Auto-spawn successor when context full

Enable automatic session succession for crew workers.

When a crew worker's context fills up (>80%), they should:
1. Write handoff mail to themselves
2. Signal session end
3. System auto-spawns successor session
4. Successor reads handoff, finds attached work, auto-continues

This completes the autonomous overnight work pattern from gt-9g82.

Depends on:
- Detecting context fullness (Claude Code API?)
- Session spawning mechanism (tmux/daemon)
- Handoff protocol already implemented


Update deacon.md.tmpl with correct molecule commands

The deacon prompt references commands that don't exist:
- gt mol bond → should be bd mol run or gt mol arm
- gt mol status → needs gt mol command tree first

Update after gt mol command tree is implemented.

Depends on: gt mol command tree issue


CloudRunOutpost: Basic implementation

## Overview

Basic CloudRunOutpost implementation. Persistent connections and cost tracking are separate tasks.

## Implementation

```go
type CloudRunOutpost struct {
    name        string
    project     string
    region      string
    service     string
    maxWorkers  int
    client      *WorkClient
    workers     map[string]*CloudRunWorker
    mu          sync.RWMutex
}

func NewCloudRunOutpost(cfg OutpostConfig) (*CloudRunOutpost, error) {
    serviceURL := fmt.Sprintf(
        "https://%s-%s.a.run.app",
        cfg.Service, cfg.Region,
    )
    return &CloudRunOutpost{
        name:       cfg.Name,
        project:    cfg.Project,
        region:     cfg.Region,
        service:    cfg.Service,
        maxWorkers: cfg.MaxWorkers,
        client:     NewWorkClient(serviceURL),
        workers:    make(map[string]*CloudRunWorker),
    }, nil
}
```

## Spawn

```go
func (o *CloudRunOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {
    req := WorkRequest{
        IssueID: issue,
        Rig:     RigConfig{URL: cfg.RigURL, Branch: cfg.GitBranch},
        Beads:   BeadsConfig{URL: cfg.BeadsURL, Branch: "beads-sync"},
        Branch:  "polecat/" + issue,
    }

    events, err := o.client.DispatchWork(context.Background(), req)
    if err != nil {
        return nil, err
    }

    worker := &CloudRunWorker{
        id:      uuid.New().String(),
        outpost: o.name,
        issue:   issue,
        events:  events,
        status:  WorkerStatusWorking,
    }

    o.mu.Lock()
    o.workers[worker.id] = worker
    o.mu.Unlock()

    go worker.monitor()
    return worker, nil
}
```

## CloudRunWorker

```go
type CloudRunWorker struct {
    id      string
    outpost string
    issue   string
    status  WorkerStatus
    events  <-chan WorkEvent
    logs    []string
}

func (w *CloudRunWorker) Attach() error {
    return errors.New("Cloud Run workers do not support attach")
}

func (w *CloudRunWorker) Logs() (io.Reader, error) {
    return strings.NewReader(strings.Join(w.logs, "\n")), nil
}
```

## Files

- `internal/outpost/cloudrun.go`

## Dependencies

Depends on: gt-9a2.1 (interfaces), gt-9a2.12 (HTTP client)
Blocks: gt-9a2.13 (persistent connections), gt-9a2.14 (cost tracking)


Post-work discovery: AI analysis finds follow-on issues

AI analyzes completed work to discover: bugs, punted work, follow-on tasks.

**From VC**: Supervisor.AnalyzeResult() with iterative refinement. ~300 lines.

**Gas Town implementation**: Post-work hook in molecule:
```yaml
post_work:
  discover:
    - bugs
    - punted_items
    - follow_on_work
  file_as: beads
```

Polecat output gets analyzed by AI, discovered work becomes beads issues.

**Value**: Nothing gets forgotten. VC found ~25% more issues with refinement.

**Key**: Use semantic deduplication (gt-xxx) to avoid pollution.


beads: Stop searching upward when .beads found

## Problem

When running bd commands in a nested directory structure with multiple .beads directories, bd shows a confusing warning:

```
╔══════════════════════════════════════════════════════════════════════════╗
║ WARNING: 2 beads databases detected in directory hierarchy              ║
╠══════════════════════════════════════════════════════════════════════════╣
║ Multiple databases can cause confusion and database pollution.          ║
║                                                                          ║
║   /Users/stevey/gt/gastown/.beads (261 issues)                           ║
║   /Users/stevey/gt/.beads (21 issues)                                    ║
║                                                                          ║
║ WARNING: Not using the closest database! Check your BEADS_DB setting.   ║
║                                                                          ║
║ RECOMMENDED: Consolidate or remove unused databases to avoid confusion. ║
╚══════════════════════════════════════════════════════════════════════════╝
```

## Why This Is Wrong

In Gas Town, nested .beads directories are **intentional and necessary**:
- Town level: /Users/stevey/gt/.beads (mail, town-level issues)
- Rig level: /Users/stevey/gt/gastown/.beads (gastown project issues)
- Worker level: polecats have their own beads in worktrees

These are **unrelated** beads instances for different scopes. They should never be consolidated.

## Expected Behavior

When bd finds a .beads directory, it should:
1. Use that directory (closest ancestor wins)
2. **Stop searching upward** - do not look for parent .beads directories
3. **No warning** about multiple databases

## Current Behavior

bd searches all the way up to root, finds all .beads directories, and warns about "multiple databases" even though they are separate, intentional instances.

## Fix

In the database discovery code, stop the upward search as soon as a .beads directory is found. The first .beads found is the one to use, and parent directories are out of scope.

## Note

This is a beads issue, filed here for tracking. Should be implemented in the beads codebase.


Git safety audit module

Port git_audit.py safety checks to Go.

## Purpose

Before destroying polecat clones, verify no code is at risk.

## Checks

1. Uncommitted changes (staged and unstaged)
2. Unpushed commits
3. Git stashes
4. Local-only branches (not tracking remote)

## Beads-Only Classification

Some files are safe to discard:
- .beads/*
- .claude/settings.json

Changes only affecting these = "beads-only" = safe to destroy.

## Interface

```go
type GitAuditResult struct {
    Polecat              string
    Path                 string
    UncommittedFiles     []string
    UncommittedIsBeadsOnly bool
    UnpushedCommits      int
    Stashes              []StashInfo
    StashesAreBeadsOnly  bool
    LocalBranches        []string
    Error                error
}

func (r *GitAuditResult) HasCodeAtRisk() bool

func AuditPolecat(name string, path string) *GitAuditResult
func AuditPolecats(polecats []PolecatInfo) []*GitAuditResult
```

## Reference

PGT: swarm/git_audit.py


Architecture: beads config and direct landing docs

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


bd close --continue: auto-advance to next molecule step

Add --continue flag to bd close for seamless molecule step transitions.

## Usage

bd close <step-id> --continue [--no-auto]

## Behavior

1. Closes the specified step
2. Finds next ready step in same molecule (sibling/child)
3. By default, marks it in_progress (--no-auto to skip)
4. Outputs the transition

## Output

[checkmark] Closed gt-abc.3: Implement feature

Next ready in molecule:
  gt-abc.4: Write tests

[arrow] Marked in_progress (use --no-auto to skip)

## If no next step

[checkmark] Closed gt-abc.6: Exit decision

Molecule gt-abc complete! All steps closed.
Consider: bd mol squash gt-abc --summary '...'

## Key behaviors
- Detects parent molecule from closed step
- Finds next unblocked sibling
- Auto-claims by default (propulsion principle)
- Graceful handling when molecule is complete

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


Polecats must not create GitHub PRs

Polecats should never use 'gh pr create' or create GitHub pull requests.

## Correct Workflow
1. Polecat works on polecat/<name> branch
2. Commits and pushes to origin
3. Creates beads MR issue (type: merge-request)
4. Refinery processes the MR and merges to main

## Wrong Workflow
- Using gh pr create
- Creating GitHub pull requests directly

## Why
- Refinery is our merge queue processor
- GitHub PRs bypass our workflow
- Beads MRs are the coordination mechanism


init.go: Replace custom contains() with strings.Contains


mol-code-review: Self-improving code review molecule

Create a code review molecule that enables Gas Town to self-improve through automated PR review. Flywheel: review generates quality checks, discovered issues, pattern learning.


gt crew restart command

Add a 'gt crew restart' command that kills the tmux session and restarts fresh. Useful when a crew member gets confused or needs a clean slate.

Should:
- Kill existing tmux session if running
- Start fresh session with claude
- Run gt prime to reinitialize context

Alias: gt crew rs


Refinery-Witness communication protocol

Define mail protocol between Refinery and Witness:

FROM Witness → Refinery:
- 'Polecat ready': polecat X completed work, ready for merge
- 'Rework complete': polecat Y finished requested rework

FROM Refinery → Witness:
- 'Merge success': polecat X merged, can be cleaned up
- 'Merge failed': polecat X needs rework on <reason>
- 'Rework request': please have a polecat rebase X on current main

Implement as structured mail with parseable format.


Epic: Wisp Molecule Integration

## Vision

Integrate Beads wisp molecules into Gas Town. All orchestration work runs as wisp molecules - patrols, polecat workflows, batch operations. Only digests reach main beads.

## The Steam Engine Metaphor

```
Engine does work → generates steam
Steam wisps rise → execution trace
Steam condenses → digest (distillate)
Steam dissipates → cleaned up (burned)
```

## Architecture

```
Proto Molecules (templates)
    ↓ bd mol bond
Wisps (.beads-wisps/ or inline)
    ↓ bd mol squash + AI summary
Main Beads (digests only)
```

## Vocabulary

| Term | Meaning |
|------|---------|
| bond | Attach proto to work (creates wisps) |
| wisp | Temporary execution step (steam rising) |
| squash | Condense wisps into digest |
| burn | Destroy wisps without record |
| digest | Permanent condensed record (distillate) |

## Key Design Decisions

1. **Wisp location**: Per-rig or inline in main beads with wisp flag
2. **Summary generation**: Agent that did work generates summary (inversion of control)
3. **Squash timing**: Final step of molecule workflow, before signaling done
4. **Crash recovery**: Wisps persist, Witness detects stalls, new agent resumes
5. **Patrols**: Each cycle is fresh wisp molecule, squashed on completion

## Digest Contents

- Molecule type and instance ID
- Assignee, start/end times
- Source issue reference
- AI-generated summary
- Outcomes (issues closed, commits, branches)

## Integration Points

- gt rig init: Configure wisp storage
- gt spawn --molecule: Bond creates wisps
- gt prime: Show wisp molecule context
- Polecat CLAUDE.md: Summary + squash protocol
- gt doctor: Wisp health checks
- Deacon/Witness/Refinery: Patrol molecules

## Phases

Phase 1: Wisp setup infrastructure
Phase 2: Spawn integration
Phase 3: Completion flow (summary + squash)
Phase 4: Patrol integration
Phase 5: Documentation and polish


Design: Additional design issues (placeholder)

Placeholder for additional design issues the user wants to raise and work through. Convert to specific subtasks as issues are identified.


MR ID generation: prefix-mr-hash convention

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

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

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

Implement: GenerateMRID(prefix, branch string) string

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


Town Doctor molecule for harness health checks

Create a Town Doctor molecule that any Gas Town agent can run to diagnose and repair harness issues.

## Concept

Instead of just `gt doctor` as a CLI command with hardcoded checks, create a **molecule** (checklist workflow) that:
- Any agent (Mayor, Witness, Polecat) can instantiate
- Walks the agent through diagnostic steps
- Agent uses judgment to fix issues found
- Works as a structured troubleshooting guide

## Why a Molecule?

1. **Agent-driven**: The agent running it becomes "the doctor" temporarily
2. **Extensible**: Add new checks by updating the molecule, not code
3. **Contextual**: Agent can reason about issues, not just run scripts
4. **Self-healing**: Agent can fix problems it finds, not just report them

## Proposed Checks (molecule steps)

1. Verify harness structure (mayor/, .beads/, CLAUDE.md exist)
2. Validate config files (town.json, rigs.json parse correctly)
3. Check beads health (bd doctor, redirect validity)
4. Verify git state (clean working tree, proper remotes)
5. Check rig integrity (each registered rig exists, has config.json)
6. Validate agent clones (mayor/rig/, refinery/rig/ exist and are valid)
7. Check for orphaned worktrees/branches
8. Verify daemon state (if running)

## Integration

- `gt doctor` could instantiate the molecule for the current agent
- Or agent can run `bd ready` and pick up doctor tasks when prioritized
- Results logged to beads for audit trail

## Related

- gt-cr9: Harness Design & Documentation (completed)
- Molecules design in architecture.md


gt mq integration status: show integration branch status

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

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

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

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

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

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


Harness & Priming: Document architecture and update all role contexts


Merge: gt-3x0z.1

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


load-context

Run gt prime and bd prime. Verify issue assignment.
Check inbox for any relevant messages.

Read the assigned issue (gt-test123) and understand the requirements.
Identify any blockers or missing information.


Pinned Beads: Ongoing concerns and anchors

Pinned beads represent persistent concerns that do not close traditionally. Stay out of bd ready. Examples: Monitor production, Weekly syncs. Implementation: pinned: true field on bead.


Adaptive backoff for daemon heartbeat

Track agent responsiveness and adjust heartbeat frequency.

## Per-Agent State

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

## Strategy Options

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

## Recovery

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

## Benefits

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


Outpost/Worker interfaces: Core abstractions for remote compute

## Overview

Define the core interfaces that all outpost types implement.

## Interfaces

```go
type OutpostType string
const (
    OutpostLocal    OutpostType = "local"
    OutpostSSH      OutpostType = "ssh"
    OutpostCloudRun OutpostType = "cloudrun"
)

type Outpost interface {
    Name() string
    Type() OutpostType
    MaxWorkers() int
    ActiveWorkers() int
    Spawn(issue string, config WorkerConfig) (Worker, error)
    Workers() []Worker
    Ping() error
    SendMail(worker string, msg Message) error  // optional
}

type Worker interface {
    ID() string
    Outpost() string
    Status() WorkerStatus  // idle, working, done, failed
    Issue() string
    Attach() error         // for interactive outposts
    Logs() (io.Reader, error)
    Stop() error
}

type WorkerConfig struct {
    RigPath    string
    BeadsDir   string
    GitBranch  string
    Context    map[string]string  // hints for worker
}
```

## Files

- `internal/outpost/outpost.go` - Outpost interface
- `internal/outpost/worker.go` - Worker interface
- `internal/outpost/config.go` - WorkerConfig, OutpostType

## Notes

This is the foundation for all federation work. Keep interfaces minimal - we can extend later.


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


Extend auto-continue to polecats (not just crew)

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

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

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

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

This applies to ALL workers, not just crew.

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


Work on ga-p6r: Add handoff protocol to spawn priming. En...

Work on ga-p6r: Add handoff protocol to spawn priming. Ensure polecats receive handoff context when spawned. When done, submit MR (not PR) to integration branch for Refinery.


Update config location: .gastown/ → config/

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

Hidden directories are poorly discovered by AI agents.


ensure-gastown-refinery

Start the gastown rig Refinery.

## Action
```bash
gt refinery start gastown
```

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

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

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


mol-witness-patrol molecule definition

Create mol-witness-patrol in builtin_molecules.go.

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

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

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


Add merge-request type to Beads schema

Define the merge-request bead type with fields:
- branch: source branch (e.g., polecat/Nux/gt-xxx)
- target_branch: destination (main or integration/xxx)
- source_issue: the work being merged (gt-xxx)
- worker: who did the work
- rig: which rig
- merge_commit: (filled on close) SHA of merge commit
- close_reason: (filled on close) success/failure details

This may require beads schema changes or just convention.


implement

Implement the solution for gt-test123. 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


Merge: gt-xw7b

branch: polecat/morsov
target: main
source_issue: gt-xw7b
rig: gastown


Remove stale migration docs from gastown-py

The gastown-py repo has migration-related documentation that is now misinformation since we have made design decisions. Remove or clearly mark as obsolete: any docs about migration paths, old architecture assumptions, or superseded designs.


MR state transitions: validate open→in_progress→closed

Enforce valid state transitions for merge-requests:

Valid transitions:
- open → in_progress (Engineer claims MR)
- in_progress → closed (merge success or rejection)
- in_progress → open (failure, reassign to worker)
- open → closed (manual rejection)

Invalid:
- closed → anything (immutable once closed)

Implement validation in MR update operations.

Reference: docs/merge-queue-design.md#state-machine


Digest: mol-deacon-patrol

Patrol: 2 completions (valkyrie gt-yd98 MQ, scrotus gt-mzal.1 boot proto). 8 polecats working.


Swarm learning: Beads database locality gap

## PGT Bug (GGT Design Already Correct)

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

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

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


gt mail inbox doesn't find crew worker mail - identity mismatch

## Problem

Crew workers don't see their handoff messages when running `gt mail inbox` from their working directory.

## Root Cause

gt derives identity from cwd path, but crew workers have a different path structure:
- **cwd**: `/Users/stevey/gt/beads/crew/dave`
- **gt derives**: `beads/crew/dave` (wrong)
- **should be**: `beads/dave` (crew workers use `rig/name` format)

Messages sent to `beads/dave` don't show up because gt is looking for `beads/crew/dave`.

## Workaround

Use explicit identity flag:
```bash
gt mail inbox --identity "beads/dave"
```

## Fix

Identity detection in gt should handle crew/ subdirectory:
- Path `<rig>/crew/<name>` should derive identity as `<rig>/<name>`
- This matches how polecats work: `<rig>/polecats/<name>` → `<rig>/<name>`

## Affected

All crew workers in all rigs.


tmux notifications: display-message too subtle, use send-keys instead

## Problem

`tmux display-message` notifications are not visible enough - they appear briefly in the status bar and are easy to miss.

## Current Behavior

router.go uses:
```go
r.tmux.DisplayMessageDefault(sessionID, notification)
```

## What Works

Sending echo commands directly to the terminal:
```bash
tmux send-keys -t <session> "echo '📬 NEW MAIL from mayor'" Enter
```

## Proposed Fix

Change notification method to send visible output to the terminal, perhaps with a box/banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📬 NEW MAIL from mayor
Subject: <subject>
Run: bd mail inbox
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

## Considerations

- This interrupts the terminal output (acceptable for important mail)
- Could check if Claude is mid-response and queue notification
- Or use tmux popup if available

Additional issues:
1. Enter key not sent properly when chained with send-keys
2. Need to debounce and send Enter separately
3. Correct pattern: send text, sleep briefly, then send Enter


Add molecule phase lifecycle diagram to architecture.md

Create a clear lifecycle diagram showing molecule phases:

```
                    ┌─────────────┐
                    │   Proto     │
                    │  (crystal)  │
                    └──────┬──────┘
                           │
                      bd mol bond
                           │
              ┌────────────┴────────────┐
              │                         │
              ▼                         ▼
      ┌───────────────┐        ┌───────────────┐
      │     Mol       │        │    Wisp       │
      │   (liquid)    │        │    (gas)      │
      │   durable     │        │  ephemeral    │
      │  main beads   │        │ .beads-eph/   │
      └───────┬───────┘        └───────┬───────┘
              │                        │
         bd mol squash            bd mol squash
              │                        │
              ▼                        ▼
      ┌───────────────┐        ┌───────────────┐
      │    Digest     │        │   (nothing)   │
      │ (distillate)  │        │  evaporates   │
      │  in git hist  │        └───────────────┘
      └───────────────┘
```

Also document:
- When to use Mol vs Wisp
- Mol: code review waves, epic implementation, feature work
- Wisp: orchestration, polecat work sessions, patrol loops


Crew directory structure and config

Add crew/ directory support to rig structure. Include:
- crew/ as peer to polecats/, refinery/, witness/
- Crew worker subdirectories with full git clones
- Optional BEADS_DIR configuration for beads integration
- Crew state tracking (separate from polecat state)


gt spawn should create fresh polecat worktree, never reuse

Currently gt spawn tries to reuse existing polecats, which causes:

1. Stale beads database
2. Stale code (behind main/integration)
3. Old inbox messages
4. Git history pollution

## Current Behavior

gt spawn:
1. Looks for idle polecat in pool
2. If found, reuses existing worktree
3. Assigns new issue

## Desired Behavior

gt spawn:
1. Always create FRESH polecat from current main/integration
2. Fresh worktree with clean beads
3. No reuse of old worktrees

## Name Pool Still Useful

Keep name pool for:
- Allocating themed names (mad-max, etc.)
- Tracking which names are in use

But worktrees should be created fresh each time.

## Implementation

In spawn.go, before starting work:
1. If worktree exists: remove it first
2. Create fresh worktree from integration branch
3. Sync beads from rig to polecat
4. Then proceed with work assignment

This ensures polecats always start with latest code and beads.


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-svi.1

type: merge-request
branch: polecat/Max
target: main
source_issue: gt-svi.1
rig: gastown


ensure-refineries

Parallel container: Start all rig refineries.

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

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

## Verify
All child refinery steps pass verification.


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.

Depends: implement


Document merge queue architecture

Update docs/architecture.md with:

- Merge Queue section explaining Beads-native approach
- Engineer role (renamed from Refinery)
- Session restart protocol
- gt mq command reference
- Federation considerations for queue

Also update any references to .gastown/ → config/.


Work on gt-role-template: Refine witness/CLAUDE.md role t...

Work on gt-role-template: Refine witness/CLAUDE.md role template. See issue for details. Run 'bd show gt-role-template' to see the full issue.


Update prompts.md: Engineer role and templates

Update docs/prompts.md with Engineer role:

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


Remove bd sync instruction from polecat startup workflow

Polecats are instructed to run `bd sync --from-main` on startup (spawn.go:634).

## Problem
- Spawn command already syncs beads before spawning (line 239)
- Polecats share rig-level beads via `.beads/redirect`
- Multiple polecats starting simultaneously all try to sync same shared beads
- This causes git conflicts/failures when many polecats spawn at once

## Observed
User reported: 'all polecats failing on beads sync on startup in one run'

## Fix
Remove line 634 from buildWorkAssignmentMail():
```
body.WriteString("2. Run \`bd sync --from-main\` to get fresh beads\n")
```

Polecats only need to sync at END of work (already in steps 5/7).

## Files
- internal/cmd/spawn.go: buildWorkAssignmentMail() and buildSpawnContext()


Merge: gt-a95

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


Polecat CLAUDE.md: configure auto-approve for bd and gt commands

Polecats get stuck waiting for bash command approval when running
bd and gt commands. Need to configure Claude Code to auto-approve these.

Options:
1. Add allowedTools to polecat CLAUDE.md
2. Configure .claude/settings.json in polecat directory
3. Use --dangerously-skip-permissions flag (not recommended)

Should auto-approve:
- bd (beads commands)
- gt (gastown commands)
- go build/test
- git status/add/commit/push

Should still require approval:
- rm -rf
- Arbitrary commands outside project

Related to polecat prompting (gt-e1y, gt-sd6).


Phase 2: Quiescent agents (Witness, Refinery)

Enable Witness and Refinery to sleep until triggered.

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

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

Depends: Phase 1 complete


Phase 1.3: gt doctor checks for ephemeral health

Add doctor checks for ephemeral beads repo.

## Checks

1. **ephemeral-exists**: .beads-ephemeral/ directory exists for each rig
2. **ephemeral-git**: It's a valid git repo
3. **ephemeral-orphans**: Molecules started but never squashed (>24h old)
4. **ephemeral-size**: Warn if ephemeral repo is >100MB (should be cleaned)
5. **ephemeral-stale**: Molecules with no activity in last hour

## Auto-fix

--fix can:
- Create missing ephemeral repo
- Clean up old completed molecules (already squashed)
- NOT auto-squash incomplete molecules (needs AI summary)


Direct test

Testing direct bd create


HOP: Skill vectors on work items

Add skill embeddings to work items for capability-based matching. See ~/ai/stevey-gastown/hop/CONTEXT.md. Post-v0.1 work.


Test4

test4 body


Use cmd.OutOrStdout instead of fmt.Print in refinery

refinery/manager.go and refinery/engineer.go use fmt.Print/Println directly for user output (30+ occurrences). This breaks testability and doesn't follow cobra best practices. Should use cmd.OutOrStdout() or pass an io.Writer.

Affected files:
- internal/refinery/manager.go (lines 222, 360-361, 369, 387-393, 519, 537, 672)
- internal/refinery/engineer.go (lines 190-211, 249, 294-297, 325-353, 362-366)


Session pre-shutdown checks

Session stop should verify clean state before killing, like PGT.

## Pre-Shutdown Checks

### 1. Git Working Tree Clean
```go
func checkGitClean(clonePath string) error {
    // git status --porcelain
    // Fail if any output
}
```

### 2. All Commits Pushed
```go
func checkCommitsPushed(clonePath string) error {
    // git log origin/HEAD..HEAD
    // Fail if any unpushed commits
}
```

### 3. Assigned Issues Handled
```go
func checkIssuesHandled(polecat *Polecat) error {
    // If polecat.Issue != "", check if closed or reassigned
}
```

### 4. Beads Synced
```go
func checkBeadsSynced(clonePath string) error {
    // bd sync --status in clone directory
}
```

## Behavior on Failure
1. First attempt: Nudge worker to fix
2. Retry up to 3 times with delay
3. After retries: Escalate to Witness/Mayor

## Integration
Modify internal/session/manager.go Stop():
```go
func (m *Manager) Stop(polecat string, force bool) error {
    if !force {
        if err := m.runPreShutdownChecks(polecat); err != nil {
            return fmt.Errorf("pre-shutdown checks failed: %w", err)
        }
    }
    // existing stop logic
}
```

## Flags
- --force: Skip checks
- --grace-period N: Time to wait for fixes

## Dependencies
- Ties into gt-69l (hook system) - can be hook-based
- Ties into gt-f8v (Witness pre-kill verification)

## Acceptance Criteria
- [ ] Stop fails if uncommitted changes (without --force)
- [ ] Stop fails if unpushed commits
- [ ] Clear error messages with fix instructions
- [ ] --force bypasses all checks


gt spawn: beads sync warnings on fresh worktree

When spawning fresh polecats, seeing 'Warning: beads sync: exit status 1' and 'Warning: beads push: exit status 1'. Worktrees are created but beads state may not be properly synced.


Extended addressing: Parse [machine:]rig/polecat

Extended addressing for cross-machine operations.

## Address Format

```
[machine:]rig/polecat
```

Examples:
- `wyvern/Toast` - Local machine, wyvern rig, Toast polecat
- `gcp-vm-1:wyvern/Toast` - Remote machine
- `wyvern/` - Broadcast to rig
- `gcp-vm-1:wyvern/` - Broadcast to remote rig

## Parser

```go
type Address struct {
    Machine  string  // empty = local
    Rig      string
    Polecat  string  // empty = broadcast
}

func ParseAddress(s string) (*Address, error)
func (a *Address) String() string
func (a *Address) IsLocal() bool
func (a *Address) IsBroadcast() bool
```

## Validation

```go
func (a *Address) Validate(registry *MachineRegistry) error
```
- Machine must exist in registry (if specified)
- Rig must exist on machine
- Polecat must exist (if specified)

## Usage

All CLI commands that take addresses use ParseAddress:
```go
// gt mail send gcp-vm-1:wyvern/Toast -s "Hello"
addr, _ := ParseAddress("gcp-vm-1:wyvern/Toast")
conn, _ := registry.Connection(addr.Machine)
// Use conn for operations
```

## Backward Compatibility

Existing `rig/polecat` addresses work unchanged (Machine defaults to local).


MCP beads tools fail from polecat directories

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

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

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

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


Add 'wit' alias for witness command

ref works as alias for refinery, but wit doesn't work for witness. Add Aliases: []string{"wit"} to witnessCmd.


Step recovery: timeout and release

Implement recovery mechanism for stuck molecule steps.

## Problem
When a worker dies mid-step, the step stays in_progress forever.
Need timeout/release mechanism for nondeterministic idempotence.

## Solution
1. Track step start time (claimed_at timestamp)
2. Timeout: After 30 min in_progress, step returns to pending
3. Manual release: bd release <step-id>

## Implementation Options

### Option A: Beads-level timeout
- Add claimed_at field to issues
- bd ready excludes items in_progress < 30 min
- bd ready includes items in_progress > 30 min (auto-recovery)

### Option B: Daemon-level timeout
- Daemon watches in_progress items
- Moves back to pending after timeout

### Option C: Manual only (MVP)
- bd release <id> manually moves in_progress → pending
- Document recovery procedure
- Witness can automate for polecats

## Recommendation
Start with Option C (manual) for Christmas. Add Option A later.

## Acceptance
- [ ] bd release command works
- [ ] Stuck steps can be recovered
- [ ] Documented recovery procedure


Plugin: merge-oracle (merge queue analysis)

Example plugin that analyzes changesets before Refinery processes them. Builds overlap graph, classifies disjointness (parallel-safe vs needs-sequencing), uses LLM for semantic complexity, identifies high-risk patterns. Based on merge-orchestration proposal. See docs/architecture.md.


Merge: gt-5af.5

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


Test MR

test


gt done: Command doesn't exist but documented in polecat CLAUDE.md

The polecat CLAUDE.md documents 'gt done' as the command to signal work is ready for merge queue, but running it gives 'unknown command'. Either implement the command or update the documentation.


Bug: LIFECYCLE messages use literal <rig> placeholder

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

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

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


Swarm learning: Spawn should auto-notify polecats

town spawn assigns issues but doesn't notify polecats. Required separate 'town session send' to inject prompts. This should be one atomic operation - spawn assigns AND pokes the polecat to start working.


CloudRun worker container: Dockerfile and entrypoint

## Overview

Docker container image for Cloud Run workers.

## Dockerfile

```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o gt ./cmd/gt

FROM ubuntu:22.04

# Install Claude Code
RUN apt-get update && apt-get install -y     curl git nodejs npm     && npm install -g @anthropic-ai/claude-code     && apt-get clean

# Install gt
COPY --from=builder /app/gt /usr/local/bin/gt

# Worker entrypoint
COPY deploy/cloudrun/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 8080
ENTRYPOINT ["/entrypoint.sh"]
```

## Entrypoint

```bash
#!/bin/bash
git config --global user.name "$GIT_USER"
git config --global user.email "$GIT_EMAIL"
exec gt worker serve --port 8080
```

## Files

- `deploy/cloudrun/Dockerfile`
- `deploy/cloudrun/entrypoint.sh`
- `deploy/cloudrun/README.md`

## Dependencies

Depends on: gt-9a2.11 (HTTP server - gt worker serve)


Add no-PR instructions to mol-polecat-work at two points

Update mol-polecat-work in builtin_molecules.go to explicitly forbid GitHub PRs.

## Two Points to Add Instructions

### 1. submit-work step
When polecat is ready to submit:
- Push branch to origin
- Create beads merge-request issue
- DO NOT use gh pr create or GitHub PRs

### 2. CLAUDE.md polecat context
Add to polecat role instructions:
- Never use gh pr create
- Never create GitHub pull requests
- The Refinery processes merges via beads MR issues

## Why Two Points
- Molecule step description guides the workflow
- CLAUDE.md reinforces at context level
- Belt and suspenders approach

## Implementation
1. Update PolecatWorkMolecule() submit-work step description
2. Update prompts/roles/polecat.md with explicit prohibition

Related: gt-44wh (general no-PR bug)


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)


HTTP work server: gt worker serve command

## Overview

HTTP server that runs inside Cloud Run containers, accepting work requests.

## Command

```bash
gt worker serve --port 8080
```

## Implementation

```go
type WorkServer struct {
    port    int
    handler *WorkHandler
}

func (s *WorkServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    switch r.URL.Path {
    case "/work":
        s.handleWork(w, r)
    case "/health":
        s.handleHealth(w, r)
    default:
        http.NotFound(w, r)
    }
}

func (s *WorkServer) handleWork(w http.ResponseWriter, r *http.Request) {
    // 1. Parse WorkRequest
    // 2. Clone/pull repo
    // 3. Start Claude on issue
    // 4. Stream WorkEvents as NDJSON
    // 5. Return WorkResult
}
```

## Streaming Response

```go
func (s *WorkServer) streamEvents(w http.ResponseWriter, events <-chan WorkEvent) {
    flusher, _ := w.(http.Flusher)
    encoder := json.NewEncoder(w)
    for event := range events {
        encoder.Encode(event)
        flusher.Flush()
    }
}
```

## Files

- `internal/cloudrun/server.go`
- `cmd/gt/worker_serve.go` - Cobra command

## Dependencies

Depends on: gt-9a2.7 (protocol types)


bd ready --type: missing type filter for MQ integration

bd ready lacks --type flag that engineer.go expects.

## Code (internal/refinery/engineer.go)
readyMRs, err := e.beads.ReadyWithType("merge-request")

## Actual bd ready
No --type flag - only supports assignee, label, priority filters.

## Impact
Refinery can't find merge-requests in queue, so MQ doesn't process anything.

## Fix Options
1. Add --type flag to bd ready
2. Use bd list --type=merge-request --status=open instead
3. Both (ready filters for unblocked, list for all)

This is blocking the entire MQ pipeline.


Digest: mol-deacon-patrol

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


Polecat .beads/ contamination from stale branches

**Fixed in commit 8699b7b**

## Problem

When polecats are spawned from branches that previously had bd sync run on them, the .beads/ directory from the branch contains stale issues.jsonl, config.yaml, etc.

The setupSharedBeads() function was creating a redirect file, but NOT cleaning up the existing .beads/ contents first.

## Root Cause

1. Old polecat branch has .beads/ tracked in git (from previous bd sync)
2. gt spawn uses Add() which reuses existing branch
3. WorktreeAddExisting() checks out branch, including .beads/ files
4. setupSharedBeads() creates redirect, but other files remain
5. bd commands see stale data

## Fix

setupSharedBeads() now:
1. Removes entire .beads/ directory if it exists
2. Recreates fresh with only redirect file
3. Redirect points directly to mayor/rig/.beads (not through rig root)


Swarm cleanup: delete merged polecat branches and reset state

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

## Current Problem

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

## Observed After Swarm

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

## Proposed Solution

Add cleanup commands:

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

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

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

## Manual Cleanup For Now

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


Merge: gt-qsvq

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


SSHOutpost: Full Gas Town clone on remote VM

## Overview

Implement SSHOutpost for running workers on remote VMs via SSH.

## Model

Remote VM has a full Gas Town clone. SSHOutpost:
- Connects via SSH
- Spawns tmux sessions on remote
- Uses remote git clone for code/beads
- Syncs via git push/pull

## Implementation

```go
type SSHOutpost struct {
    name       string
    host       string
    user       string
    keyPath    string
    townPath   string  // e.g., /home/steve/ai
    maxWorkers int
    conn       *ssh.Client
}

func NewSSHOutpost(config OutpostConfig) (*SSHOutpost, error)

func (o *SSHOutpost) Spawn(issue string, cfg WorkerConfig) (Worker, error) {
    // SSH: create tmux session on remote
    // SSH: start claude in session
    // Return SSHWorker
}

func (o *SSHOutpost) Ping() error {
    // Test SSH connectivity
}
```

## SSHWorker

```go
type SSHWorker struct {
    outpost *SSHOutpost
    id      string
    session string
    issue   string
}

func (w *SSHWorker) Attach() error {
    // SSH + tmux attach (opens terminal)
}

func (w *SSHWorker) Logs() (io.Reader, error) {
    // SSH: tmux capture-pane
}
```

## Prerequisites on Remote VM

1. Gas Town clone at townPath
2. Claude Code installed
3. Git credentials configured
4. SSH key access

## Integration with gt-f9x.7-8

This builds on the Connection interface from gt-f9x.7/8. SSHOutpost uses SSHConnection internally for remote operations.

Depends on: gt-9a2.1 (interfaces), gt-f9x.7 (Connection interface)


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.


Implement bd mol bond --ephemeral flag

Add --ephemeral flag to bd mol bond command to support ephemeral molecule bonding.

## Context
Phase 1.2 of Wisp Molecule Integration (gt-3x0z.2) discovered that this flag doesn't exist.

## Requirements

1. Add --ephemeral flag to mol bond command
2. When --ephemeral is set:
   - Mark spawned issues with wisp=true
   - Optionally write to separate .beads-ephemeral/ storage (Phase 2)

## Architecture Reference
See gastown architecture.md lines 487-491 for the full ephemeral storage design.

## Related
- gt-3x0z.2: Configure bd for ephemeral molecule bonding (closed - blocked on this)


Spawn --molecule integration

Implement gt spawn --molecule flag for molecule-based polecat workflows.

Usage: gt spawn --issue gt-xyz --molecule mol-gastown-polecat

Behavior:
1. Validate molecule exists and is well-formed
2. Create molecule instance (child beads) under the issue
3. Find first ready step(s) in the instance
4. Spawn polecat with first ready step as initial work

Implementation:
1. Add --molecule flag to spawn command
2. Call molecule.Instantiate()
3. Query ready steps from instance
4. Pass first ready step to polecat context

Files: internal/cmd/spawn.go

Acceptance:
- --molecule flag works
- Creates proper molecule instance
- Polecat starts on first ready step
- End-to-end test with actual polecat


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.


Digest: mol-deacon-patrol

Test patrol cycle - first run, no actual work done


CLI: spawn command

High-level command to spawn a polecat with work assignment.

## Command

```
gt spawn <rig>/<polecat> --issue <id>
gt spawn <rig> --issue <id>  # auto-select available polecat
gt spawn <rig>/<polecat> -m "Work on X"  # free-form task
```

## What It Does

1. Select or create polecat
2. Ensure polecat is in idle/active state
3. Assign the issue (update beads, set polecat state)
4. Start session (gt session start)
5. Inject initial context

## Options

- `--issue <id>`: Beads issue to assign
- `-m "message"`: Free-form work description
- `--create`: Create polecat if it does not exist
- `--no-start`: Assign work but do not start session

## Auto-Select Logic

If polecat not specified:
1. Look for idle polecats in rig
2. Prefer ones that worked on similar issues before
3. If none available, fail (or create if --create)

## Initial Context

Injects into session:
```
[SPAWN] You have been assigned: <issue-title>
Issue: <id>
Priority: <priority>

<description>

Work on this issue. Signal DONE when complete.
```

## Implementation

Orchestrates PolecatManager + SessionManager + Beads:
```go
func Spawn(rig, polecat, issue string, opts SpawnOptions) error
```


Enhanced polecat decommission prompting

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

## Checklist for AGENTS.md.template

```markdown
## Decommission Checklist

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

### Pre-Done Verification

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

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

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

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

### If Any Check Fails

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

### Signaling Done

Only after ALL checks pass:

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

## Implementation

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


Test: New Router

Testing bd create for mail


Add parallel step support to molecules

Enable steps to run in parallel within a molecule.

## Current State

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

## Proposed Change

Add parallel grouping:

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

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

Or via frontmatter:

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

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

## Implementation

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

## For Mayor Bootstrap

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


verify-tests

Run existing tests. Add new tests for new functionality.
Ensure adequate coverage.

go test ./...

Fix any test failures before proceeding.

Depends: implement


Pinned bead naming convention for all roles

Establish consistent naming convention for pinned beads across all roles.

## Problem

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

## Proposed Convention

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

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

## Storage Location

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

## Why This Matters

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

## Tasks

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

## Related

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


gt mq status: detailed MR view

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

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

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

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


gt polecat add: should handle existing branch gracefully

## Problem

`gt polecat add gastown Nux` fails if the branch `polecat/Nux` already exists.

## Current Behavior

```
fatal: a branch named 'polecat/Nux' already exists
```

## Expected Behavior

Should either:
1. Reuse the existing branch
2. Or prompt to delete/recreate
3. Or auto-suffix: polecat/Nux-2

## Context

Branch may exist from previous polecat that was removed but branch wasn't cleaned up.


gt rig shutdown: Gracefully stop all rig agents

Add 'gt rig shutdown <rig>' command to gracefully stop all agents in a rig.

Should:
- Stop all polecat sessions
- Stop refinery
- Stop witness
- Optionally wait for graceful shutdown with timeout


gt mail reply/thread: Conversation support

Add mail conversation features:

- gt mail reply <id> -m 'message' - Reply to a message
- gt mail thread <id> - Show all messages in a thread

Enables back-and-forth communication between agents.


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

Add a tmux health check to gt doctor that detects:

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

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

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

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


Refinery and witness rigs should redirect .beads to mayor rig

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

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

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

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


Daemon: integration test with real lifecycle

Need an end-to-end test that:
1. Starts daemon
2. Starts a test agent session
3. Sends lifecycle request to daemon
4. Verifies session was killed and restarted
5. Cleans up

Could use a mock 'agent' that's just a shell script.


Add godoc comments to exported functions

Several exported functions lack godoc comments. While not critical, adding documentation would improve code maintainability. Focus on:

- Public API functions in each package
- Exported types and their methods
- Functions that have non-obvious behavior

Can be addressed incrementally as code is touched.


Digest: mol-deacon-patrol

Patrol: read mayor handoff (gt-mzal boot design), all agents up, furiosa working gt-oiv0, note: gt-4eim orphaned (angharad gone)


Test message

Testing GGT mail integration


Design: Mayor session cycling and handoff

Design for Mayor session cycling and structured handoff.

## Overview

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

## Key Elements

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

## Subtasks (implementation)

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

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


mol-outpost-assign: Intelligent work routing to outposts

The federation design shows outposts.yaml with a static policy section. Simple preference ordering is fine as config, but intelligent work routing should be a molecule.

Current static approach:
```yaml
policy:
  default_preference: [local, gce-burst, cloudrun-burst]
```

Cases requiring cognition:
- "This is a long-running research task, route to VM not CloudRun"
- "This touches sensitive code, keep local"
- "These 5 issues are related, batch them to same outpost"
- "CloudRun cost is high today, prefer local even if slower"

## Molecule: outpost-assign
Intelligent work-to-outpost routing.

## Step: classify-work
Analyze the issue/work item:
- Expected duration (quick fix vs multi-hour)
- Resource requirements
- Sensitivity/security tier
- Related work (same epic?)

## Step: check-capacity
Query outpost status:
- Current load on each
- Cost accrued today
- Health status

## Step: select-outpost
Choose optimal outpost based on:
- Work classification
- Capacity/cost
- Policy constraints
Needs: classify-work, check-capacity

## Step: emit-assignment
Record decision in beads for audit.
Needs: select-outpost

## Notes
- This molecule is invoked by Mayor/Witness when spawning
- Simple cases can short-circuit to static policy
- Full analysis only for ambiguous cases


gt spawn: Not injecting work instructions to session

gt spawn starts session but doesn't inject the issue assignment.

Repro:
1. gt spawn gastown/Toast --issue gt-2ux
2. Session starts but polecat just sees Claude prompt
3. No issue context injected

Expected: Polecat should receive issue details automatically.
Actual: Polecat sits at blank prompt, needs manual injection.


Digest: mol-deacon-patrol

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


load-context

Run gt prime and bd prime. Verify issue assignment.
Check inbox for any relevant messages.

Read the assigned issue (gt-qwyu) and understand the requirements.
Identify any blockers or missing information.


Refactor: Eliminate state.json, use beads assignee field for polecat state

## Problem

state.json in each polecat worktree duplicates data that should be in beads:
- `issue` field duplicates assignment (should be issue.assignee)
- `state` field duplicates status (derivable from issue.status)
- `name/rig/branch/clone_path` are all derivable from filesystem/git

This violates 'Beads as the data plane' (HOP Decision 001).

## Current State

```json
{
  "name": "Angharad",        // Derivable: basename(cwd)
  "rig": "gastown",          // Derivable: parent dir name
  "state": "working",        // Should be: issue.status
  "clone_path": "/path",     // Derivable: cwd
  "branch": "polecat/X",     // Derivable: git branch
  "issue": "gt-xyz",         // Should be: issue.assignee
  "timestamps": "..."        // Should be in beads history
}
```

## Target State

**Polecat identity**: Derived from worktree path
**Polecat assignment**: `issue.assignee = 'gastown/Angharad'`
**Polecat state**: Derived from issue.status (in_progress = working, closed = done)
**Polecat existence**: Worktree directory exists

## Benefits

1. Single source of truth (no sync issues)
2. Queryable: `bd list --assignee=gastown/Angharad`
3. History tracking via beads
4. Cross-agent coordination via beads sync
5. Simpler code (no state file management)

## Implementation

1. Update `gt spawn` to set issue.assignee instead of writing state.json
2. Update polecat list/status commands to query beads
3. Update Witness to query beads for polecat state
4. Remove state.json read/write code
5. Keep state.json as optional bootstrap cache (perf optimization only)


Create mol-install-go-binary molecule

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

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

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

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

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

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

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


Work on ga-rd4: Add gt polecat status command. Show detai...

Work on ga-rd4: Add gt polecat status command. Show detailed polecat status including current issue, session state, last activity time. When done, submit MR (not PR) to integration branch for Refinery.


Merge: gt-3x1.3

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


Work on gt-ogr: Fix rig count in tmux status bar. The cou...

Work on gt-ogr: Fix rig count in tmux status bar. The count is showing wrong. Run 'bd show gt-ogr' for details.


Crew workers: design documentation and remaining work

## Summary

Crew workers are user-managed persistent workspaces within a rig, distinct from polecats.

## Current Implementation

### Commands (all working)
- `gt crew add <name>` - Create workspace (git clone)
- `gt crew list` - List workspaces with status
- `gt crew at <name>` - Attach to tmux session
- `gt crew remove <name>` - Remove workspace
- `gt crew pristine [<name>]` - git pull + bd sync
- `gt crew refresh <name>` - Context cycle with handoff mail
- `gt crew status [<name>]` - Detailed status
- `gt crew rename <name>` - Rename workspace

### Crew vs Polecat

| Aspect | Crew | Polecat |
|--------|------|---------|
| Lifecycle | User-managed | Witness-managed |
| Scheduling | Manual | `gt spawn` |
| Merge flow | Direct push OK | Integration branch → refinery |
| Garbage collection | Never | Auto on completion |
| Identity | Long-lived (emma, dave) | Ephemeral (Nux, Toast) |

## Known Bugs

- **gt-70b3**: detectSender() doesn't recognize crew workers
- **gt-vdp0**: Crew CLAUDE.md shows Refinery template

## Potential Enhancements

1. Rebase helper in `gt crew pristine` for conflict resolution
2. Cross-rig crew support (crew worker in multiple rigs?)
3. Better mail identity auto-detection for crew


Retry logic: exponential backoff for transient failures

Implement retry logic for transient failures.

Retryable failures:
- Push failed (network, auth transient)
- Test flaky (config: retry_flaky_tests)
- Fetch failed (network)

Retry strategy:
- Max retries: 3 (configurable)
- Backoff: 1s, 2s, 4s (exponential)
- On final failure: treat as permanent, assign back

Non-retryable failures:
- Merge conflict
- Test consistently fails
- Build error

Track retry count in MR metadata for debugging.

Reference: docs/merge-queue-design.md#failure-recovery


Molecule Phase Terminology Documentation

Document the three-phase molecule lifecycle with consistent terminology:

## The Phases (States of Matter)

| Phase | State | Nature |
|-------|-------|--------|
| **Proto** | Solid/Crystal | Frozen template, static definition in catalog |
| **Mol** | Liquid | Reified instance, malleable, tracked in git (durable) |
| **Wisp** | Gas | Evaporates after squash, ephemeral orchestration |

## Documentation Gaps Identified

### High Priority
1. Update vision.md Steam Engine metaphor to use proto/mol/wisp terminology
2. Add lifecycle diagram: Proto → bond → Mol or Wisp → squash → Digest
3. Document Go types for phases (ProtoMolecule, etc.)
4. Document .beads-ephemeral/ structure and purpose

### Medium Priority
5. Update CLAUDE.md files (polecat, witness, refinery) with molecule workflow
6. Document bd mol bond/squash/burn CLI API with examples
7. Add polecat guide: Executing molecules and generating summaries

### Low Priority
8. Add terminology glossary to architecture.md
9. Create troubleshooting playbook for stuck molecules
10. Add reference diagrams for state transitions

## Current State
- architecture.md has good molecule basics but uses inconsistent terminology
- vision.md has Steam Engine metaphor (proto=fuel, wisp=steam, digest=distillate)
- molecules.md has detailed reference but needs phase clarity
- builtin_molecules.go has 8 molecules but no phase documentation in code


Fetch and conflict check: git operations for MR

Implement git operations for MR processing.

Steps:
1. git fetch origin <mr.branch>
2. git checkout <mr.target> (main or integration/xxx)
3. git merge --no-commit --no-ff <mr.branch> (test merge)
4. Check for conflicts
5. If conflicts: abort and return Failure(conflict, files)
6. If clean: abort (actual merge in next step)

Helper functions:
- FetchBranch(branch string) error
- CheckConflicts(source, target string) ([]string, error)

Reference: docs/merge-queue-design.md#process-merge-steps


Fix TestHasPolecat test failure in internal/session

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

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

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


Design molecule parameterization

Enable protos to accept parameters for customization.

## Use Cases

1. rig-spinup needs rig name: `gt sling rig-spinup --param rig=newproject`
2. agent-restart needs agent: `gt sling agent-restart --param agent=gastown/witness`
3. code-review needs scope: `gt sling code-review --param scope=src/auth/`

## Proposed Syntax

### In Proto

```markdown
## Step: create-rig-structure
mkdir -p ~/gt/${rig}/refinery ~/gt/${rig}/witness
```

### In Sling

```bash
gt sling rig-spinup mayor/ --param rig=newproject --wisp
```

### In Bonded Molecule

Interpolation happens at bond time. Step descriptions have concrete values.

## Implementation

1. Proto declares params in frontmatter: `params: [rig]`
2. gt sling validates required params provided
3. bd mol bond receives params, interpolates descriptions
4. Bonded molecule has concrete step text

## Edge Cases

- Missing required param → error
- Unused param → warning
- Param in step title → interpolate there too


implement

Implement the solution for gt-qwyu. 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


Witness session startup (gt witness start)

Implement gt witness start <rig>

Should:
1. Verify rig exists and has witness/ directory
2. Check for existing witness session (don't double-start)
3. Create tmux session: gt-<rig>-witness
4. Start Claude Code with --dangerously-skip-permissions
5. Send gt prime to load context
6. Send startup prompt

Similar pattern to refinery startup in internal/refinery/manager.go


gt mq submit: creates task type instead of merge-request type

## Problem

`gt mq submit` creates an issue with `type: task` but should be `type: merge-request`.

## Evidence

```
$ bd show gt-n508
gt-n508: Merge: gt-70b3
Status: open
Priority: P1
Type: task      <-- WRONG, should be merge-request
...
Description:
type: merge-request   <-- Correct type is in description, not in actual type field
```

## Impact

`gt mq list` shows empty queue because it queries for `type: merge-request`

## Fix

`gt mq submit` should set `--type merge-request` when creating the bead.


CLI: witness commands (start, stop, status)

Witness daemon CLI commands.

## Commands

### gt witness start
Start the witness daemon for a rig.
```
gt witness start <rig> [--interval <seconds>]
```
- Starts background daemon process
- Default heartbeat interval: 30s
- Logs to <rig>/witness/witness.log

### gt witness stop
Stop the witness daemon.
```
gt witness stop <rig>
```
- Graceful shutdown
- Completes current heartbeat cycle

### gt witness status
Show witness status.
```
gt witness status <rig> [--json]
```
Output:
- Running/stopped
- Last heartbeat time
- Polecats being monitored
- Recent nudges/escalations

### gt witness logs
View witness logs.
```
gt witness logs <rig> [--follow] [--lines <n>]
```
- --follow: Continuous output (like tail -f)
- --lines: Number of lines (default 50)

## Daemon Management

Witness runs as background process:
- PID stored in <rig>/witness/witness.pid
- Uses nohup for persistence
- Logs structured JSON events

## Implementation

```go
var witnessCmd = &cobra.Command{Use: "witness"}
witnessCmd.AddCommand(startCmd, stopCmd, statusCmd, logsCmd)
```

Start launches daemon via exec, status reads PID file and pings process.


Plugin system: subprocess JSON protocol

Language-agnostic plugin system via subprocess JSON protocol.

## Concept

Allow extending Gas Town with external scripts/programs. Plugins communicate via stdin/stdout JSON.

## Protocol

Request (gt → plugin):
```json
{"method": "check", "params": {"rig": "wyvern", "polecat": "Toast"}}
```

Response (plugin → gt):
```json
{"result": {...}, "error": null}
```

Error response:
```json
{"result": null, "error": {"code": 1, "message": "..."}}
```

## Interface

```go
type Plugin struct {
    Name    string
    Path    string  // executable path
    Methods []string
}

type PluginManager struct {
    plugins map[string]*Plugin
}

func NewPluginManager() *PluginManager
func (pm *PluginManager) Register(plugin *Plugin) error
func (pm *PluginManager) Call(plugin, method string, params any) (any, error)
func (pm *PluginManager) Discover(dir string) error  // auto-discover plugins
```

## Plugin Discovery

Look in:
1. `<town>/plugins/`
2. `~/.config/gastown/plugins/`
3. System path with `gt-plugin-*` prefix

## Built-in Hooks

Plugins can register for events:
- `polecat.started` - Polecat session started
- `polecat.done` - Polecat signals done
- `merge.requested` - MR submitted
- `merge.completed` - MR merged

## Use Cases

- Custom health checks
- Integration with external systems (Slack, etc.)
- Custom merge policies
- Metrics collection

## Future

Consider MCP integration for richer plugin capabilities.


Test message

Test body