Molecule state file management

## Cross-Repo Reference

This work is tracked in beads repo as **bd-hulf**.

The gastown task gt-qvn7.2.2 is a placeholder.
Actual implementation happens in beads.

See: bd show bd-hulf (from beads/crew/dave)


Digest: mol-deacon-patrol

Patrol 13: clear


mol-polecat-arm formula

Define mol-polecat-arm.formula.yaml with steps: capture (gt peek worker), assess (analyze output for stalls/errors), intervene (gt nudge or escalate). This is the per-worker arm in Christmas Ornament pattern.


Test Patrol for Bonding

Parent issue for mol bond CLI test


Test: Alpha to Beta

Sibling communication test


Digest: mol-deacon-patrol

Patrol complete: 0 messages, agents healthy, no cleanup needed


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.


Digest: mol-deacon-patrol

Patrol 2: inbox clear, all agents healthy


Formula SDK: Developer Tooling for Workflow Authors

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

## Components

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

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

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

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

## Relationship to Other Concepts

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

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

## Open Questions

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

## Related

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


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Digest: mol-deacon-patrol

Patrol 14: all clear


Digest: mol-deacon-patrol

Patrol 8: All clear


Review: Witness patrol template changes (gt-h1n5)

Polecat rictus implemented significant witness.md.tmpl changes: banners, wisp-based execution, handoff bead attachment, loop-or-exit, patrol summary. Review for correctness and consistency with deacon pattern.


Polecat name pooling: Bounded reusable names

Polecats reuse names from a bounded pool (50) with overflow to sequence numbers.

## Naming Scheme
- Pool: polecat-01 through polecat-50 (prefer low numbers)
- Overflow: <rigname>-<sequenceNumber> (e.g., beads-51, gastown-52)

## Design
- Witness tracks which pool names are in use
- On spawn: pick first available from pool
- If pool exhausted: use rigname-N format
- On completion: pool name returns, sequence numbers don't

## Why?
- User experience: tmux sessions survive polecat restarts
- Users stay attached, see new polecat start (like mayor respawn loop)
- Bounded resource usage for common case
- Scales beyond 50 when needed

## Implementation
- Witness maintains name allocation in beads or local state
- Tmux session runs respawn loop (like mayor)
- Name released on graceful exit or when witness detects dead session


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 3: Quick scan, stable


Startup hook should validate attached molecule is still open

When the SessionStart hook outputs attached_molecule from the handoff bead, it should check if that molecule is still open. If closed, it should:
1. Clear the stale attachment
2. Auto-spawn a fresh patrol molecule
3. Attach the new patrol

Currently it just outputs the stale reference without validation, leaving the Deacon confused about what to run.


mol-deacon-patrol


Ephemeral rig support for ad-hoc batch work

Support for temporary worker rigs for ad-hoc batch work.

## Use Case

Ad-hoc batch work where you want temporary workers:
- gt spawn --epic <epic-id> --ephemeral --workers 3
- Creates temp rig with 3 clones
- Workers process epic children
- Work merges through queue
- Clones cleaned up when done

## Interface

```go
type EphemeralRig struct {
    ID               string
    GitURL           string
    BaseCommit       string
    Workers          []string
    IntegrationBranch string
    EpicID           string  // associated epic (for cleanup trigger)
    CreatedAt        time.Time
}

func InitEphemeralRig(gitURL string, numWorkers int) (*EphemeralRig, error)
func (r *EphemeralRig) AddWorker(name string) error
func (r *EphemeralRig) Destroy(force bool) error
```

## Directory Structure

```
<rig>/ephemeral/
└── rig-a3f7/
    ├── config.json
    ├── Alice/     # clone
    ├── Bob/       # clone
    └── Carol/     # clone
```

## Cleanup Trigger

When all issues in the associated epic are closed AND merged, the ephemeral rig can be destroyed.

## Note

No swarm ID needed - the epic ID provides the grouping. Ephemeral rig is just a convenience for temporary clones.

## Reference

PGT: ephemeral.py (for structure, ignore swarm ID coupling)


Formula parser and YAML schema

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

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

**Beads issue: bd-weu8**


Digest: mol-deacon-patrol

Patrol 7: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol 6: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Work on ga-xxp: Define mol-polecat-work standard molecule...

Work on ga-xxp: Define mol-polecat-work standard molecule. See bd show ga-xxp for full details.


Phase 1: Core messaging primitives (@group, list:, queue:)

## Scope

Core messaging infrastructure that enables multi-recipient and work-queue patterns.

### Deliverables

1. **Config directory structure** - ~/gt/config/ with lists.json, queues.json
2. **@group dynamic resolution** - Filesystem scan for agent directories
   - @rig/gastown → scan gastown/ for agents
   - @town → scan all rigs
   - @witnesses, @crew/gastown, etc.
3. **list:name static lookup** - Fan-out to N copies (each recipient gets work item)
4. **queue:name with claim** - Shared storage, atomic claim via bd update --claim
5. **Fan-out at send time** - gt mail send handles expansion

### Key semantics
- @group and list: both fan out (N copies, N obligations)
- queue: shared copy, first-to-claim wins
- All resolve at send time, not receive time


Doctor check: Zombie session cleanup

Detect and clean up zombie tmux sessions via gt doctor.

## Problem

Zombie sessions occur when:
- Agent crashes without cleanup
- gt kill fails mid-operation
- System restart leaves orphan sessions
- Session naming collision

## Checks

### ZombieSessionCheck
- List all tmux sessions matching gt-* pattern
- Cross-reference with known polecats
- Flag sessions with no corresponding polecat state
- Flag sessions for removed polecats
- Check session age vs polecat creation time

### Detection Criteria
- Session exists but polecat directory doesn't
- Session name doesn't match any registered polecat
- Polecat state=idle but session running
- Multiple sessions for same polecat

## Output

```
[WARN] Zombie tmux sessions detected:
  - gt-wyvern-OldPolecat (polecat removed)
  - gt-beads-Unknown (no matching polecat)
  - gt-wyvern-Toast (duplicate session)

  Run 'gt doctor --fix' to clean up
```

## Auto-Fix (--fix flag)

- Kill orphan tmux sessions
- Update polecat state to match reality
- Log all cleanup actions

## Safety

- Never kill sessions where polecat state=working
- Prompt before killing if --fix used without --force
- Create audit log of killed sessions


