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

## Problem

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

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

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

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

## The Right Architecture

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

## Scope

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

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

3. Update gt witness commands to use Claude session model

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

## Related

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


request-shutdown

Send shutdown request to Witness.
Wait for termination.

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

Depends: generate-summary


Add neighbor-check steps to all patrol molecules

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

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

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

This creates distributed monitoring - no single point of failure.


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.


Overhaul gt mol to match bd mol chemistry interface

## The Sling: Unified Work Dispatch

This issue tracks the overhaul of `gt molecule` to align with chemistry metaphor and introduce the **Universal Gas Town Propulsion Principle**.

### The Propulsion Principle

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

This is the one rule that drives all Gas Town agents.

### The Sling Operation

`gt sling <thing> <target> [options]` - unified command for spawn + assign + pin.

See: `gastown/mayor/rig/docs/sling-design.md`

### Implementation Tasks

| Issue | Title | Priority |
|-------|-------|----------|
| gt-4ev4 | Implement gt sling command | P1 |
| gt-uym5 | Implement gt mol status command | P1 |
| gt-i4kq | Update templates for Propulsion Principle | P1 |
| gt-7hor | Document the Propulsion Principle | P2 |

### Command Changes

| Old | New |
|-----|-----|
| `gt molecule instantiate` | `gt sling` |
| `gt molecule attach` | `gt sling --force` |
| `gt molecule detach` | `gt mol burn` |
| `gt molecule progress` | `gt mol status` |
| `gt molecule list` | `gt mol catalog` |
| `gt spawn --molecule` | `gt sling` |

### Acceptance Criteria

- [ ] `gt sling` works for protos, issues, and epics
- [ ] `gt mol status` shows hook state
- [ ] Templates updated for propulsion principle
- [ ] Old commands deprecated with warnings
- [ ] Documentation complete


Merge: gt-3x1

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


Merge: gt-ldk8

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


Self-test

Testing gt mail works


Remove pinned field workaround after beads fix

## Summary

Once bd-phtv is fixed in beads, we can remove the workaround documentation and potentially simplify the pinToHook() implementation.

## Current Workaround

The handoff bead attachment mechanism (AttachMolecule) is used as the primary work assignment mechanism instead of the pinned field. This works correctly but adds complexity.

## Changes After Beads Fix

1. Remove the NOTE comment in internal/beads/beads.go:Pin() explaining the bug
2. Consider simplifying pinToHook() if the pinned field becomes reliable
3. Update gt-o3is to reference the fix

## Blocked By

This issue is blocked by external:beads:pinned-field-fix (bd-phtv).
When that capability is shipped, this issue becomes ready.

## Related

- gt-o3is: Original investigation that found this bug
- bd-phtv: The beads fix (in ~/gt/beads)

BLOCKED: Can't add external:beads:pinned-field-fix dependency due to bd-ucgz (migration invariants bug). Once that's fixed, add: bd dep add gt-hj9e external:beads:pinned-field-fix


Digest: mol-deacon-patrol

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


Proto marketplace: shareable molecule templates

Enable sharing protos between Gas Town installations.

## Vision

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

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

## Registry Design

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

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

## Proto Package Format

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

## Commands

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

## For Now

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


Polecat template: simplify completion section to just 'gt done'

Completion section lists multiple options (gt done, gt handoff, bd sync). Should just say 'gt done' with succinct guidance on when bd sync is needed. Remove the alternatives that cause confusion.


gt spawn: Notify Deacon and Witness on polecat start

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

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

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

Part of the village self-monitoring architecture.


Merge: gt-svi.1

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


Split PGT/GGT harness or migrate to GGT-only

Current ~/ai harness is shared by PGT and GGT with confusing overlap. Options:
1. Keep separate (document the coexistence)
2. Migrate fully to GGT structure
3. Create separate harnesses

This affects the beads redirect, Mayor home location, and rig structure.


Draft mol-ready-work protomolecule definition

Draft the actual protomolecule definition in markdown format.

## Molecule Structure

```markdown
## Molecule: ready-work
Autonomous backlog processing patrol for crew workers.

Phase: vapor (wisp) - ephemeral patrol cycles
Squash: after each work item or context threshold

## Step: orient
Load context and check for interrupts:
- Read mail for overseer instructions
- Check for predecessor handoff
- Load current context state

## Step: scan-backlogs
Survey all backlogs in priority order:
1. gh pr list --state open
2. gh issue list --state open --label untriaged (or no label)
3. bd ready
4. gh issue list --state open --label triaged

Capture counts and candidates.

Needs: orient

## Step: select-work
Apply ROI heuristic to select best work item:
- Estimate size (tokens needed)
- Check remaining context capacity
- Weight by impact (priority, type)
- Select highest ROI achievable item
- If empty: exit patrol

Needs: scan-backlogs

## Step: execute-work
Work the selected item:
- For PRs: review, request changes, or merge
- For untriaged: triage and label
- For beads: implement and close
- For triaged GH: implement fix

Commit, push, close/update as appropriate.

Needs: select-work

## Step: check-context
Assess context state:
- Estimate remaining capacity
- If < 20%: goto handoff
- If ok: loop to scan-backlogs

Needs: execute-work

## Step: handoff
Prepare for session transition:
- Summarize work completed this cycle
- Note any in-progress items
- Send handoff mail to self
- Squash wisp to digest
- Exit for fresh session

Needs: check-context
```

## Variables

- `backlog_priority`: Override backlog scan order
- `context_threshold`: Percentage at which to handoff (default: 20)
- `max_items`: Maximum items to process per session

## Notes

- This is a vapor-phase molecule (wisp)
- Each work item should squash to a digest
- The patrol itself squashes at handoff


Proto debugging and inspection tools

Tools for understanding cooked protos:
- bd cook --dry-run (already planned)
- Step-through cooking: see each compose rule applied
- Diff between proto versions
- Provenance tracing: which formula/rule produced this step?
- Visualization of step graph (ASCII or graphviz)

Deferred: post-launch polish


Remove shell respawn loops from witness and deacon

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

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

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

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

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

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


Deacon patrol banners: visual feedback on atom transitions

Print large ASCII banners when transitioning between patrol atoms.

## Problem

When the deacon progresses through patrol atoms (steps), there is no visual feedback.
The operator cannot easily see what the deacon is doing without reading the full output.

## Desired Behavior

Print banners on step start and completion:

  INBOX-CHECK - Checking for lifecycle requests, escalations, timers
  INBOX-CHECK COMPLETE - Processed 3 messages, 0 lifecycle requests

## Benefits

1. Scanability: Operator can glance at tmux and see what is happening
2. Progress tracking: Easy to see where in the patrol loop we are
3. Debugging: Clear demarcation between steps for troubleshooting

## Implementation Options

1. In deacon CLAUDE.md: Instruct agent to print banners
2. gt patrol step start/end: Commands that print banners
3. bd mol step hooks: Automatically on step transitions

## Related

- gt-id36: Deacon Kernel
- gt-rana: Patrol System


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

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

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


Test Polecat Arm

Test child for bonding pattern


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


Digest: mol-deacon-patrol

Patrol OK: 8 polecats, 4 witness/refineries up


Design future federation model

Document how remote/federated refinery would work in the future.