Digest: mol-deacon-patrol


Test Patrol Parent

Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Test patrol cycle - verifying wisp flow


Digest: mol-deacon-patrol

Patrol 7: routine


Digest: mol-deacon-patrol

Patrol 20: all healthy, doctor pass, handoff cycle


gt spawn should create fresh polecat worktree, never reuse

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

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

## Current Behavior

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

## Desired Behavior

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

## Name Pool Still Useful

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

But worktrees should be created fresh each time.

## Implementation

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

This ensures polecats always start with latest code and beads.


gt doctor: detect orphaned code on beads-sync branch

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

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

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

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

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


gt spawn: Not injecting work instructions to session

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

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

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


Digest: mol-deacon-patrol

Patrol #19: Stable


Add 'gt account default' command

Set the default account in accounts.yaml. Used when no GT_ACCOUNT env or --account flag specified.


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol complete: 6 msgs archived, all agents healthy, cleaned 29 stale mols


Digest: mol-deacon-patrol

Patrol 3: All healthy


Digest: mol-deacon-patrol

Patrol 4: Routine, all healthy


Digest: mol-deacon-patrol

Patrol 8: Quiet


Digest: mol-deacon-patrol

Patrol 9: Quiet


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


LocalOutpost: Refactor current polecat spawning

## Overview

Refactor current local polecat spawning to implement the Outpost interface.

## Current State

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

## Implementation

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

func NewLocalOutpost(config OutpostConfig) *LocalOutpost

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

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

## LocalWorker

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

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

## Notes

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

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


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


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


Digest: mol-deacon-patrol

Patrol 20 - handoff threshold reached


Nested loop support in control flow

Currently, nested loops (a loop inside a loop body) are not supported.

In expandLoopIteration(), the Loop field is intentionally not copied:
```go
// Note: Loop field intentionally not copied - nested loops need explicit support
```

To support nested loops:
1. After expanding the outer loop iteration, recursively call ApplyLoops on the body steps
2. Handle nested iteration ID prefixing (e.g., `outer.iter1.inner.iter2.step`)
3. Add tests for nested loop scenarios

This is a lower-priority enhancement since most real-world formulas use single-level loops.


Digest: mol-deacon-patrol

Patrol cycle 3: all systems nominal


Missing standard OSS files: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY

For OSS launch, we need:
1. CONTRIBUTING.md - How to contribute, PR process, code style
2. CODE_OF_CONDUCT.md - Community standards
3. SECURITY.md - How to report vulnerabilities

These are expected by OSS communities and GitHub surfaces them in repo UI.


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)


Digest: mol-deacon-patrol

Patrol 6: OK


Digest: mol-deacon-patrol

Patrol 17: All healthy


Digest: mol-deacon-patrol

Patrol #14


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

# CLI API Audit for OSS Launch

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

## Current State Audit

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

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

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

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

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

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

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

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

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

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

## Structural Concerns

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

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

### 2. Overlap between gt and bd

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

Which owns what? User confusion likely.

### 3. Naming inconsistencies

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

### 4. Subcommand depth decisions

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

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

### 5. Flag vs subcommand guidelines needed

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

## Recommendations to Evaluate

### A. Consolidate gt top-level commands

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

### B. Clarify gt vs bd ownership

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

### C. Apply consistent naming

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

### D. Flag vs subcommand rule

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

## Tasks

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

## Success Criteria

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


Test message

Testing GGT mail integration


Digest: mol-deacon-patrol

Patrol 18: All healthy


Digest: mol-deacon-patrol

Patrol 6: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol 13


Session management: start, stop, attach, capture

Polecat session lifecycle management.

## Interface

```go
type SessionManager struct {
    tmux *Tmux
    rig  *Rig
}

func NewSessionManager(tmux *Tmux, rig *Rig) *SessionManager

// Lifecycle
func (sm *SessionManager) Start(polecat string, opts StartOptions) error
func (sm *SessionManager) Stop(polecat string) error
func (sm *SessionManager) IsRunning(polecat string) (bool, error)
func (sm *SessionManager) List() ([]SessionInfo, error)

// Interaction
func (sm *SessionManager) Attach(polecat string) error
func (sm *SessionManager) Capture(polecat string, lines int) (string, error)
func (sm *SessionManager) Inject(polecat string, message string) error

type StartOptions struct {
    WorkDir   string   // defaults to polecat clone dir
    Issue     string   // optional: issue to work on
    Command   string   // optional: override claude command
}

type SessionInfo struct {
    Polecat   string
    SessionID string
    Running   bool
    StartedAt time.Time
}
```

## Session Naming

`gt-<rig>-<polecat>` (e.g., `gt-wyvern-Toast`)

## Start Flow

1. Verify polecat clone exists
2. Check no existing session
3. Create tmux session in polecat workdir
4. Send initial command: `claude` or custom
5. If issue provided, inject initial prompt

## Stop Flow

1. Capture final output (for logging)
2. Send exit/quit command
3. Wait briefly for graceful shutdown
4. Kill session if still running

## Capture

Uses tmux capture-pane to get recent output. Returns last N lines.

## Inject

Sends text to session via tmux send-keys. Used for:
- Mail notifications
- Witness nudges
- User messages


Test Patrol Parent

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

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

Original description:
Test parent for Christmas Ornament pattern


gt crew status: Show workspace status

Implement 'gt crew status [<name>]' command:
- Show session state (running/stopped)
- Show git status (branch, uncommitted changes, unpushed)
- Show last commit info
- Show mail inbox status (unread count)
- If no name given, show all crew workers


Swarm learning: Refinery merge queue automation

Manually merging 15 polecat branches was painful and error-prone. Refinery should automate: detect completed work, run tests, merge to main, handle conflicts. This is core Refinery value prop.


Digest: mol-deacon-patrol

Patrol 18: OK


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.


Digest: mol-deacon-patrol

Patrol 11: clear


Activity Feed TUI

Terminal UI for browsing Gas Town activity. Shows hierarchical view of rigs, workers, and their current state. Features: live updates, expandable details, molecule progress (step X of Y). Built with bubbletea/lipgloss. Design doc: history/activity-feed-tui-design.md


Mail should use wisps for ephemeral orchestration messages

## Problem

Town HQ beads are polluted with lifecycle orchestration messages:
- POLECAT_STARTED notifications
- Work assignments to polecats
- "Start work" nudges
- Test messages

These should never have been persistent beads. They accumulate forever.

## Analysis

Mail serves two purposes:
1. **Durable messages** - Handoffs, escalations, human-agent comms (need persistence)
2. **Ephemeral signals** - Lifecycle pings, work assignments, nudges (should be wisps)

## Options

### Option A: Dual-inbox architecture
- `gt mail inbox` checks both `.beads/` and `.beads-wisp/`
- Sender specifies `--ephemeral` flag for transient messages
- Ephemeral messages auto-expire or squash to digests

### Option B: All mail becomes wisps
- Default to wisp storage for all mail
- Important messages explicitly promoted to persistent
- Simpler model but loses audit trail for some messages

### Option C: Message type determines storage
- `message` type beads go to wisps by default
- `handoff` type stays persistent
- Automatic routing based on content

## Recommendation

Option A (dual-inbox) seems cleanest:
- Explicit control via `--ephemeral`
- Backwards compatible
- Clear mental model

## Acceptance Criteria

- Lifecycle pings (POLECAT_STARTED, etc.) go to wisps
- Work assignments go to wisps
- Handoffs stay persistent
- `gt mail inbox` shows both
- Wisps auto-cleanup on patrol squash

## Blocks

This blocks reliable swarm operations - every spawn pollutes HQ indefinitely.


Implement aspect merging across formula chain

Implement merging of aspects when formulas extend each other.

## Current State

extends: already works for steps and vars.
Aspects need similar merge behavior.

## Implementation

1. In Resolve(), collect aspects from entire extends chain
2. Merge lists: parent aspects first, then child
3. Support exclude-aspects field to remove inherited aspects
4. Dedupe by aspect name (child wins on conflict)

## Files

- internal/formula/parser.go: Resolve()
- internal/formula/types.go: add ExcludeAspects field

## Tests

1. Child inherits parent aspects
2. Child adds additional aspects
3. Child excludes parent aspect
4. Three-level chain merges correctly


Digest: mol-deacon-patrol

Quick patrol: no messages, all healthy


Digest: mol-deacon-patrol

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


Digest: mol-deacon-patrol

Patrol 7: routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 20: All healthy - final patrol


mol-deacon-patrol


Digest: mol-deacon-patrol

P11: stable


Digest: mol-deacon-patrol

Patrol 15: All clear


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


Digest: mol-deacon-patrol

Patrol 5: routine


Swarm learning: Session cleanup missing from swarm workflow

## Problem

After Enders Game swarm completed (18 issues merged), 16 polecat sessions were left running but idle. No automated cleanup occurred.

## What Should Happen

1. Witness detects polecat completed work (idle at prompt)
2. Witness verifies git state is clean
3. Witness shuts down session
4. Witness reports completion to Mayor

## GGT Components

- gt-cxx: Witness context cycling (covers self-cycling)
- gt-u1j.9: Witness daemon heartbeat loop
- gt-kmn.6: Witness swarm landing protocol

## Recommendation

Add to Witness responsibilities:
- Monitor for 'work complete' signals (DONE keyword, idle detection)
- Automated session shutdown after verification
- Swarm completion reporting to Mayor

See also: architecture.md 'Worker Cleanup (Witness-Owned)' section which describes this but it wasn't implemented in PGT.


gt mol status: role detection fails from polecat directory

When running 'gt mol status' from a polecat's worktree directory (e.g., ~/gt/gastown/polecats/furiosa), the role detection incorrectly returns 'mayor' instead of 'gastown/furiosa'.

## Root Cause
The detectRole() function in prime.go calculates relPath from townRoot (~gt) to cwd (~/gt/gastown/polecats/furiosa), giving 'gastown/polecats/furiosa'. It then checks parts[0] == 'mayor' but 'gastown' != 'mayor', so it falls through to rig detection where it treats 'gastown' as a rig name.

However, the code then looks for parts[1] == 'polecats' but the actual check is parts[1] == 'polecats' which should work...

## Actual Issue
Need to debug further - the hook file IS created correctly by spawn, but gt mol status can't find it because it's looking for the wrong agent identity.

## Expected
Running from ~/gt/gastown/polecats/furiosa should detect:
- Role: polecat
- Rig: gastown
- Polecat: furiosa
- Agent identity: gastown/furiosa

## Actual
- Role: mayor
- Agent identity: mayor

This prevents polecats from seeing their slung work via gt mol status.


Digest: mol-deacon-patrol

Patrol 2: all clear, 9 sessions healthy


Digest: mol-deacon-patrol

Patrol 17


Digest: mol-deacon-patrol

Patrol 13: routine


Digest: mol-deacon-patrol

P6: stable


gt spawn/crew setup should create .beads/redirect for worktrees

Crew clones and polecats need a .beads/redirect file pointing to the shared beads database (../../mayor/rig/.beads). Currently:

- redirect files can get deleted by git clean
- not auto-created during gt spawn or worktree setup
- missing redirects cause 'no beads database found' errors

Found missing in: gastown/joe, beads/zoey (after git clean)

Fix options:
1. gt spawn creates redirect during worktree setup
2. gt prime regenerates missing redirects
3. bd commands auto-detect worktree and find shared beads

This should be standard Gas Town rig configuration.


Create patrol formula YAML files

Create formula YAML files for:
- mol-deacon-patrol.formula.yaml
- mol-witness-patrol.formula.yaml
- mol-refinery-patrol.formula.yaml

Use the step definitions currently in molecules_patrol.go as reference.
Store in .beads/formulas/


Witness patrol: stale MR queue detection needs state tracking

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

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

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

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


Merge: gt-5af.5

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


#channel resolution for real-time broadcast

Wire tmux scanner into nudge system for #channel addresses.

## Deliverables

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

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

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

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


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

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


Consider splitting large files (800+ lines)

Several files are getting large and may benefit from splitting:
- internal/beads/beads.go (990 lines)
- internal/cmd/molecule.go (981 lines)
- internal/refinery/manager.go (934 lines)
- internal/beads/beads_test.go (883 lines)
- internal/cmd/polecat.go (836 lines)
- internal/witness/manager.go (808 lines)
- internal/cmd/mail.go (804 lines)

For .go files, consider extracting logical subsystems. For test files, this is lower priority.