## Options to document
1. Git bundles - portable patches, no branches on origin
2. Dedicated integration branch pattern (integration/*)
3. Hybrid - local for same-machine, bundles for remote

## Deliverable
Design doc in docs/federation-refinery.md or similar.
Not implementing now - just capturing the design for when needed.


Test infrastructure: fixtures, mocks, integration tests

Test infrastructure for Gas Town.

## Test Categories

### Unit Tests
- Config parsing
- Mail operations
- Merge queue operations
- Template rendering

### Integration Tests
- Git operations (uses real git in temp dirs)
- Full workflows (spawn → work → merge)
- CLI command tests

## Fixtures

```go
package testutil

// Creates temp town with minimal structure
func NewTestTown(t *testing.T) *TestTown

// Creates temp rig with git repo
func NewTestRig(t *testing.T, town *TestTown, name string) *TestRig

// Creates test polecat
func NewTestPolecat(t *testing.T, rig *TestRig, name string) *TestPolecat
```

## Mocks

```go
// Mock tmux for session tests (avoid actual tmux)
type MockTmux struct {
    Sessions map[string][]string  // captured send-keys
}

func (m *MockTmux) NewSession(name, dir string) error
func (m *MockTmux) SendKeys(session, keys string) error
func (m *MockTmux) CapturePane(session string, lines int) (string, error)
```

## Test Helpers

```go
// Run test in temp directory
func InTempDir(t *testing.T, fn func(dir string))

// Initialize git repo for testing
func InitGitRepo(t *testing.T, dir string)

// Assert file exists with content
func AssertFileContains(t *testing.T, path, substr string)

// Assert JSON file has field
func AssertJSONField(t *testing.T, path, field string, expected any)
```

## CI Integration

- go test ./... runs all tests
- Integration tests skip with -short flag
- Coverage report generation

## Test Data

Embedded test fixtures:
```go
//go:embed testdata/*
var testdataFS embed.FS
```


Design: Swarm shutdown and worker cleanup

Design for graceful swarm shutdown, worker cleanup, and session cycling.

## Key Decisions

1. Pre-kill verification uses model intelligence (not framework rules)
2. Witness can request restart when context filling (mail self, exit)
3. Mayor NOT involved in per-worker cleanup (Witness responsibility)
4. Clear responsibility boundaries between Mayor/Witness/Polecat

## Subtasks (implementation)

- gt-sd6: Polecat decommission checklist prompting
- gt-f8v: Witness pre-kill verification protocol
- gt-eu9: Witness session cycling and handoff
- gt-gl2: Mayor vs Witness cleanup responsibilities

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


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

GGT is missing most polecat management commands that PGT has.

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

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

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


Merge: gt-5af.5

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


Design: Failure modes and recovery

Document failure modes and recovery strategies for Gas Town operations.

## Critical Failure Modes

### 1. Agent Crash Mid-Operation

**Scenario**: Polecat crashes while committing, Witness crashes while verifying

**Detection**:
- Session suddenly gone (tmux check fails)
- State shows 'working' but no session
- Heartbeat stops (for Witness)

**Recovery**:
- Doctor detects via ZombieSessionCheck
- Capture any recoverable state
- Reset agent state to 'idle'
- For Witness: auto-restart via supervisor or manual gt witness start

### 2. Git State Corruption

**Scenario**: Merge conflict, failed rebase, detached HEAD

**Detection**:
- Git commands fail
- Dirty state that won't commit
- Branch diverged from origin

**Recovery**:
- gt doctor reports git health issues
- Manual intervention recommended
- Severe cases: remove clone, re-clone

### 3. Beads Sync Conflict

**Scenario**: Two polecats modify same issue

**Detection**:
- bd sync fails with conflict
- Beads tombstone mechanism handles most cases

**Recovery**:
- Beads has last-write-wins semantics
- bd sync --force in extreme cases
- Issues may need manual dedup

### 4. Tmux Failure

**Scenario**: Tmux server crashes, socket issues

**Detection**:
- All sessions inaccessible
- "no server running" errors

**Recovery**:
- Kill any orphan processes
- tmux kill-server && tmux start-server
- All agent states reset to idle
- Re-spawn active work

### 5. Claude API Issues

**Scenario**: Rate limits, outages, context limits

**Detection**:
- Sessions hang or produce errors
- Repeated failure patterns

**Recovery**:
- Exponential backoff (handled by Claude Code)
- For context limits: session cycling (mail-to-self)
- For outages: wait and retry

### 6. Disk Full

**Scenario**: Clones, logs, or beads fill disk

**Detection**:
- Write operations fail
- git/bd commands error

**Recovery**:
- Clean up logs: rm ~/.gastown/logs/*
- Remove old polecat clones
- gt doctor --fix can clean some cruft

### 7. Network Failure

**Scenario**: Can't reach GitHub, API servers

**Detection**:
- git fetch/push fails
- Claude sessions hang

**Recovery**:
- Work continues locally
- Queue pushes for later
- Sync when connectivity restored

## Recovery Principles

1. **Fail safe**: Prefer stopping over corrupting
2. **State is recoverable**: Git and beads have recovery mechanisms
3. **Doctor heals**: gt doctor --fix handles common issues
4. **Emergency stop**: gt stop --all as last resort
5. **Human escalation**: Some failures need Overseer intervention

## Implementation

- Document each failure mode in architecture.md
- Ensure doctor checks cover detection
- Add recovery hints to error messages
- Log all failures for debugging


Prompt templates: role contexts, nudge messages

Prompt templates for role contexts and messages.

## Template Types

### Role CLAUDE.md Templates

For gt prime and CLAUDE.md generation:
- Mayor template
- Witness template
- Refinery template
- Polecat template

### Message Templates

For notifications and nudges:
- Spawn assignment
- Witness nudge
- Escalation to Mayor
- Session handoff

## Implementation

```go
//go:embed templates/*.md.tmpl
var templateFS embed.FS

type Templates struct {
    fs embed.FS
}

func NewTemplates() *Templates
func (t *Templates) RenderRole(role string, data RoleData) (string, error)
func (t *Templates) RenderMessage(name string, data any) (string, error)
```

## Template Data

```go
type RoleData struct {
    Role      string
    RigName   string
    TownRoot  string
    Polecats  []string
    Commands  []CommandHelp
}

type SpawnData struct {
    Issue       string
    Title       string
    Priority    int
    Description string
}

type NudgeData struct {
    Polecat    string
    Reason     string
    NudgeCount int
    MaxNudges  int
}
```

## Template Location

Embedded in binary via go:embed:
```
internal/templates/
├── roles/
│   ├── mayor.md.tmpl
│   ├── witness.md.tmpl
│   ├── refinery.md.tmpl
│   └── polecat.md.tmpl
└── messages/
    ├── spawn.md.tmpl
    ├── nudge.md.tmpl
    └── escalation.md.tmpl
```

## Usage

gt prime uses role templates.
gt spawn uses spawn template.
Witness uses nudge/escalation templates.


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.


Activity feed from wisp state: gt patrol status

Enable mayor and gt tool to quickly see what patrol agents are doing.

## Problem

The mayor and gt tool cannot quickly see what the deacon (or other patrol agents) are doing.
Need a way to extract an activity feed from the current wisp state.

## Desired Commands

- gt patrol status: Show current patrol state (step, timing, cycle count)
- gt patrol history: Show recent patrol cycles (from digests)
- gt patrol feed: Live tail of patrol activity

## Data Sources

- .beads-wisp/issues.jsonl: Current wisp with step progress
- .beads/issues.jsonl: Digests from squashed patrols
- heartbeat.json: Last activity timestamp

## Use Cases

1. Mayor checking deacon: Is the deacon doing anything?
2. Debugging hangs: What step is it stuck on?
3. Operator monitoring: Dashboard of patrol health
4. Summaries for handoffs: Auto-generate patrol digest

## Related

- gt-id36: Deacon Kernel
- gt-3x0z: Wisp Molecule Integration


Document bd mol bond/squash/burn CLI

Create CLI reference documentation for molecule commands:

## bd mol bond

Instantiate a proto into a runnable molecule.

```bash
bd mol bond <proto-id> [--wisp] [--assignee=<addr>]
```

- Default: creates a Mol (durable, in main beads)
- --wisp: creates a Wisp (ephemeral, in .beads-ephemeral/)
- --assignee: who will execute this molecule

## bd mol squash

Complete a molecule and generate digest.

```bash
bd mol squash <mol-id> --summary='...'
```

- For Mol: creates digest in git history
- For Wisp: evaporates (no permanent record)
- --summary: required summary of what was accomplished

## bd mol burn

Abandon a molecule without completing.

```bash
bd mol burn <mol-id> [--reason='...']
```

- Discards molecule state
- No digest created
- Use when molecule is no longer needed


Deacon patrol molecules stored in wrong beads location

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


Test Task 2: Add comment to version.go


Recreate beads rigs with fresh clones

## Problem

Beads rigs have schema mismatches (missing thread_id column, etc.) from development iteration.

## Tasks

1. Shut down any active polecats
2. Delete existing beads rigs: mayor/rig, refinery/rig, witness/rig, crew/*
3. Re-clone from beads repo
4. Run bd init in each new clone

## Rigs to recreate

- /Users/stevey/gt/beads/mayor/rig
- /Users/stevey/gt/beads/refinery/rig
- /Users/stevey/gt/beads/crew/* (if any)

## Source

Clone from beads repo (need to confirm remote URL)


Shutdown request handler

Handle polecat shutdown requests:

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

Depends on fixing gt-dsfi (handoff deadlock).


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

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


Test message

Testing GGT mail integration


Molecule execution support for polecats and crew

Enable agents to run bonded molecules through the full lifecycle.

## The Model
1. BOND - bd mol bond <template> --assignee <identity>
   Creates concrete issues, assigns root to agent

2. DISCOVER - Agent finds assigned molecules via bd ready
   DAG structure shows unblocked steps

3. WORK - Agent works through DAG, closing steps as done
   Can delegate children to lower-tier agents (haiku)

4. SURVIVE - Agent dies → beads persist
   Any agent resumes from DAG state

5. SUPERVISE - Witness monitors for stalled molecules
   Nudges owner or reassigns if dead

## Questions to Resolve
- Seed node terminology: seed vs root vs pole vs nucleus
- Assignee inheritance: single owner vs delegation model
- Stall detection: heartbeat vs activity timeout vs session monitoring

## Implementation
- Polecat startup: check for assigned molecules
- Polecat work loop: follow molecule DAG
- Witness: monitor molecule progress, detect stalls
- Mayor: can assign molecules, handle escalations

## Depends On
- beads: bd mol bond command (bd-usro in beads repo)


Digest: mol-deacon-patrol

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


Add human escalation configuration

Add overseer contact config to mayor/town.json. Deacon uses this for escalation when it cannot resolve issues. Support email and/or other notification methods.


Code review: handoff.go changes (gt-yt6g, gt-tocb)

Review ~80 lines of Go changes to internal/cmd/handoff.go:

## Commits to review
- 1414081: Standardize session end with gt handoff (gt-yt6g)
  - Detect polecats via GT_POLECAT env var
  - Call gt done instead of respawning for polecats
  - +31/-11 lines

- 9c85b83: Support full session paths in gt handoff (gt-tocb)
  - resolveRoleToSession accepts <rig>/crew/<name>, <rig>/witness, <rig>/refinery
  - +46/-3 lines

## Review focus
- Error handling in path resolution
- Edge cases in polecat detection
- Test coverage needed?


Automatic spawn for ready work

Auto-spawn polecats for ready work:

When Witness has capacity (active_workers < max_workers):
1. Query bd ready for unblocked issues
2. Filter to rig-appropriate work (by prefix or epic)
3. For each ready issue up to capacity:
   - gt spawn --issue <id>
   - Track that we spawned for this issue

Configuration (in rig config.json):
- max_workers: 4 (default)
- spawn_delay: 5s between spawns
- auto_spawn: true/false

This enables 'fire and forget' swarming:
- Mayor creates epic with children
- Mayor tells Witness to work epic
- Witness spawns polecats automatically
- Witness cleans up as they complete


CLI: plugin commands (list, status)

Add gt plugins <rig> to list plugins and gt plugin status <name> to check plugin state. Simple directory scan of <rig>/plugins/.


Build activity stream component

Bubbletea component showing scrollable activity stream for a selected worker. Shows mutation events with timestamps, symbols, and issue titles. Displayed when user expands/selects a worker.


bd formula list/show commands

Implement formula management commands:

  bd formula list
  # Lists formulas from all search paths

  bd formula show rule-of-five
  # Shows formula details, steps, compose rules

Search paths (in order):
1. .beads/formulas/ (project)
2. ~/gt/.beads/formulas/ (town)
3. ~/.beads/formulas/ (user)
4. Built-in formulas (embedded)


Digest: mol-deacon-patrol

Patrol OK: archived old handoff, all agents up, furiosa on gt-oiv0


Update docs to reflect molecule-first paradigm

Gas Town is fundamentally a molecule execution engine. Documentation should reflect this more clearly.

## Issues Found

### 1. gt spawn examples show molecule as optional
README.md line 116: `gt spawn --issue <id> # Start polecat on issue`
Should emphasize: polecats execute molecules, not just issues.

### 2. Architecture.md spawn examples inconsistent
Line 344 shows molecule: `gt spawn --issue gt-xyz --molecule mol-engineer-in-box`
Line 1434 shows without: `gt spawn --issue <id>`

### 3. Config vs molecule distinction not clear
outposts.yaml shows static policy - should note when molecules apply.

### 4. Operational molecules section is good but buried
Lines 430-566 cover operational molecules well. Should be more prominent.

## Updates Needed
- [ ] README: Update spawn examples to show molecule usage
- [ ] architecture.md: Ensure all spawn examples include molecules
- [ ] architecture.md: Add section on "when config vs molecule"
- [ ] architecture.md: Move operational molecules higher in document
- [ ] Add principle: "If it requires cognition, it's a molecule"
- [ ] federation-design.md: Note that policy can escalate to mol-outpost-assign

## Key Message
Gas Town doesn't spawn workers on issues. It spawns workers on molecules.
The issue is just the seed data for the molecule execution.


HOP: Entity chain tracking for agents

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


Merge polecat/rictus: Add molecule phase lifecycle diagram

Branch: polecat/rictus

Adds molecule phase lifecycle diagram to architecture.md showing Proto → Mol/Wisp → Digest state transitions with the 'states of matter' metaphor. Also documents when to use Mol (durable) vs Wisp (ephemeral).

Closes: gt-c6zs


Port Gas Town to Go

Complete rewrite of Gas Town in Go for improved performance and single-binary distribution.

## Goals
- Single installable binary (gt)
- All Python functionality ported
- Federation support built-in
- Improved performance

## Phases
1. Core infrastructure (config, workspace, git wrapper)
2. Rig & polecat management
3. Session & tmux operations
4. Mail system
5. CLI commands
6. TUI (optional)


GGT Command Parity: Complete gt command coverage

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

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


Update lifecycle mail targets to deacon/

Update Mayor, Witness, and Crew handoff code to send lifecycle requests to deacon/ instead of daemon/. Update internal/cmd/handoff.go and related code.


Merge: gt-3x0z.3

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


Test issue 1 for displacement


Merge: gt-h6eq.1

branch: polecat/nux
target: main
source_issue: gt-h6eq.1
rig: gastown


Remove redundant gt prime SendKeys from crew commands

The crew commands (gt crew at, gt crew restart) still send 'gt prime' via SendKeys after session creation:
- internal/cmd/crew_at.go:97, 121
- internal/cmd/crew_lifecycle.go:202

This is now redundant because SessionStart hook handles priming automatically.

**Low priority** - these aren't causing bugs (just duplicate work), unlike the spawn race condition that was fixed. Can be cleaned up when convenient.


Auto-restart patrol agents after N loops

All patrol roles should auto-restart to keep context usage low. Role-specific heuristics:

**Deacon**:
- 20 patrol loops without major incident
- Immediate restart after ANY extraordinary action (lifecycle request, remediation, escalation)
- Rationale: Keep context short so there's headroom if something big comes up

**Witness**:
- Based on polecats processed (not loop count)
- Restart after processing N polecats (spawns, nudges, decommissions)
- Suggested N: 10-15 polecats

**Refinery**:
- Based on MRs processed (not loop count)
- Restart after processing N merge requests
- Suggested N: 5-10 MRs (merges are context-heavy)

Benefits:
- Keeps context fresh (better focus/performance)
- Reduces cost (quadratic increase vs conversation length)
- Preserves headroom for handling surprises
- Simple and predictable (no context estimation needed)

Each role tracks their metric in state file and hands off when threshold reached.


request-shutdown

Send shutdown request to Witness.
Wait for termination.

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

Depends: generate-summary


gt mq retry: retry a failed MR

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

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

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

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


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


Test

Body


gt polecat git-state command for pre-kill verification

Add git-state subcommand to gt polecat for Witness pre-kill verification.

## Usage
```bash
gt polecat git-state <rig>/<polecat>
```

## Output
```
Git State: gastown/furiosa

  Working Tree: clean | dirty
  Uncommitted:  0 files | N files (list)
  Unpushed:     0 commits | N commits ahead
  Stashes:      0 | N stashes

  Verdict: CLEAN (safe to kill) | DIRTY (needs cleanup)
```

## JSON output (--json flag)
```json
{
  "clean": true,
  "uncommitted_files": [],
  "unpushed_commits": 0,
  "stash_count": 0
}
```

## Used by
- Witness pre-kill verification (mol-witness-patrol)
- Manual cleanup checks

## Implementation
- Check git status in polecat worktree
- Check git log origin/main..HEAD
- Check git stash list


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


mol-ready-work: graceful GitHub/label handling

## Summary

mol-ready-work assumes:
- GitHub repo exists with gh CLI configured
- Labels 'untriaged' and 'triaged' exist

Should handle gracefully:
1. No GitHub repo (beads-only project) → skip GH backlogs
2. Missing labels → skip that backlog tier, don't error
3. gh CLI not authenticated → warn and skip GH backlogs

## Implementation
Add checks in scan-backlogs step:
```bash
# Check if gh is available and authenticated
if gh auth status &>/dev/null; then
  # scan GH backlogs
fi
```

## Parent
Part of gt-tnca (mol-ready-work epic)


Machine registry: Store and manage machine configs

Registry for managing remote machines in federation.

## Data Model

```go
type Machine struct {
    Name     string `json:"name"`
    Type     string `json:"type"`      // "local", "ssh", "gcp"
    Host     string `json:"host"`      // for ssh: user@host
    KeyPath  string `json:"key_path"`  // SSH key path
    TownPath string `json:"town_path"` // Path to town on remote
}
```

## Interface

```go
type MachineRegistry struct {
    path     string  // config/federation.json
    machines map[string]*Machine
}

func NewMachineRegistry(configPath string) *MachineRegistry
func (r *MachineRegistry) Get(name string) (*Machine, error)
func (r *MachineRegistry) Add(m *Machine) error
func (r *MachineRegistry) Remove(name string) error
func (r *MachineRegistry) List() []*Machine
func (r *MachineRegistry) Connection(name string) (Connection, error)
```

## Storage

federation.json in config/:
```json
{
  "version": 1,
  "machines": {
    "local": {"type": "local"},
    "gcp-vm-1": {
      "type": "ssh",
      "host": "user@10.0.0.1",
      "key_path": "~/.ssh/gcp_key",
      "town_path": "/home/user/ai"
    }
  }
}
```

## Connection Factory

```go
func (r *MachineRegistry) Connection(name string) (Connection, error) {
    m := r.machines[name]
    switch m.Type {
    case "local":
        return NewLocalConnection(), nil
    case "ssh":
        return NewSSHConnection(m.Host, m.KeyPath), nil
    }
}
```


Add gt crew rename command


detectSender() doesn't recognize crew workers

## Problem

`detectSender()` in mail.go only detects polecats, not crew workers.

## Current Code (line 445)

```go
// If in a rig's polecats directory, extract address
if strings.Contains(cwd, "/polecats/") {
    // extract rig/polecat
}

// Default to mayor
return "mayor/"
```

## Symptom

Emma (crew worker at `/Users/stevey/gt/beads/crew/emma`) runs:
- `gt mail inbox` → checks `mayor/` inbox (wrong!)
- Should check `beads/emma` or `beads/crew/emma`

## Fix

Add crew detection:
```go
// If in a rig's crew directory, extract address
if strings.Contains(cwd, "/crew/") {
    parts := strings.Split(cwd, "/crew/")
    if len(parts) >= 2 {
        rigPath := parts[0]
        crewName := strings.Split(parts[1], "/")[0]
        rigName := filepath.Base(rigPath)
        return fmt.Sprintf("%s/%s", rigName, crewName)
    }
}
```

## Also Check

- `gt prime` correctly detects role, so there may be another detection function that works
- Should unify detection logic


execute-actions

Send nudges, process shutdowns, escalate as decided.

Needs: decide-actions


Merge: gt-a95

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


Add hook-attachment-valid doctor check

Add gt doctor check to verify attached molecules exist and are not closed.

Check: hook-attachment-valid
Error if: Hook's attached_molecule field points to non-existent or closed issue
Fix suggestion: Clear attachment with gt mol detach


Rig management: discover, load, create rigs

Rig discovery, loading, and creation.

## Interface

```go
type Rig struct {
    Name      string
    Path      string
    GitURL    string
    Config    RigConfig
    Polecats  []string
    HasWitness bool
    HasRefinery bool
}

type RigManager struct {
    townRoot string
    config   *Config
    git      *Git
}

func NewRigManager(townRoot string, config *Config, git *Git) *RigManager

// Discovery
func (rm *RigManager) DiscoverRigs() ([]*Rig, error)
func (rm *RigManager) GetRig(name string) (*Rig, error)
func (rm *RigManager) RigExists(name string) bool

// Creation
func (rm *RigManager) AddRig(name, gitURL string) (*Rig, error)
func (rm *RigManager) RemoveRig(name string) error

// Rig state
func (rm *RigManager) LoadRigConfig(rig *Rig) error
func (rm *RigManager) SaveRigConfig(rig *Rig) error
```

## Discovery Logic

1. Read rigs.json from config/
2. For each registered rig, verify directory exists
3. Load rig-level config if present
4. Scan for polecats/ subdirectory
5. Check for witness/, refinery/ directories

## Rig Creation

1. Clone repo to town root
2. Add entry to rigs.json
3. Create agent directories (polecats/, witness/, refinery/, mayor/)
4. Update .git/info/exclude to ignore agent dirs
5. Initialize rig config

## Rig Structure

Per docs/architecture.md:
```
<rig>/
├── polecats/
├── refinery/rig/
├── witness/rig/
└── mayor/rig/
```


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

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

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

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

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

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


Remove unused style helper functions

internal/style/style.go defines RenderSuccess, RenderWarning, RenderError, and RenderInfo helper functions that are never used. Code uses style.Success.Render() directly instead. Either use the helpers consistently or remove them.


Track merge requests as beads (type=merge-request)

Currently MRs are tracked in .gastown/refinery.json. For HOP audit trail and entity CV tracking, merge requests should be Beads entries with type=merge-request. This enables:
- Full audit trail of what was merged, when, by whom
- Entity chain contributions (who validated what)
- Cross-rig visibility of merge activity

The refinery would create an MR bead when work enters the queue, update status as it progresses (open → in_progress → merged/rejected).

Part of Beads-as-data-plane vision from HOP.


More branches to process?

More branches to process?

If yes: Return to process-branch with next branch.
If no: Continue to generate-summary.

Track: branches processed, branches skipped (with reasons).

instantiated_from: mol-refinery-patrol
step: loop-check


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)


Overseer Crew: User-managed persistent workspaces

## Overview

Crew workers are the overseer's (human's) personal workspaces within a rig. Unlike polecats which are witness-managed and ephemeral, crew workers are:

- **Persistent**: Not auto-garbage-collected
- **User-managed**: Overseer controls lifecycle
- **Long-lived identities**: dave, emma, fred - recognizable names
- **Gas Town integrated**: Mail, handoff mechanics work
- **Tmux optional**: Can work in terminal directly

## Directory Structure

```
<rig>/
  polecats/       # Managed workers (witness controls)
  refinery/       # Merge queue processor
  witness/        # Pit boss
  crew/           # Overseer's personal workspaces
    dave/         # Full clone, persistent
    emma/         # Full clone, persistent
    fred/         # Full clone, persistent
```

## Key Differences from Polecats

- Location: crew/ instead of polecats/
- Lifecycle: User-managed, not witness-managed
- Auto-cleanup: Never (polecats auto-cleanup on swarm land)
- Issue assignment: Optional (polecats require it)
- Tmux: Optional (polecats require it)
- Mail & Handoff: Yes for both
- Identity: Persistent (polecats are ephemeral)

## CLI Commands

- gt crew add <name> [--rig <rig>] - Create crew workspace
- gt crew list [--rig <rig>] - List crew workspaces
- gt crew at <rig>/<name> - Attach to workspace (start session)
- gt crew attach <name> - Attach (infer rig from cwd)
- gt crew refresh <name> - Handoff + restart (context cycling)
- gt crew remove <name> [--force] - Remove workspace
- gt crew status [<name>] - Show workspace status

## Design Notes

- Crew workers use full git clones (not worktrees)
- Optional beads integration via BEADS_DIR
- Mail-to-self handoff works for context cycling
- No witness monitoring or nudging
- No automatic issue assignment required

## Background

Users often maintain separate repo clones for serial agent work. This is tedious to set up manually. Crew workspaces bring these into Gas Town's infrastructure while keeping user control.


Formula inheritance trees for organizational policies

Support organizational formula hierarchies where teams extend a company-base-formula. Each team can add required aspects (accessibility audit for frontend, SQL injection scan for backend). Enables policy enforcement across an organization.


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.


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

Polecat management CLI commands.

## Commands

### gt polecat list
List polecats in a rig.
```
gt polecat list <rig> [--json]
gt polecat list --all [--json]
```
Output:
- Name
- State (idle/active/working/done/stuck)
- Current issue (if any)
- Session status (running/stopped)

### gt polecat add
Add a new polecat to a rig.
```
gt polecat add <rig> <name>
```
- Creates polecat directory
- Clones rig repo
- Creates work branch
- Initializes state

### gt polecat remove
Remove a polecat from a rig.
```
gt polecat remove <rig>/<polecat> [--force]
```
- Fails if session running
- Warns if uncommitted changes
- --force bypasses checks

### gt polecat wake
Mark polecat as active (ready for work).
```
gt polecat wake <rig>/<polecat>
```
Transitions: idle → active

### gt polecat sleep
Mark polecat as idle (not available).
```
gt polecat sleep <rig>/<polecat>
```
Transitions: active → idle
Fails if session running (stop first).

## Address Format

`<rig>/<polecat>` for operations on specific polecat.
`<rig>` for list command.

## Implementation

```go
var polecatCmd = &cobra.Command{Use: "polecat"}
polecatCmd.AddCommand(listCmd, addCmd, removeCmd, wakeCmd, sleepCmd)
```


Implement/document gt sling mechanism

Investigate and implement the gt sling command for attaching molecules to crew workers. Check if gt sling exists, design the flow (mail-based vs direct pin vs wisp spawn), implement in gastown CLI, integrate with bd mol/wisp/pin commands.


Digest: mol-deacon-patrol

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


Rename engineer-in-box to shiny across all docs

Systematic rename of mol-engineer-in-box to shiny throughout docs: molecular-chemistry.md, molecules.md, architecture.md, etc. The shiny name is now canonical per the Breaking Bad × Mad Max naming.


Witness should verify polecat submitted before stopping session

## Problem

Witness stopped dementus's session before it could call `gt done`, losing the MR submission. I had to manually push and submit the branch.

## Root Cause

Witness cleanup is triggered by nudge/manual check rather than by receiving POLECAT_DONE message. When Witness cleans up based on issue status (closed), it doesn't wait for the polecat to complete its shutdown sequence.

## Expected Behavior

Witness should only stop a polecat session after:
1. Receiving POLECAT_DONE message from that polecat, OR
2. Timeout waiting for POLECAT_DONE after issue is closed

## Current Behavior

Witness stops sessions immediately when asked to check for completions, even if polecat hasn't called `gt done` yet.

## Fix

In mol-witness-patrol inbox-check step:
- Only clean up polecats that have sent POLECAT_DONE
- For polecats with closed issues but no DONE message, nudge them to complete
- Add timeout before force-killing


gt crew at/attach: Start session in crew workspace

Implement 'gt crew at <rig>/<name>' and 'gt crew attach <name>' commands:
- Start tmux session (optional - could just print cd instructions)
- Launch claude code in the workspace
- Deliver any pending mail
- Support --no-tmux to just print directory path
- 'attach' infers rig from cwd


Refinery patrol: Add sibling-check step

Refinery should check on Witness health as part of patrol (village sibling watch).

## Implementation

1. Add `sibling-check` step to mol-refinery-patrol (early in cycle)
2. Use `gt peek <rig>/witness 20` to check Witness output
3. Look for signs of health:
   - Recent activity (tool calls, log messages)
   - No error stack traces
   - Responsive to pings
4. If Witness seems stuck:
   - Send status request mail
   - Note for potential escalation
   - Don't block Refinery work

## Acceptance
- Refinery checks Witness each patrol cycle
- Anomalies logged
- Non-blocking (Refinery continues even if Witness is down)


Design Deacon molecule health-check step

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

**New molecule step: health-scan**

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

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

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


Polecat wisp architecture: Proto → Wisp → Mol pattern

Design the three-layer architecture for polecat lifecycle:

## The Insight

Polecats should run a ONE-SHOT WISP (not looping like patrols):

**Step 1: Onboard**
- Read full polecat protocol (polecat.md template)
- Learn Gas Town operation, exit strategies, molecule protocol
- This is the 'how to be a polecat' education

**Step 2: Execute Mol**
- Run the assigned molecule (the actual work item)
- Could span multiple sessions via session continuity
- The mol is pure work content (epic, issue, feature)

**Step 3: Cleanup**
- Run final step of the wisp
- Self-delete / request shutdown

## Three Layers

- **Proto**: polecat.md template (instructions for being a polecat)
- **Wisp**: One-shot harness instantiated from proto (wraps the mol)
- **Mol**: The work item (issue/epic being processed)

## Why This Matters

1. **Separation of concerns**: Protocol (how) vs Work (what)
2. **Reusability**: Same wisp harness wraps any mol
3. **Extensibility**: Plugin points for custom behavior
4. **Session continuity**: Wisp handles multi-session, not the mol
5. **Blurred control/data planes**: Intentional in Gas Town

## Design Questions

1. How does proto (polecat.md) become a wisp instance?
2. What are the plugin/extension points?
3. Should all 'engineer in a box' mols use proto → wisp → mol?
4. How does this relate to refinery/deacon patterns?


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


gt spawn: polecats report success but no work actually happens

## Problem

gt spawn polecats have multiple silent failure modes:

### Failure Mode 1: No gt prime
- Claude starts at prompt and waits for input
- SessionStart hook doesn't auto-run 'gt prime'
- Without gt prime, polecats don't pick up work

### Failure Mode 2: No git push (CRITICAL)
- Polecat commits code locally
- Polecat closes the beads issue
- Polecat sends POLECAT_DONE
- **But code is never pushed to remote branch**
- When worktree is cleaned up, commits are lost forever
- Issue appears closed but no code exists

## Evidence

testcat on bd-d28c:
- Reported 'Work Complete' with commits 7d3447b9, cd87e541
- Closed bd-d28c
- Submitted MR bd-yx22
- But: `grep -r 'TestCreateTombstone' cmd/bd/*.go` returns nothing
- No polecat/testcat branch on remote

## Required Fixes

1. Polecats MUST push their branch before closing issues
2. Witness MUST verify branch exists on remote before cleanup
3. gt spawn should auto-nudge 'gt prime'
4. Consider: Polecat handoff should fail if unpushed commits exist

## Verification Protocol for Witness

Before accepting POLECAT_DONE:
```bash
# 1. Verify branch pushed
git branch -r | grep polecat/<name>

# 2. Verify code exists
grep -r '<expected_function>' path/to/files

# 3. Only then cleanup
```


Create PolecatArmMolecule() for per-polecat inspection

Add PolecatArmMolecule() to builtin_molecules.go.

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

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

This proto is bonded dynamically by survey-workers step.


Phase 2.3: Polecat CLAUDE.md molecule workflow protocol

Update polecat prompting for molecule-based work.

## CLAUDE.md Updates

Add section on molecule workflow:

```markdown
## Molecule Workflow

When assigned a molecule (check gt prime output):

1. Follow molecule steps in order
2. Mark steps complete: bd mol step complete <step-id>
3. Before signaling done:
   a. Generate summary of work performed
   b. Run: bd squash <molecule-root> --summary "<your summary>"
4. Then signal done as normal

### Summary Guidelines

Your summary should include:
- What was the task?
- What did you do?
- What was the outcome?
- Any issues or follow-ups?

Keep it to 2-4 sentences. This becomes the permanent record.
```


Human escalation: notify overseer when self-heal fails

Lightweight escalation extracted from Deacon epic (gt-5af).

**Implementation**: Config in town.json or similar:
```yaml
escalation:
  contact: steve@example.com  # or slack webhook
  triggers:
    - daemon_cant_restart
    - session_missing_5min
```

**Trigger points**:
- Go daemon can't restart a session after N attempts
- Agent detects it's stuck and can't recover
- Witness can't reach polecat

**Mechanism**:
- Simple: `gt mail send --human` already exists
- Enhanced: email/slack via external script

**Weight**: Small config + one code path in daemon
**Value**: High for unattended operation - human gets notified instead of silent failure


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{},
}
```


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


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.


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


Phase 5.2: Ephemeral error handling and recovery

Handle edge cases in ephemeral molecule lifecycle.

## Scenarios

### Agent dies mid-molecule
- Ephemeral state persists
- Witness detects stall (no heartbeat)
- Options:
  a. Nudge agent to resume
  b. Reassign to new agent
  c. Escalate to Mayor

### Squash fails
- Retry with exponential backoff
- If persistent failure, escalate
- Don't lose the ephemeral state until squash succeeds

### Orphaned molecules
- Molecule started, never completed
- gt doctor detects (>24h old with no activity)
- Options:
  a. Manual review
  b. Auto-abandon with 'abandoned' digest
  c. Reassign

### Ephemeral repo corruption
- Re-init from scratch
- Active molecules are lost
- Main beads is source of truth for assigned work

## Implementation

Add error handling to:
- bd mol bond (handle init failures)
- bd squash (retry logic)
- gt doctor (recovery suggestions)


Aspects: AOP cross-cutting concerns

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

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


max Handoff

attached_molecule: gt-g2p7
attached_at: 2025-12-24T00:05:39Z


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.


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


Merge queue: per-rig queue management

Per-rig merge queue for coordinating polecat work.

## Concept

When polecats complete work, they submit to the merge queue. The Refinery processes the queue, merging work to main in order.

## Data Model

```go
type MergeRequest struct {
    ID        string    `json:"id"`
    Polecat   string    `json:"polecat"`
    Branch    string    `json:"branch"`
    Issue     string    `json:"issue,omitempty"`
    Status    MRStatus  `json:"status"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

type MRStatus string
const (
    MRPending   MRStatus = "pending"
    MRReviewing MRStatus = "reviewing"
    MRMerged    MRStatus = "merged"
    MRRejected  MRStatus = "rejected"
)
```

## Interface

```go
type MergeQueue struct {
    rig  *Rig
    path string  // <rig>/refinery/queue.jsonl
}

func NewMergeQueue(rig *Rig) *MergeQueue

// Queue operations
func (mq *MergeQueue) Submit(polecat, branch string, issue string) (*MergeRequest, error)
func (mq *MergeQueue) List() ([]*MergeRequest, error)
func (mq *MergeQueue) Next() (*MergeRequest, error)  // oldest pending
func (mq *MergeQueue) Get(id string) (*MergeRequest, error)

// Status updates
func (mq *MergeQueue) SetStatus(id string, status MRStatus) error
func (mq *MergeQueue) MarkMerged(id string) error
func (mq *MergeQueue) MarkRejected(id, reason string) error
```

## Queue Storage

JSONL file at `<rig>/refinery/queue.jsonl`. FIFO ordering.

## Git Coordination

Refinery processes queue:
1. Fetch polecat branch
2. Attempt merge to main
3. Run tests (if configured)
4. Push to origin
5. Update queue status

## Conflict Handling

If merge fails:
- Mark MR as rejected
- Notify polecat to rebase


gt mq reject: manual MR rejection

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

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

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

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


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


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


orphan-check

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


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 spawn: pasted work assignment needs manual Enter to start

## Problem

After `gt spawn` pastes the work assignment into Claude, the session waits for Enter.

## Current Behavior

1. `gt spawn gastown/Rictus --issue gt-xxx`
2. Session starts, work is pasted
3. Claude shows 'Pasted text #1 +53 lines' but doesn't start
4. Must manually send Enter or attach and press Enter

## Expected

The spawn should send Enter after pasting to kick off the work.

## Related

Same debounce issue as tmux notifications (gt-vnp9).


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.


Human escalation path design

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


mol-theme-generate: Custom name pool generation via cognition

Currently polecat name themes are hardcoded in namepool.go. Simple theme selection is fine as static config, but custom name generation should be a molecule.

Examples requiring cognition:
- "Generate 50 polecat names in the style of [book/movie/game]"
- "Create names that match the project's domain (medical, financial, etc.)"
- "Extend the mad-max theme with 20 more obscure characters"

## Molecule: theme-generate
Generate custom polecat names for a rig.

## Step: analyze-request
Understand the naming request:
- Theme style or source material
- Number of names needed
- Any constraints (length, format)

## Step: generate-candidates
Generate candidate names matching the style.
Aim for 2x the requested count.

## Step: validate-names
Filter candidates:
- No duplicates with existing themes
- Appropriate length (3-15 chars)
- No problematic terms

## Step: create-theme
Write the custom theme to rig config or beads.
Register in name pool.
Needs: validate-names

## Notes
- Output is a new theme entry in BuiltinThemes equivalent
- Could be stored as a pinned bead for persistence


Runtime dynamic expansion (for-each)

Implement runtime expansion for discovered work:
- on-complete: for-each: output.items
- Bonds N instances based on step output
- Christmas Ornament pattern support

Enables dynamic survey-workers → polecat-arm bonding.


Clean up stale children on deacon handoff bead

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

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


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.


🤝 HANDOFF: Investigate beads-sync divergence (221 files)

## Context

gt doctor now detects orphaned code on beads-sync branch. Running it shows:

  beads-sync-orphans: 221 file(s) on beads-sync not in main

This is in the gastown repo (checking from crew/max).

## Background

- Earlier today we recovered orphaned mail migration code lost in merge 96c773f
- Recently simplified architecture: all workers use mayor/rig/.beads (redirects)
- This simplification may have caused beads-sync branch to diverge unexpectedly

## Investigation Steps

1. From crew/max run: git diff main..beads-sync --stat
2. Check if beads-sync should even exist anymore (was for multi-clone sync)
3. If obsolete with redirect architecture, consider deleting it
4. If it has legitimate changes, cherry-pick or merge to main

## Key Question

With all workers using mayor/rig/.beads via redirects, is beads-sync still needed?

## Commands

git log main..beads-sync --oneline | head -20
git diff main..beads-sync -- *.go | head -100


Add molecule to update local go binary on push to main

When pushing to main branch, automatically rebuild and install the gt binary on the local machine so changes are immediately available.


plugin-run

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


gt mail: Cross-level routing is broken

**Problem:**
When Mayor (at ~/gt) sends mail to a rig worker (gastown/crew/max), the message lands in town-level beads (~/.beads/) but the recipient checks rig-level beads (crew/max/.beads/).

**Reproduction:**
```bash
cd ~/gt
gt mail send gastown/crew/max -s 'Test' -m 'body'
# Message goes to ~/gt/.beads/ with prefix hq-*

cd ~/gt/gastown/crew/max
gt mail inbox
# Does NOT see the message - it's looking in crew/max/.beads/
```

**Root cause:**
`findBeadsWorkDir()` walks up from CWD to find .beads. `Router.Send()` runs `bd create` in that directory. This means messages always go to the sender's beads, not the recipient's.

**Fix options:**
1. Route based on recipient address - if sending to rig/*, use that rig's .beads
2. Use a single shared beads database for all mail (simpler but less isolated)
3. Teach agents to check both levels (workaround, not fix)

**Related:**
- gt-ngu1: Pinned beads sorting (done but pointless if mail doesn't route)
- This blocks all cross-level mail functionality


Test MR

test


Digest: mol-deacon-patrol

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


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.


Refinery background daemon mode

Refinery currently only works in foreground mode. Background daemon is stubbed.

## Current State
manager.go line 128-129:
```go
// Background mode: spawn a new process
// For MVP, we just mark as running - actual daemon implementation in gt-ov2
return nil
```

## Requirements

### 1. Background Process Spawning
```go
func (m *Manager) Start(foreground bool) error {
    if !foreground {
        // Spawn gt refinery start --foreground as subprocess
        cmd := exec.Command(os.Args[0], "refinery", "start", m.rig.Name, "--foreground")
        cmd.Start()  // Don't wait
        // Record PID
    }
}
```

### 2. PID File Management
- Write PID to .gastown/refinery.pid
- Check PID validity on status
- Clean up stale PID files

### 3. Log Output
- Redirect stdout/stderr to .gastown/refinery.log
- Log rotation (optional for MVP)

### 4. Graceful Shutdown
- Handle SIGTERM/SIGINT
- Complete current merge before exit
- Update state to stopped

### 5. Health Check
- Process existence check via kill -0
- Optional: heartbeat file with timestamp

## Files to Modify
- internal/refinery/manager.go: Start(), Status(), process spawning

## Acceptance Criteria
- [ ] gt refinery start <rig> spawns background process
- [ ] gt refinery status shows running with PID
- [ ] gt refinery stop sends SIGTERM and waits
- [ ] Logs written to .gastown/refinery.log
- [ ] Survives terminal close


Refinery as Worktree: Local MR Integration

Move refinery from separate clone to git worktree. Polecats stop pushing to origin - refinery sees their branches locally. MRs become wisps (ephemeral). Only main gets pushed after merge.

## Goals
- Origin stays clean (only main + beads-sync branches)
- No orphaned polecat branches ever
- Simpler mental model for MR coordination
- Faster integration (no network for local MR ops)

## Trade-offs
- Machine crash = redo pending work (acceptable, beads track state)
- Future federation needs different approach (bundles or integration branch)

## Components Affected
- Rig initialization (refinery setup)
- Spawn/polecat workflow (remove origin push)
- Refinery manager (local branch access)
- Documentation (architecture, workflows)
- Molecule templates (remove push instructions)


Worker cleanup: Beads sync on shutdown

Add beads sync verification to worker cleanup checklist and Witness verification.

## Update to Decommission Checklist (gt-sd6)

Add to pre-done verification:
- bd sync --status must show 'Up to date'
- git status .beads/ must show no changes

## Beads Edge Cases

Uncommitted beads changes:
  bd sync
  git add .beads/
  git commit -m 'beads: final sync'

Beads sync conflict (rare):
  git fetch origin main
  git checkout main -- .beads/
  bd sync --force
  git add .beads/
  git commit -m 'beads: resolve sync conflict'

## Update to Witness Verification (gt-f8v)

When capturing worker state:
  town capture <polecat> "bd sync --status && git status .beads/"

Check for:
- bd sync --status shows 'Up to date'
- git status .beads/ shows no changes

If beads not synced, nudge:
  WITNESS CHECK: Beads not synced. Run 'bd sync' then commit .beads/. Signal done when complete.


Failure handling: assign back to worker, add labels

Handle merge failures appropriately.

Failure types and actions:
| Failure     | Action                                      |
|-------------|---------------------------------------------|
| conflict    | Add needs-rebase label, assign to worker    |
| tests_fail  | Add needs-fix label, assign to worker       |
| build_fail  | Add needs-fix label, assign to worker       |
| flaky_test  | Retry once, then treat as tests_fail        |
| push_fail   | Retry with backoff, escalate if persistent  |

Actions:
1. bd update <id> --status=open --assignee=<worker>
2. bd update <id> --labels=<failure-label>
3. Send mail to worker explaining failure
4. Log failure details

Reference: docs/merge-queue-design.md#handling-failures


Digest: mol-deacon-patrol

Test patrol cycle - first run, no actual work done


mol-ready-work variants: safe vs aggressive

## Summary

Create two variants of mol-ready-work:

### mol-ready-work-safe (default)
- PRs: review and comment, but require human approval for merge
- Issues: triage only, don't auto-close
- Beads: implement but create PR instead of pushing to main

### mol-ready-work-aggressive
- PRs: can approve and merge directly
- Issues: can close duplicates/invalid
- Beads: can push directly to main

## Implementation
Could be a single molecule with a `{{mode}}` variable, or two separate protos.

## Parent
Part of gt-tnca (mol-ready-work epic)


Guardrail: Verify commits exist before closing polecat issues

## Updated Approach (ZFC)

The original proposal was for mechanical guardrails in bd close. This contradicts the ZFC principle: all decisions go to models, not code.

## Correct Solution

The verification should happen in **mol-polecat-arm** execute step, not bd close:

In the pre-kill-verify action:
```bash
# Current steps
git status                    # Must be clean
git log origin/main..HEAD     # Check for unpushed
bd show <assigned-issue>      # Verify closed/deferred

# ADD: Verify productive work
git log --oneline --grep='<issue-id>' | head -1
# If no commits AND issue being closed as 'done' → flag for review
```

The agent (Witness) makes the decision. The mol gives it the verification step.

## Why Not Code Guardrails

Polecats have legitimate reasons to close issues without commits:
- Already done (someone else fixed it)
- Deferred (out of scope)
- Escalated (needs human decision)
- Duplicate (merged with another issue)

A code guardrail would block all these. The mol step lets the agent verify AND make the judgment call.

## Implementation

Update mol-polecat-arm execute step to include commit verification for 'done' closures.


Federation: Wasteland architecture for cross-town coordination

## Overview

Federation enables Gas Town to scale across machines via **Outposts** - remote compute environments that can run workers.

**Design doc**: docs/federation-design.md

## Outpost Types

| Type | Description | Cost Model |
|------|-------------|------------|
| Local | Current model (tmux panes) | Free |
| SSH/VM | Full Gas Town clone on VM | Always-on |
| CloudRun | Container workers on GCP | Pay-per-use |

## Key Concepts

### Outpost Abstraction
```go
type Outpost interface {
    Name() string
    Type() OutpostType  // local, ssh, cloudrun
    MaxWorkers() int
    Spawn(issue string, config WorkerConfig) (Worker, error)
    Workers() []Worker
    Ping() error
}
```

### Cloud Run Workers
- Persistent HTTP/2 connections solve zero-to-one cold start
- Pay only when working (~$0.017 per 5-min session)
- Scale 0→N automatically
- Git clone via persistent volumes

### SSH/VM Outposts
- Full Gas Town clone on remote machine
- SSH for commands, git for sync
- Good for long-running autonomous work

## Design Principles

1. **Outpost abstraction** - support multiple backends
2. **Local-first** - remote is for overflow/burst
3. **Git as source of truth** - code and beads sync everywhere
4. **HTTP for Cloud Run** - dont force mail onto containers
5. **Graceful degradation** - works with any subset of outposts

## Related

- gt-f9x.7-10: Connection interface (lower-level abstraction)
- docs/federation-design.md: Full architectural analysis


Formula error handling and recovery

Specify how cooking errors are reported and recovered:
- What happens when extends chain is broken (missing formula)?
- What happens when aspect pointcut matches nothing?
- What happens when expansion produces invalid structure?
- Graceful degradation vs fail-fast semantics
- Error metadata in cooked protos

Deferred: post-launch polish


gt context --usage: estimate remaining context via tmux line count

## Summary

Implement `gt context --usage` to estimate remaining context capacity.

## Approach

Use tmux scrollback buffer line count as proxy for token usage:
- `tmux capture-pane -p | wc -l` gives current line count
- Heuristics (tunable per model):
  - Opus 4.5: ~1800 lines = warning threshold
  - ~2000+ lines = critical, need handoff

## Output Format
```
Context Usage: 1642 lines (~82%)
Status: WARNING - consider handoff soon
```

## Notes
- Heuristics are model-specific, need config
- Line count is proxy, not exact token count
- Good enough for autonomous patrol decisions


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.


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.


Merge: gt-tnca.1

branch: polecat/immortan
target: main
source_issue: gt-tnca.1
rig: gastown


Rule of Five expansion template

Create rule-of-five as an expansion template:
- Jeffrey's discovery: agents converge in 4-5 iterations
- Template expands any step into 5-pass refinement
- draft → refine-1 → refine-2 → refine-3 → refine-4

First example of a macro-style expansion proto.


Immediate daemon notification on lifecycle request

When gt handoff sends a lifecycle request to the daemon (via bd mail send deacon/), the daemon only discovers it on its next heartbeat poll (every 5 min). Workers wait unnecessarily for retirement.

## Current Behavior
1. Worker runs gt handoff
2. Lifecycle mail sent to deacon/ via beads
3. Worker blocks waiting for retirement
4. Daemon heartbeat runs (up to 5 min later)
5. Daemon processes lifecycle request and kills session

## Expected Behavior
Lifecycle requests should be processed immediately, not on poll interval.

## Proposed Solutions

### Option A: SIGUSR1 Signal (simplest)
1. Add SIGUSR1 handler in daemon that calls ProcessLifecycleRequests()
2. gt handoff reads daemon.pid and sends SIGUSR1 after mail send

### Option B: Unix Socket
1. Daemon listens on ~/gt/daemon/lifecycle.sock
2. gt handoff connects and sends 'process' message

### Option C: Watchfile + fsnotify
1. gt handoff touches ~/gt/daemon/lifecycle.trigger
2. Daemon uses fsnotify to detect and process

Recommend Option A for simplicity.

## Affected Files
- internal/daemon/daemon.go - add signal handler
- internal/cmd/handoff.go - send signal after mail


Witness startup: bond mol-witness-patrol on start

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

## Desired behavior
On Witness session start:
1. gt prime detects RoleWitness
2. Check for existing in-progress patrol
3. If found: resume from current step
4. If not found: bd mol bond mol-witness-patrol --wisp
5. Output patrol context to agent

## Depends on
- gt-83k0 (mol-witness-patrol definition)
- gt-caih (handoff bead state persistence)


Implement Christmas Ornament pattern for mol-witness-patrol

Integrate dynamic bonding into mol-witness-patrol once Beads primitives are ready.

## Completed

- ✅ WaitsFor parsing (gt-odfr) - Parser now extracts WaitsFor: all-children
- ✅ mol bond command (gt-isje) - gt mol bond creates dynamic children with --var expansion
- ✅ WitnessPatrolMolecule() updated with Christmas Ornament structure (gt-tnow.1)
- ✅ PolecatArmMolecule() created for per-polecat inspection (gt-tnow.2)

## Remaining

- gt-tnow.3: Plugin hook support (P2)
- gt-tnow.4: Integration test with live polecats (P2)

## Design Docs

- docs/molecular-chemistry.md (already updated with pattern)
- docs/architecture.md (already updated with activity feed)
- gt-qflq: mol-witness-patrol design bead (updated)
- gt-dapb: mol-polecat-arm proto


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.


Document the Propulsion Principle

Write canonical documentation for the Universal Gas Town Propulsion Principle.

Location: gastown/mayor/rig/docs/propulsion-principle.md

Content:
- The One Rule (hook has work → work happens)
- Why it works (stateless agents, molecule-driven)
- The sling lifecycle diagram
- Agent startup protocol
- Examples and anti-patterns

This is foundational theory-of-operation documentation.


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


Add orphaned-attachments doctor check

Add gt doctor check for molecules attached to non-existent agents.

Check: orphaned-attachments
Warning if: Handoff bead exists for agent that no longer has worktree
Fix suggestion: Re-sling to active agent or close molecule


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: slit handoff (landing protocol), polecats cleaned (0 now), 4 witness/refineries up


gt mq submit: create MR from current branch

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

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

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

Creates merge-request bead and prints MR ID.

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


Swarm package: Swarm, SwarmTask, SwarmState types

Define core swarm types.

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

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

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

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

## Note

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


Witness Plugin System

Patrol extensions via molecule bonding.

## Core Insight

Plugins ARE molecules. No separate format needed.

## How It Works

```
mol-witness-patrol
    │
    ├── survey-workers
    │
    ├── plugin-run ←── bonds registered plugin molecules
    │       │
    │       ├── mol-mood-check (if registered)
    │       ├── mol-security-scan (if registered)
    │       └── mol-custom-X (user-installed)
    │
    └── aggregate (WaitsFor: all-children)
```

## Plugin Molecule Structure

A plugin is just a molecule proto with specific labels:

```json
{
  "id": "mol-mood-check",
  "title": "Polecat Mood Check",
  "description": "Assess polecat emotional state from output. Vars: {{polecat_name}}, {{captured_output}}",
  "labels": ["template", "plugin", "witness", "tier:haiku"],
  "issue_type": "task"
}
```

Labels encode metadata:
- `plugin` - marks as bondable plugin
- `witness` / `deacon` / `refinery` - which patrol can use it
- `tier:haiku` / `tier:sonnet` - model tier hint

## Registration

Plugins registered in rig config or molecules.jsonl:

```bash
# Install from Mol Mall
bd mol install mol-mood-check

# Or add to ~/.beads/molecules.jsonl manually
```

## Execution

The `plugin-run` step in patrol:

```bash
# For each registered plugin molecule matching this patrol:
bd mol bond mol-mood-check $PATROL_WISP \
  --ref mood-{{polecat_name}} \
  --var polecat_name=$POLECAT \
  --var captured_output="$OUTPUT"
```

## CLI

- `bd mol list --label plugin` - List available plugins
- `bd mol install <id>` - Install from Mol Mall
- `gt patrol plugins <role>` - Show plugins for a patrol role

## Benefits

- No YAML schema to maintain
- No separate plugin loading code
- Plugins are versioned, synced, auditable (they are beads)
- Distribution via Mol Mall (molecules.jsonl registry)
- Same {{var}} substitution as all molecules


Create activity aggregator

Component that connects to multiple rig beads daemons and merges their activity into a unified view. Polls GetMutations and GetWorkerStatus from each rig, groups by rig/worker. Handles connection failures gracefully.

BLOCKED BY (Beads rig):
- bd-gqxd: Enrich MutationEvent with title and assignee
- bd-l13p: Add GetWorkerStatus RPC endpoint
- bd-0oqz: Add GetMoleculeProgress RPC endpoint


gt refinery attach: Attach to refinery session

Add 'gt refinery attach [rig]' command to attach to refinery tmux session.

Mirrors 'gt mayor attach' pattern. If rig not specified, use current rig context.


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


Review and audit all GGT beads

Thorough review of all filed beads in gastown GGT repo. Check for: consistency, completeness, correct dependencies, accurate descriptions, proper prioritization. Ensure beads are self-contained and dont rely on external docs.


Merge: gt-70b3

type: merge-request
branch: polecat/Rictus
target: main
source_issue: gt-70b3
rig: gastown


done

Exit received. Ready for cleanup.

The polecat has completed its work and sent SHUTDOWN.
Perform cleanup:
```bash
gt session kill {{polecat}}
gt worktree prune {{polecat}}
```

Update beads state and close the lease.
Variables: {{polecat}}, {{issue}}


gt sling pinToHook doesn't set pinned boolean field

## Updated Root Cause Analysis (2025-12-23)

The issue is **NOT** in gt as originally thought. It's in the beads (bd) codebase.

### What happens:
1. `bd pin` correctly sets pinned=1 in SQLite
2. Any subsequent `bd` command (even `bd show`) resets pinned to 0
3. This happens even with `--no-auto-import` and `--sandbox` flags

### Evidence:
```bash
$ bd --no-daemon pin gt-k08o --for=max
📌 Pinned gt-k08o to max's hook

$ sqlite3 beads.db 'SELECT id, pinned FROM issues WHERE id="gt-k08o"'
gt-k08o|1   # ← Correct immediately after pin

$ bd --no-daemon --no-auto-import show gt-k08o
[shows issue without pinned field]

$ sqlite3 beads.db 'SELECT id, pinned FROM issues WHERE id="gt-k08o"'
gt-k08o|0   # ← WRONG\! bd show overwrote it
```

### Where to look:
The bug is likely in one of these beads code paths:
- Some import/hydration running despite --no-auto-import
- WAL mode not flushing before subsequent reads
- Multi-repo or redirect handling corrupting pinned field

### Workaround:
The handoff bead attachment mechanism (AttachMolecule) works correctly.
The pinned field is cosmetic for `bd hook` visibility only.
gt sling correctly uses AttachMolecule for work assignment.

### Next steps:
Create a beads issue to fix this properly in the bd codebase.
This is not a gt issue.

Created beads bug: bd-phtv in ~/gt/beads


Merge Queue in Beads: Universal chit system for all work

**Design doc**: docs/merge-queue-design.md


CLI: mayor commands (start, attach, stop, status)

Mayor management CLI commands.

## Commands

### gt mayor start
```
gt mayor start [--continue] [--agent AGENT]
```
- --continue: Resume from previous session (check for handoff mail)
- --agent: claude (default) or other agent type

### gt mayor attach
```
gt mayor attach
```
Attach to running Mayor session.

### gt mayor stop
```
gt mayor stop [--grace-period N]
```
Stop Mayor session with optional grace period.

### gt mayor status
```
gt mayor status [--json]
```
Show Mayor running status.

## Session Management
Session name: `gt-mayor`
Working directory: `<town>/mayor/rig/` or `<town>/mayor/`

## Implementation
Similar to session commands but for special Mayor context.

```go
func getMayorPath(townRoot string) string {
    return filepath.Join(townRoot, "mayor")
}

func getMayorSessionName() string {
    return "gt-mayor"
}
```

## New File
internal/cmd/mayor.go

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

## Acceptance Criteria
- [ ] gt mayor start launches Mayor session
- [ ] gt mayor attach works
- [ ] gt mayor stop with grace period
- [ ] gt mayor status shows running state


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


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.


working

Actively working. Monitor for stuck.

The polecat is processing its assigned issue ({{issue}}).
Monitor via peek. Watch for:
- Progress on commits
- Status updates in beads
- SHUTDOWN mail when done

Wait for SHUTDOWN signal from the polecat.
Variables: {{polecat}}, {{issue}}


TODO: Check if issue is child of configured epic in Witness

witness/manager.go:688 has a TODO to filter issues by whether they're children of the configured epic. Currently this filter is skipped.


Phase 1.1: Attachment field on pinned beads

Add attached_molecule field to pinned bead schema.

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

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

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