Digest: mol-deacon-patrol

Patrol 9: routine


bd mol advance command

## Cross-Repo Reference

This work is tracked in beads repo as **bd-3zm7**.

The gastown task gt-qvn7.2.1 is a placeholder.
Actual implementation happens in beads.

See: bd show bd-3zm7 (from beads/crew/dave)


Design: Polecat Beads write access

Design for granting polecats direct beads write access.

## Background

With Beads v0.30.0 tombstone-based rearchitecture, we have solid multi-agent support. Reversing the original read-only decision.

## Benefits

- Simplifies architecture (no mail-based issue filing proxy)
- Empowers polecats to file discovered work
- Beads handles work-disavowal

## Complications

For OSS projects where you cannot commit to project .beads/, need per-rig beads repo configuration.

## Subtasks (implementation)

- gt-zx3: Per-rig beads configuration schema
- gt-e1y: Worker prompting updates for beads access
- gt-cjb: Witness proxy removal
- gt-082: Beads sync in decommission checklist

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


Test

Body


Merge: gt-72so

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


Digest: mol-deacon-patrol


Update Mayor prompting in gastown-py

The Mayor CLAUDE.md and related prompting in gastown-py (still in production use) needs to reflect current design decisions: session cycling, handoff protocol, cleanup responsibilities, beads access model. Sync prompting with GGT design work.


execute-actions

Send nudges, process shutdowns, escalate as decided.

Needs: decide-actions


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


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

Patrol 13: All healthy


Digest: mol-deacon-patrol

P16: stable


Execute registered plugins

Execute registered plugins.

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 14: routine


Digest: mol-deacon-patrol

Patrol 13: Quiet


Digest: mol-deacon-patrol

Patrol 6: routine, all healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Mol Mall: Formula marketplace and aspect composition

## Summary

A marketplace for sharing molecule formulas using GitHub as backend, plus a new
**aspect composition** capability for cooking that allows formulas to be applied
as cross-cutting transformations to existing mols.

## Key Insight

Formulas aren't just standalone workflows—they're **transformations** you can
apply to other mols. This enables patterns like:
- "Apply Rule of Five code review to any coding task"
- "Wrap any epic with security review steps"
- "Add logging/metrics to any patrol molecule"

## Architecture

```
Remote Formulas (GitHub)
        ↓ install
Local Formulas (~/.gt/formulas/ or .beads/formulas/)
        ↓ cook --with
Mols (beads, git-tracked)
        ↓ pour/sling
Execution (ephemeral or tracked)
```

## Formula Types

1. **Standalone** - Complete workflows (mol-polecat-work, mol-deacon-patrol)
2. **Aspects** - Cross-cutting concerns woven into other mols (rule-of-five)
3. **Adapters** - Wrappers that make things runnable

## Aspect Composition (New Cooking Capability)

```bash
bd cook my-epic --with rule-of-five,security-review
```

Aspects declare injection points:

```yaml
# rule-of-five.formula.yaml
kind: aspect
name: rule-of-five
version: 1.2.0

inject_after:
  tag: generates-code  # matches any step with this tag

steps:
  - id: review-correctness
    title: "Review: Correctness"
  - id: review-edge-cases
    title: "Review: Edge Cases"
  - id: review-performance
    title: "Review: Performance"
  - id: review-security
    title: "Review: Security"
  - id: review-maintainability
    title: "Review: Maintainability"
```

Injection modes:
- `inject_after: <step-id or tag>` - insert steps after
- `inject_before: <step-id or tag>` - insert steps before
- `wrap: <step-id or tag>` - insert before AND after
- `replace: <step-id or tag>` - substitute entirely

## The Mall Index

A well-known repo maps short names to full references:

```yaml
# steveyegge/gt-mall/index.yaml
formulas:
  rule-of-five:
    repo: steveyegge/gt-formulas
    path: aspects/rule-of-five.formula.yaml
    version: v1.2.0
    description: "Five-lens code review"
    tags: [review, quality]
```

Commands:
- `gt mol search review` - search the index
- `gt mol install rule-of-five` - fetch from GitHub
- `gt mol install github.com/acme/formulas/custom@v1` - direct URL

## Implementation Phases

### Phase 1: Aspect Composition (Cooking)
- Extend `bd cook` to accept `--with aspect1,aspect2`
- Aspect application during mol generation
- Local aspects in `.beads/formulas/`

### Phase 2: Mall Index
- Create gt-mall repo with index.yaml
- `gt mol search` queries the index
- `gt mol install` fetches and caches formulas

### Phase 3: Publishing
- `gt mol publish` pushes to your formula repo
- PR workflow to add to mall index

### Phase 4: Refinements
- Aspect ordering and conflict detection
- Aspect dependencies (`requires: [other-aspect]`)
- Private formula repos (enterprise)
- Local overrides/forks

## Open Questions

1. **Ordering conflicts**: Two aspects inject after same step—which goes first?
2. **Aspect dependencies**: Aspect A requires aspect B?
3. **Compile-time vs runtime**: Aspects are compile-time (baked into mol).
   Wisps remain runtime (slung dynamically).

## Deferred Until

Gas Town patrols operational. Prerequisites:
- [ ] Patrol system working (Deacon, Witness, Refinery)
- [ ] Basic spawn/work/merge cycle
- [ ] Activity feed showing work progress

Then the mall becomes valuable for sharing patrol customizations.

## Supersedes

This replaces gt-uzf2l which had the original marketplace concept but lacked
the aspect composition insight.

## Related

- Cooking system (bd cook)
- Formula definitions (.formula.yaml)
- Wisp architecture (runtime molecules)

See docs/formula_evolution.md for expanded thinking on: formula resolution hierarchy, combinators (>>, |, wrap, inject, extends), algebraic properties, higher abstractions, Mol Mall registry predictions, distribution scenarios, and open questions. The aspect composition in this design corresponds to the Wrapping (AOP) and Injection combinators in that doc.


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

Patrol 15


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


Outpost CLI commands: gt outpost list/status/add

## Overview

CLI commands for managing outposts.

## Commands

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

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

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

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

# Remove outpost
gt outpost remove <name>

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

## Files

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

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


Deacon CLAUDE.md for patrol execution

Update Deacon role CLAUDE.md for patrol execution.

## Key Additions

### Role Definition

```markdown
## Your Role: DEACON

You are the Deacon - Gas Towns heartbeat process.
You run mol-deacon-patrol continuously.

Your job:
- Check mail for callbacks
- Spawn polecats for ready work
- Monitor rig health (basic)
- Cycle context when full
```

### Patrol Execution

```markdown
## Patrol Execution

You run mol-deacon-patrol on your hook.

On each heartbeat from the daemon:
1. Check your current step: bd hook
2. Execute that step
3. Advance: bd mol advance mol-deacon-patrol
4. If COMPLETE: restart the patrol or cycle context

The daemon keeps you alive. Your job is to run the patrol.
```

### Heartbeat Response

```markdown
## Heartbeat Response

When you see "HEARTBEAT: ..." from the daemon:
- If idle: check your hook, start/resume patrol
- If mid-step: continue working
- If waiting: the heartbeat reminds you to check state

Heartbeats are your clock tick. Use them.
```

### Context Cycling

```markdown
## Context Cycling

When context is high (>80%):
1. Write state to molecule
2. Run: gt handoff -s "Deacon cycling" -m "Context full"
3. Exit cleanly
4. Daemon respawns you
5. You wake, prime, read hook, continue
```

## File

deacon/CLAUDE.md (in town root)


Digest: mol-deacon-patrol

Patrol complete: 0 mail, Mayor+2 witnesses+2 refineries healthy, 3 polecats working (gastown), no orphans, gc N/A


Add 'gt account list' command

Show registered accounts from accounts.yaml. Mark default with asterisk. Show handle, email, description.


mol-witness-patrol molecule definition

Create mol-witness-patrol in builtin_molecules.go.

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

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

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


gt park command for parking molecules on external deps

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

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

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

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

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

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


Fix gt prime to give crew workers crew context

gt prime currently gives Mayor context to all agents. Crew workers should get crew-specific context. Also extract shared theory of operation from mayor priming into shared context for all roles.


Digest: mol-deacon-patrol

Patrol 8: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 10: all quiet


Digest: mol-deacon-patrol

Patrol 12


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 11: All healthy


mol-deacon-patrol


Phase 3.2: mol-polecat-work squash step

Add summary+squash as final steps in mol-polecat-work.

## Current Steps

1. read-assignment
2. understand-task
3. implement-solution
4. verify-tests
5. commit-work
6. signal-done

## Updated Steps

1. read-assignment
2. understand-task
3. implement-solution
4. verify-tests
5. commit-work
6. **generate-summary** ← NEW
7. **squash-molecule** ← NEW
8. signal-done

## Step Definitions

### generate-summary
Agent writes a concise summary following the template.
Save to a local variable or temp file.

### squash-molecule
Run: bd squash $MOLECULE_ROOT --summary "$SUMMARY"
This creates digest in main beads, cleans ephemeral.

## Update Location

This requires updating the mol-polecat-work definition in beads molecule catalog.


Remove all hardcoded gastown dependencies from gt codebase

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

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

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

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


Dynamic wisp modification: insert, reorder, bond mid-execution

## Vision

Wisps should be living documents that adapt mid-execution, not static scripts.

## Operations Needed

### bd mol insert
Insert a step into a running wisp:
```bash
bd mol insert <wisp-id> --after <step> --step 'security-gate: Review auth changes'
```

### bd mol reorder
Change step order in a running wisp:
```bash
bd mol reorder <wisp-id> --move process-branch --before current
```

### bd mol bond (to wisp)
Attach an entire molecule to a running wisp:
```bash
bd mol bond mol-weekly-maintenance <wisp-id> --after await-work
```

### bd mol skip
Skip a step (with reason):
```bash
bd mol skip <wisp-id> <step> --reason 'Queue empty, skipping summary'
```

## Use Cases

1. **Hotfix priority**: Reorder queue to process urgent MR first
2. **Security gate**: Insert review step when PR touches sensitive files
3. **Scheduled maintenance**: Bond maintenance mol on schedule
4. **Context adaptation**: Skip steps when they don't apply

## Why This Matters

Engine room problems emerge dynamically. The wisp's flexibility lets agents model situations as they evolve, not execute rigid scripts.

GUPP still applies: whatever's on your hook, you run. But the hook contents can adapt.

## Implementation

This requires Beads changes to support wisp mutation:
- Track step ordering in wisp storage
- Support step insertion/deletion/reordering
- Handle bond-to-wisp (spawn steps into existing wisp)
- Preserve audit trail of modifications


CLI: mail commands (send, inbox, read)

CLI: mail commands wrapping bd mail.

## Status

Current implementation works with JSONL files. Refactor to wrap bd mail CLI.

## Commands

### gt mail inbox
```
gt mail inbox [--unread] [--json]
```
Wraps: `bd mail inbox [--json]`

### gt mail read
```
gt mail read <id>
```
Wraps: `bd mail read <id> && bd mail ack <id>`
Note: bd mail read + ack marks as read.

### gt mail send
```
gt mail send <address> -s "Subject" -m "Body" [--notify]
```
Wraps: `bd mail send <recipient> -s "Subject" -m "Body"`
If --notify: inject tmux notification after send.

### gt mail delete
```
gt mail delete <id>
```
Wraps: `bd mail ack <id>` (closes the message issue)

## Address Translation

Same as gt-u1j.6:
- `mayor/` → `mayor`
- `<rig>/refinery` → `<rig>-refinery`
- `<rig>/<polecat>` → `<rig>-<polecat>`

## Dependencies

- gt-u1j.6: Mail system backend


Digest: mol-deacon-patrol

Patrol 3: routine checks, all healthy


load-context

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

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


Merge: gt-5af.2

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


mol-outpost-assign: Intelligent work routing to outposts

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

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

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

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 6: Routine


Map expansion should match nested child steps


Digest: mol-deacon-patrol

Patrol OK: no mail, 8 polecats working, all witnesses/refineries up


Digest: mol-deacon-patrol

Patrol 6: Quick cycle, all quiet


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

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

## Usage

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

## Behavior

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

## Output

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

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

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

## If no next step

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

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

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

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


Check Witness and Refinery health

Check Witness and Refinery health for each rig.

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

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

**Signals to assess:**

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

**Tracking unresponsive cycles:**

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

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

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

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

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

Reset unresponsive_cycles to 0 when component responds normally.


Self-mail should suppress tmux notification

When sending mail to yourself (e.g., mayor sending to mayor/), the tmux notification shouldn't fire.

**Rationale:**
- Self-mail is intended for future-you (next session handoff)
- Present-you just sent it, so you already know about it
- The notification is redundant/confusing in this case

**Fix:**
Suppress tmux notification when sender == recipient address.


Digest: mol-deacon-patrol

Patrol 19: routine


Add molecules.jsonl as separate catalog file for template molecules


Witness patrol: cleanup idle orphan polecats

Add patrol step to find and cleanup polecats that are idle with no assigned issue. These orphans occur when polecats crash before sending DONE or Witness misses the message. Patrol should verify git is clean before removing worktree. Part of gt-rana.


Digest: mol-deacon-patrol

Patrol cycle 3: routine check, all healthy


mol-deacon-patrol


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.


Convert MR queue to wisp storage

MR queue should use wisp storage (.beads-wisp/) instead of durable beads.

## Design (Simplified)

With refinery as worktree, polecats and refinery share the same machine. No cross-machine MR coordination needed. Wisps are the natural fit.

### Storage
- Location: `.beads-wisp/mq/<mr-id>.json`
- Format: Same MRFields structure (branch, target, source_issue, worker, rig)
- Lifecycle: Create on submit, delete after merge

### Code Changes

1. **MR Creation** (done.go, mq_submit.go)
   - Write to `.beads-wisp/mq/` instead of `bd create --type=merge-request`
   - Generate ID: `mr-<timestamp>-<random>` or similar

2. **Refinery Query** (refinery/manager.go, engineer.go)
   - Read from `.beads-wisp/mq/` directory
   - List files, parse JSON, process in order

3. **Cleanup**
   - Delete MR file after successful merge
   - On failure, leave file (refinery retries)

### What Stays in Beads
- Source issues (the work being merged) - still tracked in beads
- Merge commits reference source issue ID
- `bd close <issue>` still happens on merge

### Benefits
- No sync overhead for transient MR state
- Simpler model (file per MR, delete when done)
- Consistent with wisp philosophy (ephemeral operational state)

### Not Needed
- Digest squashing (MRs are deleted, not accumulated)
- Cross-machine visibility (single-machine architecture)


Molecule instantiation: create child beads from template

When instantiating a molecule on a work bead:

## Transaction Flow

1. Parse molecule's `## Step:` sections from description
2. Begin SQLite transaction
3. For each step, create child issue:
   - ID: `{parent-id}.{step-ref}` or generated
   - Title: step title (from header or first line)
   - Description: step prose instructions
   - Type: task
   - Priority: inherit from parent
4. Add `instantiated-from` edge from each step to molecule:
   ```sql
   INSERT INTO dependencies (issue_id, depends_on_id, type, metadata)
   VALUES (step_id, mol_id, 'instantiated-from', '{"step": "implement"}');
   ```
5. Wire inter-step dependencies from `Needs:` lines
6. Commit transaction (atomic - all or nothing)

## Parsing Conventions

```markdown
## Step: <ref>
<prose instructions>
Needs: <step>, <step>  # optional
Tier: haiku|sonnet|opus  # optional hint
```

## Parameterization

Steps can have `{{variable}}` placeholders:
```markdown
## Step: implement
Implement {{feature_name}} in {{target_file}}.
```

Context map provided at instantiation time.

## API

```go
func (s *Store) InstantiateMolecule(mol *Issue, parent *Issue, ctx map[string]string) ([]*Issue, error)
func ParseMoleculeSteps(description string) ([]MoleculeStep, error)
```

Implementation lives in `internal/beads/molecule.go`.


Digest: mol-deacon-patrol

Patrol 8


Digest: mol-deacon-patrol

Patrol 1: All healthy, no lifecycle requests, 8 active sessions


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

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


Digest: mol-deacon-patrol

Patrol #5: Stable


Replaceable notifications via Claude Code queue

Leverage Claude Code's ability to replace queued text for notifications that supersede previous ones.

## Problem

If daemon sends 10 heartbeats while agent is busy, agent returns to see 10 stacked messages. Wasteful and noisy.

## Solution

Use Claude Code's queue replacement for:
- Heartbeat messages (only latest matters)
- Status updates that supersede previous
- Progress notifications

## Implementation

Notifications get a 'slot' identifier. New notification in same slot replaces old one:
- Slot: 'heartbeat' → only one heartbeat queued at a time
- Slot: 'status-<rig>' → latest status per rig
- No slot → stacks normally (for unique messages)

## Research Needed

- How does Claude Code expose queue replacement?
- tmux send-keys behavior with pending input
- Alternative: clear + resend pattern


Test4

test4 body


Digest: mol-deacon-patrol

Patrol 16


Design mol-ready-work patrol for crew workers

## Summary

Design and implement a protomolecule (mol-ready-work) that enables crew workers to autonomously work through backlogs when the overseer is away. This replaces the normal "await instructions" patrol step with productive backlog processing.

## Context

Crew workers like dave/joe are persistent, user-managed agents. Currently their patrol loop has an "await instructions" step that idles. We want an alternative: sling mol-ready-work at them and they crank through backlogs until:
- The overseer interrupts with new instructions
- Context fills up (request handoff)
- Backlogs are empty

## Backlogs (Priority Order)

1. **Open PRs** - Review/merge pending pull requests
2. **Untriaged GH issues** - New issues needing triage
3. **Open beads work** - bd ready items (unblocked issues)
4. **Triaged GH issues** - Bugs/features to implement

## Key Features

### ROI-Based Selection
Instead of strict priority, agent applies ROI heuristic:
- Size estimate (fits in remaining context?)
- Achievability (has all needed info?)
- Impact (priority + type weight)
- Pick highest-value achievable item

### Context Management
- Check token usage after each work item
- Request handoff before running out
- Leave clear handoff notes (mail to self)
- Next session picks up the patrol

### Patrol Loop Structure
```
orient → scan-backlogs → select-work → execute-work → check-context → (loop or handoff)
```

## Design Questions

1. How does gt sling work? Does it exist?
2. How does this interact with the normal crew patrol?
3. Should the molecule go in Gas Town catalog or per-rig?
4. How does bonding work for discovered work during execution?
5. Should this be a wisp (ephemeral) or mol (persistent)?

## Acceptance Criteria

- [ ] mol-ready-work protomolecule defined in catalog
- [ ] gt sling command implemented (or existing mechanism documented)
- [ ] Context-checking step works with agent token awareness
- [ ] Handoff mechanism integrates with gt mail
- [ ] Documentation for crew workers on using the patrol


Plugin system: subprocess JSON protocol

Language-agnostic plugin system via subprocess JSON protocol.

## Concept

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

## Protocol

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

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

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

## Interface

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

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

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

## Plugin Discovery

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

## Built-in Hooks

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

## Use Cases

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

## Future

Consider MCP integration for richer plugin capabilities.


Merge: gt-3x0z.3

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


Digest: mol-deacon-patrol

Patrol 17: Mayor OK, 11 sessions


gt uninstall: Clean removal of Gas Town harness

Add 'gt uninstall' command to cleanly remove a Gas Town installation.

Should:
- Remove harness directory structure
- Optionally preserve rigs/data with --keep-data flag
- Warn about running sessions
- Clean up any global config references


Add --fart as easter egg alias for bd mol bond

Add a hidden alias for the bond command:

```bash
bd mol fart mol-polecat-work --wisp
# equivalent to:
bd mol bond mol-polecat-work --wisp
```

## Context
The fart joke: instantiating a proto can produce either:
- A Mol (solid/substantial output)
- A Wisp (gas/ephemeral output)

## Implementation
- Add 'fart' as an alias in the mol subcommand
- No documentation needed (easter egg)
- Maybe a fun message: 'Bonding molecule...' or similar

Low priority, just for fun.


Digest: mol-deacon-patrol

Patrol OK: 8 polecats, 4 witness/refineries up


Digest: mol-witness-patrol

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


Agent monitoring and status inference

Agent monitoring with status inference from activity, like PGT.

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

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

## Activity Detection

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

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol 4: all clear


Digest: mol-deacon-patrol

Patrol 16: all clear


Evaluate pending async gates

Evaluate pending async gates.

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

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

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

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

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

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

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


Maintenance: Regular cleanup of closed MR/gate beads

Closed merge-request and gate beads accumulate over time. Need regular cleanup.

## Cleanup Candidates
- type=merge-request with status=closed
- type=gate with status=closed
- type=molecule with status=closed (completed workflows)

## Options
1. **Deacon patrol step** - squash closed MRs periodically
2. **Refinery post-merge** - close and tombstone MR after successful merge
3. **bd doctor check** - warn when stale MR count exceeds threshold

## Consideration
Keep some audit trail? Or just tombstone after N days?


gt swarm start: Does not spawn polecat sessions

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

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

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


Direct test

Testing direct bd create


Digest: mol-deacon-patrol

Patrol 19: All agents healthy


Digest: mol-deacon-patrol

Patrol complete: reset 3 orphaned polecats (furiosa, nux, slit) to idle, all agents healthy


Digest: mol-deacon-patrol

P8: stable


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

Set up Go project structure with CLI framework.

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

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


Digest: mol-deacon-patrol

Patrol 18: all clear


Digest: mol-deacon-patrol

Patrol 5: nominal


mol-witness-patrol

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

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

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

This molecule uses dynamic bonding to spawn mol-polecat-arm for each worker,
enabling parallel inspection with a fanout gate for aggregation.

## The Christmas Ornament Shape

```
                     ★ mol-witness-patrol (trunk)
                    /|\
          ┌────────┘ │ └────────┐
       PREFLIGHT  DISCOVERY  CLEANUP
          │          │           │
      inbox-check  survey    aggregate (WaitsFor: all-children)
      check-refnry   │       save-state
      load-state     │       generate-summary
                     ↓       context-check
             ┌───────┼───────┐  burn-or-loop
             ●       ●       ●   mol-polecat-arm (dynamic)
            ace     nux    toast
```


Verify gt daemon start/stop works

Verify the daemon orchestrator:

```bash
gt daemon start   # Should start and stay running
gt daemon status  # Should show running
gt daemon stop    # Should stop cleanly
```

The daemon is responsible for:
- Respawning the deacon when it exits (context exhaustion)
- Heartbeat monitoring
- Clean shutdown coordination

Test: Start, verify deacon session appears, stop, verify clean exit.


gt handoff deadlock at handoff.go:125

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


Digest: mol-deacon-patrol

Patrol 20: All healthy, handoff triggered


Digest: mol-deacon-patrol

Patrol 8: nominal


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.


Test Polecat Arm

Test child for bonding pattern


Architecture: Decentralized rig structure with per-rig agents

## Decision

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

## Town Level Structure

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

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

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

## Key Decisions

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

## Role Detection

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

## Migration from PGT

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


Analysis: Beads database size and hygiene strategy

Audit beads database size and plan medium-term hygiene.

## Questions
1. How many issues total (including tombstones)?
2. Size of issues.jsonl?
3. Growth rate per day/week?
4. What percentage are tombstones?

## Hygiene Topics
- Compaction: squash tombstones periodically
- Archival: move old closed issues to archive file
- Pruning: delete truly stale items (test beads, old MRs)
- Sync efficiency: large JSONL = slow sync

## Action Items
- [ ] Count total issues by status
- [ ] Count tombstones
- [ ] Measure file sizes
- [ ] Propose hygiene schedule


Test Patrol Parent

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

Original description:
Test parent for Christmas Ornament pattern


test pin fix


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Nudge newly spawned polecats

Nudge newly spawned polecats that are ready for input.

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

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

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

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

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

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

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

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Merge: gt-h5n.5

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


Digest: mol-deacon-patrol

Patrol 17: nominal


Mail inbox from witness/refinery dirs shows Mayor inbox

When running `gt mail inbox` from the witness or refinery directories, it shows the Mayor's inbox instead of the agent's own inbox.

Reproduction:
```
$ cd ~/gt/beads/witness && gt mail inbox
📬 Inbox: mayor/ (1 messages, 1 unread)
  ● 🤝 HANDOFF: Swarm session complete...
```

Expected: Should show beads/witness inbox

Likely cause: The cwd-based identity resolution isn't recognizing witness/refinery as valid mail identities, so it falls back to Mayor.


mol-deacon-patrol


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

Patrol 3: all healthy, no work


CloudRun persistent connections: HTTP/2 keepalive

## Overview

Implement persistent HTTP/2 connections to keep Cloud Run containers warm.

## Problem

Cloud Run has cold start latency when scaling from 0. Persistent connections keep containers warm.

## Implementation

```go
type PersistentConnectionManager struct {
    serviceURL string
    conn       net.Conn
    client     *http2.ClientConn
    mu         sync.Mutex
    lastUsed   time.Time
    keepAlive  time.Duration
}

func (m *PersistentConnectionManager) GetConnection() (*http2.ClientConn, error) {
    m.mu.Lock()
    defer m.mu.Unlock()

    // Reuse existing connection if healthy
    if m.client != nil && m.client.CanTakeNewRequest() {
        m.lastUsed = time.Now()
        return m.client, nil
    }

    // Create new connection
    return m.dial()
}

func (m *PersistentConnectionManager) keepAliveLoop() {
    ticker := time.NewTicker(m.keepAlive / 2)
    for range ticker.C {
        m.mu.Lock()
        if time.Since(m.lastUsed) > m.keepAlive {
            // Connection idle too long, close it
            m.close()
        } else {
            // Send ping to keep alive
            m.ping()
        }
        m.mu.Unlock()
    }
}
```

## Integration with CloudRunOutpost

```go
type CloudRunOutpost struct {
    // ...existing fields...
    connMgr *PersistentConnectionManager
}

func (o *CloudRunOutpost) Spawn(...) {
    conn, err := o.connMgr.GetConnection()
    // Use connection for work dispatch
}
```

## Config

```yaml
outposts:
  - name: cloudrun-burst
    type: cloudrun
    # ...
    keep_alive: 5m  # Keep connection warm for 5 minutes
```

## Files

- `internal/cloudrun/connection.go`

## Dependencies

Depends on: gt-9a2.8 (basic CloudRunOutpost)


Test Patrol Parent


Digest: mol-deacon-patrol

Patrol 19: all healthy


gt sling command implementation

Implement the gt sling command for handoff with attached work.

## Command Signature

```bash
gt sling <bead-id> [-s subject] [-m message]
```

## Behavior

1. Validate the bead exists: bd show <bead-id>
2. Create wisp on agents hook:
   - File: .beads-wisp/hook-<agent>.wisp.yaml
   - Content: bead_id, slung_at, optional context
3. Optionally send handoff mail with subject/message
4. Exit cleanly (or signal restart)

## Wisp Format

```yaml
type: slung-work
bead_id: gt-xxx
slung_at: 2025-12-24T...
slung_by: crew/joe
context: "Optional message"
```

## Files to Create/Modify

- cmd/gt/sling.go (new)
- internal/wisp/wisp.go (may need creation)
- internal/wisp/hook.go (hook reading)

## Notes

- Keep it simple - this is connector code
- The wisp is burned after pickup
- Sling should work for any role (crew, polecat, deacon)


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


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.


gt sling/handoff fails: slashes in agent identity create invalid hook paths


Verify refinery patrol loop executes

Verify refineries run their patrol formula:

1. Check refinery session: `gt session status gastown/refinery`
2. If not running: `gt session start gastown/refinery`
3. Watch refinery: `tmux attach -t gt-gastown-refinery`
4. Verify it handles:
   - Checking for pending MRs
   - Processing merge queue
   - Reporting results

Test for both rigs: gastown and beads.


Add 'wit' alias for witness command

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


mol-polecat-work

Full polecat lifecycle from assignment to decommission.

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

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


Digest: mol-deacon-patrol

Patrol 11: All healthy, dave now running


Merge: gt-ay1r

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


Digest: mol-deacon-patrol

Patrol 12: clear


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


gt crew add: Create crew workspace

Implement 'gt crew add <name> [--rig <rig>]' command:
- Clone repo into <rig>/crew/<name>/
- Create feature branch (optional, or stay on main)
- Register for mail delivery
- Initialize CLAUDE.md with crew worker prompting
- Do NOT register with witness (user-managed)


Digest: mol-deacon-patrol

Patrol 17: All clear


🤝 HANDOFF: Timing fixes applied

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


Digest: mol-deacon-patrol

Patrol 19: Nominal


Test message

Testing GGT mail via beads


Test Patrol for Bonding

Parent issue for mol bond CLI test


Add crew auto-start config to gt start

gt start needs a config file to specify:
- Which crew members auto-start per rig
- Which rigs to auto-start (instead of requiring --all or --rigs flags)

Requested defaults:
- beads rig: dave
- gastown rig: max, joe

This would allow 'gt start' to bring up the configured crew without manual flags.


Polecat template: clarify work status commands (bd list vs gt mol status)

Template shows 'bd list --status=in_progress' for checking work, but polecats should probably use 'gt mol status' instead (or in addition). Clarify the right approach for polecats to check their current work assignment.


Digest: mol-deacon-patrol

Patrol 3: inbox clear, all healthy


Digest: mol-deacon-patrol

Patrol 15: All healthy


Inconsistent error wrapping patterns

Error handling is inconsistent across the codebase:

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

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


Test Patrol Parent

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

Original description:
Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Patrol 16: routine


Digest: mol-deacon-patrol

Patrol cycle 9: nominal


Pinned beads should appear first in mail inbox

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

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

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

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

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

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


mol-witness-patrol

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

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

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

## The Christmas Ornament Shape

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

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

## Phases

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

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

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

## Dynamic Arms

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

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

## Activity Feed

This design enables real-time visibility:

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

## Storage

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

## Dependencies

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

Labels: [template, christmas-ornament]


gt done: Missing command referenced in polecat docs


Replace WaitForClaudeReady with gt peek for steady-state agent observation

## Problem

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

## Architectural Fix

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

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

## Implementation

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


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.


Patrol hygiene: Witness/Refinery/Deacon inbox cleanup

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

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

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

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

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

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


Digest: mol-deacon-patrol

Patrol cycle 18: nominal


Digest: mol-deacon-patrol

Patrol 17: routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol: slit handoff (landing protocol), polecats cleaned (0 now), 4 witness/refineries up


Tmux session scanner for running agents

Scan tmux for running Gas Town agent sessions.

## Deliverables

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

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

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

## Location
internal/discovery/tmux.go

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


Handle callbacks from agents

Handle callbacks from agents.

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

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

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