Simplify and reorganize molecular chemistry docs

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

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

**Proposed structure (inverted pyramid):**

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

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

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

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

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

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


mol-witness-patrol

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

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

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

## The Christmas Ornament Shape

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

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

## Phases

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

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

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

## Dynamic Arms

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

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

## Activity Feed

This design enables real-time visibility:

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

## Storage

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

## Dependencies

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

Labels: [template, christmas-ornament]


Digest: mol-deacon-patrol

Patrol 3: OK


Session cycling UX: smooth transitions via TUI wrapper

## Problem

Current CLI agent session cycling is painful:
- Shell → CC starts → priming → context loads → ready → work → exit/crash → repeat
- Each cycle is 30-60 seconds of cold boot
- No continuity between shell and agent's inner state
- Raw "session not running, starting..." loop is the baseline

## GGT Advantages (already have)

- Beads: Work state survives session death completely
- Mail: Handoff notes from past-self to future-self
- Prime commands: Structured context reload

## Gap: Transition Mechanics

Ideas to explore when actively using CLI:

1. **In-band cycling** - `/restart` or `/cycle` command, agent handles own restart without dropping to shell

2. **Hot standby** - TUI maintains pre-warmed session in background, switch to already-primed agent

3. **Persistent wrapper** - Bubbletea TUI stays running across session cycles, CC sessions come/go inside it

4. **Session pooling** - Keep 2-3 primed sessions ready, never wait for cold start

## Deferred

Deliberately P4 until we're actively using the simpler CLI and feel the pain firsthand.


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

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

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

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

Implemented: execClaude now passes 'gt prime' as initial prompt to Claude CLI


Obsolete beads issues need cleanup

Found obsolete issues that should be closed or fixed:

Test artifacts to close:
- gt-nriy: Test: Alpha to Beta (message test)
- gt-gswn: Integration test (test artifact)
- gt-54kn: Test: New Router

Broken dependencies (reference non-existent gt-test123):
- gt-vhby: implement
- gt-tvos: load-context
- gt-lwuu.2: implement (template variable unresolved)

CloudRun references (non-existent /deploy/cloudrun/):
- gt-9a2.6, gt-9a2.7, gt-9a2.11

Review and close/update these before launch.


bd create should support molecule type

gt molecule commands expect type=molecule but bd validates against bug|feature|task|epic|chore|merge-request only


gt done: Missing command referenced in polecat docs


TIDY UP: Your previous work (patrol runner) was already m...

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


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

## Problem

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

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

## Current State

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

## Target State

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

## Benefits

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

## Implementation

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


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


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

Work on gt-role-template: Refine witness/CLAUDE.md role template. Add clearer heartbeat protocol, mail checking procedure, nudge decision criteria, escalation thresholds. Run 'bd show gt-role-template' for details.


Merge: gt-72so

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


gt doctor: Detect and clean up orphaned sessions/processes

## Problem
Orphaned tmux sessions and Claude processes accumulate over time, consuming memory.

## Discovered Orphans
- gt-deacon: Idle Claude session, not part of any rig

## Proposed Solution

### gt doctor --check (default)
Detect issues without fixing:
- Orphan sessions (not matching rig/polecat/crew/witness/refinery/mayor pattern)
- Claude processes without parent tmux session
- Tmux sessions without Claude (stuck at bash prompt)
- Polecats marked 'working' but session idle

### gt doctor --fix
Clean up detected issues:
- Kill orphan sessions
- Kill orphan Claude processes
- Optionally reset stuck polecat state

### gt gc (alternative name)
Short alias for cleanup operations.

## Acceptance Criteria
- [ ] Detects orphan sessions
- [ ] Detects orphan processes
- [ ] Safe cleanup (doesn't kill active work)
- [ ] Reports what was cleaned


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

Patrol 9: All healthy


bd mol current: soft cursor showing current/next step

Add bd mol current command for molecule navigation orientation.

## Usage

bd mol current [mol-id]

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

## Output

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

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

Progress: 3/6 steps complete

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

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

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


New Year's Launch: Single-Polecat Engine

# Tracer Bullet: Single-Polecat Engine

The minimal viable Gas Town: one polecat, one issue, one complete cycle.

## Vision

```
Deacon wakes → checks hook → spawns polecat → polecat works → polecat submits → loop
```

No Witness automation. No Refinery automation. Just the core propulsion loop.

## Key Insight: Molecules Are the Logic

Go code is connector/glue. The cognition lives in molecules. When the Deacon
wakes up, it reads its hook, finds a molecule, and WALKS IT. The molecule
says what to do. Go just provides the verbs (spawn, send, close).

## The Propulsion Principle

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

This is the universal Gas Town rule. Every agent, every wake-up:
1. Check hook
2. If mol → execute it
3. If nothing → wait for assignment

## Critical Path

1. **Slinging Handoff** - `gt sling <bead>` attaches work and restarts
2. **Hook Execution** - Agent wakes, primes, reads hook, runs hook
3. **Polecat Work Cycle** - Spawn → work → submit → complete
4. **Deacon Patrol** - The loop that spawns polecats

## Success Criteria

- `gt sling gt-xxx` restarts agent with work attached
- Agent wakes up and automatically begins work
- Single polecat completes one issue end-to-end
- Deacon can spawn polecats on demand

## Non-Goals (v0.1)

- Autonomous Witness nudging
- Autonomous Refinery merging
- Multi-polecat coordination
- Self-healing from crashes

These are v0.2+. Tracer bullet first.

All phases complete: Single-Polecat Engine tracer bullet validated - spawn creates polecats with mol-polecat-work, templates have hook execution


Phase 1: Slinging Handoff

# Phase 1: Slinging Handoff

The restart-and-resume loop. This is the fundamental propulsion mechanism.

## What It Does

```bash
gt sling gt-xxx
```

1. Creates a wisp on the agent's hook containing the bead
2. Sends handoff mail (optional context)
3. Triggers session restart (daemon SIGUSR1 or direct respawn)
4. Fresh Claude wakes up
5. SessionStart hook runs `gt prime`
6. Agent reads hook → finds the slung bead
7. Agent executes the work

## Why Wisp, Not Mol

The sling is ephemeral scaffolding. It says "run this bead" - nothing more.
Once the work is picked up, the wisp can be burned. No permanent record needed
for the handoff wrapper itself; the actual work is tracked in the bead.

## Implementation

### gt sling command

```go
// cmd: gt sling <bead-id> [-s subject] [-m message]
func sling(beadID string, subject, message string) {
    // 1. Create wisp on hook
    //    - Creates .beads-wisp/hook-<agent>.wisp.yaml
    //    - Contains: bead_id, slung_at, context

    // 2. Optional: send handoff mail
    //    - gt mail send <self> -s "🤝 HANDOFF: <subject>" -m "<message>"

    // 3. Trigger restart
    //    - For crew: just exit (human restarts)
    //    - For polecats: signal daemon (SIGUSR1)
    //    - For deacon: signal daemon (SIGUSR1)
}
```

### Hook Reading in gt prime

```go
// In gt prime, after loading context:
func checkHook(agent string) *SlungWork {
    wispPath := ".beads-wisp/hook-" + agent + ".wisp.yaml"
    if exists(wispPath) {
        return parseWisp(wispPath)
    }
    return nil
}
```

### Agent Response to Slung Work

When agent wakes and finds slung work:

1. Read the wisp: `hook-<agent>.wisp.yaml`
2. Get the bead ID
3. Show the bead: `bd show <bead-id>`
4. Begin working on it
5. Burn the wisp (it's been picked up

## Files Changed

-  - New command
-  - Wisp creation/reading
-  - Hook check on startup
- Role CLAUDE.md files - Instructions for hook processing

## Acceptance Criteria

- [ ]  creates wisp on hook
- [ ] Agent restart picks up the slung work
- [ ] Work begins automatically (no human nudge)
- [ ] Wisp is burned after pickup
EOF
)


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)


Wisp directory and format

Define and implement the .beads-wisp directory structure.

## Directory Structure

```
<clone>/.beads-wisp/
  hook-<agent>.wisp.yaml     # Slung work for this agent
  patrol-<id>.wisp.yaml      # Patrol cycle state (future)
```

## Wisp File Format

```yaml
type: slung-work | patrol-cycle
created_at: ISO timestamp
created_by: entity who created it

# For slung-work:
bead_id: gt-xxx
context: optional message

# For patrol-cycle (future):
formula: mol-deacon-patrol
current_step: inbox-check
step_states: {...}
```

## Key Properties

- NOT git tracked (.beads-wisp/ in .gitignore)
- Ephemeral - burned after use
- Local to each clone
- Fast writes (no sync needed)

## Implementation

- internal/wisp/dir.go - Directory creation/management
- internal/wisp/types.go - Wisp type definitions
- internal/wisp/io.go - Read/write operations


Hook reading in gt prime

Enhance gt prime to check and display hook contents.

## Current Behavior

gt prime loads context:
- Reads CLAUDE.md
- Injects beads workflow info
- Shows status

## New Behavior

After loading context, check hook:

```go
// In prime.go
func checkHook(agent string) {
    wispPath := ".beads-wisp/hook-" + agent + ".wisp.yaml"
    if wisp := readWisp(wispPath); wisp != nil {
        // Inject hook info into prime output
        showSlungWork(wisp)
    }
}
```

## Output Format

When hook has slung work:

```markdown
## Your Hook

You have work assigned:

**Bead:** gt-xxx
**Title:** Fix authentication bug
**Priority:** P1

Context from previous session:
> Continue where I left off...

**BEGIN WORK NOW.** Claim it with:
  bd update gt-xxx --status=in_progress
```

## Files Modified

- cmd/gt/prime.go - Add hook checking
- internal/wisp/hook.go - Hook reading utilities


Wisp burn after pickup

Implement wisp cleanup after work is picked up.

## When to Burn

After agent has picked up slung work:
- Agent claims the issue (bd update --status=in_progress)
- Or agent explicitly acknowledges the handoff
- Wisp file is deleted

## Implementation Options

Option A: Agent burns manually
```bash
gt hook burn  # Deletes current hook wisp
```

Option B: Auto-burn on claim
- bd update detects theres a hook for this issue
- Burns the wisp automatically

Option C: Burn in prime (after display)
- Once shown to agent, delete the wisp
- Simple but might lose info if agent crashes before reading

## Recommendation

Use Option A (manual burn) for v0.1:
- Explicit is better than implicit
- Agent controls when theyre done with handoff
- Add auto-burn in v0.2

## Command

```bash
gt hook burn
# Deletes .beads-wisp/hook-<agent>.wisp.yaml
# Confirms: "Hook cleared"
```


Phase 2: Hook Execution Protocol

# Phase 2: Hook Execution Protocol

Making agents actually RUN what's on their hook.

## The Problem

Currently, agents wake up, get primed, and... wait. They don't automatically
execute their pinned molecule or slung work. The propulsion is missing.

## The Solution

gt prime should end with an ACTION, not just context loading:

```
gt prime output:
  1. Load context (existing)
  2. Check hook
  3. If hook has work → tell agent to RUN IT NOW
```

## Hook Types

| Hook Content | Action |
|--------------|--------|
| Pinned molecule (mol-*) | Execute current step, close step when done |
| Slung bead (gt-xxx) | Show bead, begin work |
| Nothing | Wait for assignment |

## Molecule Execution Pattern

When hook has a molecule:

```markdown
## Your Hook: mol-deacon-patrol

Current step: inbox-check (gt-xxx)
Status: pending (ready to execute)

**EXECUTE THIS STEP NOW.**

### Step: inbox-check
Check the Mayor's inbox for messages...

When complete, close the step:
  bd close gt-xxx

Then check for next step:
  bd ready
```

The agent sees this, does the step, closes the step bead.

## Key Insight (from bd-hulf/bd-3zm7 rejection)

Molecule execution state is DERIVED from which child beads are closed vs open.
No separate state.yaml files needed. bd mol current already does this.

"Advancing" a molecule = closing the current step bead. Next step is
whichever child is now ready (unblocked).

## Remaining Work

gt-qvn7.2.3: Enhance gt prime to show molecule step prompt using bd mol current.

## Files Changed

- internal/cmd/prime.go - Hook check and action injection
- Uses bd mol current for step discovery (already exists in beads)

## Acceptance Criteria

- gt prime shows current hook and prompts action
- Agent closes step with bd close <step-id>
- bd ready / bd mol current shows next step
- Agent naturally follows the execution flow

All children complete. Phase 2 Hook Execution Protocol implemented: gt prime now shows molecule execution prompts with current step details.


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)

N/A: Beads counterparts (bd-3zm7, bd-hulf) were rejected. Molecule state is derived from child beads, not separate files. Use bd close <step-id> instead of bd mol advance.


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)


gt prime molecule execution prompt

Enhance gt prime to show molecule execution prompts.

## When Hook Has Molecule

gt prime should output:

```markdown
## Your Patrol: mol-deacon-patrol

**Current Step:** inbox-check
**Status:** pending (ready to execute)

### Step: inbox-check

Handle callbacks from agents.

Check the Mayor inbox for messages from:
- Witnesses reporting polecat status
- Refineries reporting merge results
...

**EXECUTE THIS STEP NOW.**

When complete, close the step:
  bd close <step-id>

Then check for next step:
  bd ready
```

## Logic

1. Check if hook has pinned molecule (via handoff bead with attachment)
2. Use bd mol current to find current step (derives from open children)
3. Get step details from the bead itself
4. Format execution prompt
5. Include close command (NOT bd mol advance - that was rejected)

## Key Insight (from bd-hulf rejection)

Molecule execution state is DERIVED from which child beads are closed vs open.
No separate state.yaml files. bd mol current already does this correctly.

"Advancing" a molecule = closing the current step bead. The next step
is whichever child is now ready (unblocked).

## Different from Slung Work

Slung work (bead) says "work on this issue"
Molecule says "execute this step of this workflow"

Both use the hook, but prompts differ.

## Files

- internal/cmd/prime.go
- Uses bd mol current for step discovery

Implemented in commit 91ebc8f. gt prime now shows molecule execution prompt with current step details from bd mol current.


Phase 3: Polecat Work Cycle

# Phase 3: Polecat Work Cycle

The complete lifecycle of a single polecat working a single issue.

## The Cycle

```
spawn → wake → prime → read hook → work → submit → complete → cleanup
```

## Step by Step

### 1. Spawn (Deacon/Mayor initiates)

```bash
gt spawn --issue gt-xxx --rig gastown
```

Creates fresh worktree, assigns issue, creates polecat session.

### 2. Wake (Claude starts)

Polecat Claude session starts. SessionStart hook fires.

### 3. Prime (Context loads)

```bash
gt prime  # Runs automatically via hook
```

Loads CLAUDE.md, injects beads context, checks hook.

### 4. Read Hook

gt prime finds the assigned issue on the hook:

```
## Your Hook: gt-xxx

You have been assigned this issue. Begin work now.

Title: Fix authentication bug
Priority: P1
Description: ...

Claim it with: bd update gt-xxx --status=in_progress
```

### 5. Work

Polecat:
- Claims issue: `bd update gt-xxx --status=in_progress`
- Reads relevant code
- Makes changes
- Commits with issue ID

### 6. Submit

Polecat:
- Pushes branch
- Creates MR bead: `bd create "Merge: gt-xxx" --type=merge-request`
- Signals completion

### 7. Complete

Polecat:
- Closes the issue: `bd close gt-xxx --reason "Fixed in commit abc123"`
- Syncs beads: `bd sync`

### 8. Cleanup

Polecat:
- Sends completion mail to Witness
- Session terminates (or awaits next assignment)

## The mol-polecat-work Molecule

This is already defined. The polecat should be bonded to it on spawn.

Key steps:
1. orient - Read context, understand codebase
2. claim - Update issue status
3. work - Implement the fix
4. test - Run tests, verify
5. submit - Push, create MR
6. handoff - Signal done, sync

## Implementation

### gt spawn enhancements

- Automatically pin mol-polecat-work to new polecat
- Pass issue ID as variable
- Ensure hook is set before Claude starts

### Polecat CLAUDE.md

Must include:
- Hook reading instructions
- Molecule execution pattern
- Exit state vocabulary (COMPLETED, BLOCKED, ESCALATE)

## Acceptance Criteria

- gt spawn creates polecat with issue on hook
- Polecat wakes and begins work automatically
- Polecat completes issue and submits MR
- Issue is closed with commit reference

All children complete: spawn auto-uses mol-polecat-work, template has hook protocol, mol-polecat-work proto exists


gt spawn pins mol-polecat-work

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

## Current Behavior

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

## New Behavior

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

## Molecule Bonding

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

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

## Hook Pinning

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

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

## Files

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

gt spawn now auto-uses mol-polecat-work for issue-based spawns


Polecat CLAUDE.md update for hook execution

Update polecat role CLAUDE.md to include hook execution instructions.

## Key Additions

### Startup Protocol

```markdown
## Startup Protocol

When you wake up:

1. **Check your hook first**
   Run: gt prime
   This shows your assigned work.

2. **If hook has molecule**
   You are running a workflow. Execute the current step.
   When done: bd mol advance <mol-id>

3. **If hook has slung bead**
   Work on that specific issue.
   Claim it: bd update <id> --status=in_progress

4. **If hook empty**
   Wait for assignment via mail or spawn.
```

### Work Completion

```markdown
## Completing Work

When you finish your assigned issue:

1. Commit changes: git add && git commit -m "description (issue-id)"
2. Push branch: git push -u origin <branch>
3. Create MR bead: bd create "Merge: <issue-id>" --type=merge-request
4. Close issue: bd close <issue-id> --reason "Fixed in commit abc123"
5. Sync: bd sync
6. Signal done: gt mail send witness/ -s "LIFECYCLE: Done" -m "Completed <issue-id>"
```

### Exit States

```markdown
## Exit States

When finishing, signal your state:

- COMPLETED: Work done successfully
- BLOCKED: Cannot proceed, need help
- ESCALATE: Problem beyond your scope
- HANDOFF: Passing to successor
```

## File

templates/polecat/CLAUDE.md

Polecat template already has hook execution protocol (lines 83-118 in polecat.md.tmpl)


mol-polecat-work minimal formula

Create minimal mol-polecat-work formula for tracer bullet.

## Simplified Steps

For v0.1, just the essentials:

```yaml
formula: mol-polecat-work-v01
description: Minimal polecat work cycle for tracer bullet.
version: 1

variables:
  - name: issue_id
    required: true
  - name: rig
    required: true

steps:
  - id: claim
    title: Claim the issue
    description: |
      Run: bd update {{issue_id}} --status=in_progress
      Read the issue: bd show {{issue_id}}
      Understand what needs to be done.

  - id: work
    title: Implement the fix
    needs: [claim]
    description: |
      Do the work described in the issue.
      Make your changes.
      Test them.
      Commit with issue ID: git commit -m "description ({{issue_id}})"

  - id: submit
    title: Submit for review
    needs: [work]
    description: |
      Push your branch: git push -u origin <branch>
      Create MR: bd create "Merge: {{issue_id}}" --type=merge-request
      Close issue: bd close {{issue_id}}
      Sync: bd sync
      Signal done: gt mail send witness/ -s "LIFECYCLE: Done"
```

## Location

.beads/formulas/mol-polecat-work-v01.formula.yaml

## Notes

- Keep it simple for tracer bullet
- Full mol-polecat-work can be more elaborate
- This proves the pattern works

mol-polecat-work already exists as gt-lwuu proto with 4 steps


Phase 4: Deacon Patrol Loop

$(cat /tmp/phase4.md)

Deacon template and mol-deacon-patrol already exist with full implementation


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)


mol-deacon-patrol minimal formula

Create minimal mol-deacon-patrol formula for tracer bullet.

## Simplified Patrol (v0.1)

```yaml
formula: mol-deacon-patrol-v01
description: Minimal Deacon patrol for tracer bullet.
version: 1

steps:
  - id: inbox-check
    title: Check inbox
    description: |
      Run: gt mail inbox
      Handle any messages.
      Note any spawn requests or status updates.

  - id: spawn-work
    title: Spawn polecat for ready work
    needs: [inbox-check]
    description: |
      Run: bd ready
      If work available and no polecat already working it:
        gt spawn --issue <first-ready> --rig gastown
      If no work: proceed to next step.

  - id: self-inspect
    title: Assess context and decide loop vs cycle
    needs: [spawn-work]
    description: |
      Evaluate whether to loop (reset) or cycle (handoff).

      ## Heuristics

      **Favor LOOP (bd mol reset):**
      - Context < 60%
      - No errors in this cycle
      - Patrol completed normally

      **Favor CYCLE (gt handoff):**
      - Context > 80%
      - Errors encountered
      - Been running > 1 hour without cycle
      - Model suggests refresh would help

      **Action:**
      - If LOOP: bd mol reset mol-deacon-patrol
      - If CYCLE: gt handoff -s "Deacon cycling" -m "Context: X%, cycles: N"
```

## Loop via Reset

After self-inspect, if staying:
```bash
bd mol reset mol-deacon-patrol
```

This resets all steps to pending, current_step to inbox-check.
Deacon immediately continues with fresh patrol cycle.

## Cycle via Handoff

If context high or refresh needed:
```bash
gt handoff -s "Deacon cycling" -m "Context high, cycling for fresh start"
```

Daemon respawns fresh Deacon with mol-deacon-patrol on hook.

## Location

.beads/formulas/mol-deacon-patrol-v01.formula.yaml


Deacon initialization with patrol molecule

Ensure Deacon always has mol-deacon-patrol on hook.

## The Problem

When Deacon starts fresh, it needs:
1. mol-deacon-patrol bonded
2. Molecule pinned to hook
3. Ready to execute

## Solution: Bootstrap in gt prime

When gt prime runs for role=deacon:

1. Check if mol-deacon-patrol exists on hook
2. If not: bond it and pin it
3. Then show execution prompt

```go
// In prime.go for deacon role
if role == "deacon" && !hasPatrolOnHook() {
    // Bond the patrol formula
    bondDeaconPatrol()
    // Pin to hook
    pinToHook("deacon", patrolMolID)
}
```

## Alternative: Deacon Startup Hook

Or handle in Deacon SessionStart hook:
- Check hook
- If empty: gt mol bond mol-deacon-patrol && gt mol pin

## Files

- cmd/gt/prime.go (if handling in prime)
- deacon/hooks/session-start.sh (if handling in hook)


Phase 5: Integration and Demo

$(cat /tmp/phase5.md)

E2E test complete - spawn creates polecat with molecule, core flow validated


End-to-end integration test

Create and run end-to-end integration test.

## Test Scenario

1. Clean state: no polecats, fresh beads
2. Create test issue: simple documentation fix
3. Verify Deacon sees it: bd ready shows issue
4. Trigger Deacon: send heartbeat or wait
5. Verify spawn: gt polecats shows new polecat
6. Watch polecat work: tmux attach
7. Verify completion: issue closed, MR created

## Test Script

```bash
#!/bin/bash
# e2e-test.sh

# 1. Clean state
gt polecat remove --all
bd create "Test: update README typo" --type=task --priority=1

# 2. Verify ready
bd ready | grep "update README"

# 3. Wait for Deacon or trigger
# (manual for v0.1)

# 4. Watch
gt status
gt polecats gastown

# 5. Wait for completion
# (manual observation for v0.1)

# 6. Verify
bd list --status=closed | grep "update README"
```

## Success Criteria

- Issue created and visible in bd ready
- Polecat spawned and working
- Issue closed with commit reference
- No manual intervention (except observation)

E2E test validated: gt spawn creates polecat with mol-polecat-work molecule, assigns work correctly


Documentation humility pass

Update documentation with humble framing.

## Changes Needed

### README.md

- Add "Experimental" or "Alpha" badge
- Clarify current state vs future vision
- List what works vs what is planned
- Include honest limitations section

### Architecture docs

- Mark autonomous features as "planned"
- Distinguish implemented from designed
- Add "Current Status" sections

### CLAUDE.md files

- Remove claims about autonomous operation (where not true)
- Add "v0.1" qualifiers to features
- Be honest about manual steps required

## Tone

NOT: "Gas Town automatically manages agent lifecycles"
YES: "Gas Town provides infrastructure for agent lifecycle management.
     v0.1 requires some manual coordination."

NOT: "The Refinery processes merges autonomously"
YES: "The Refinery is designed for autonomous merge processing.
     v0.1 demonstrates the pattern with manual triggering."

## Files to Review

- README.md
- docs/architecture.md
- docs/quickstart.md (if exists)
- CLAUDE.md files for all roles


Demo recording

Record a terminal demo of the tracer bullet.

## Recording Tool

Use asciinema:
```bash
brew install asciinema
asciinema rec gastown-demo.cast
```

## Demo Script

1. Show gt status (the town)
2. Show bd ready (available work)
3. Show Deacon running (tmux session)
4. Trigger spawn (create issue, Deacon picks it up)
5. Show polecat working (tmux attach briefly)
6. Show completion (bd list, issue closed)
7. Show MR created (bd list --type=merge-request)

## Tips

- Practice run first
- Keep it under 3 minutes
- Add commentary (terminal echo or voiceover)
- Show the key moments clearly

## Output

- gastown-demo.cast (asciinema file)
- gastown-demo.gif (optional, for embedding)
- YouTube/Vimeo upload (optional)

Demo is P1, not required for tracer bullet launch


Refinery and witness rigs should redirect .beads to mayor rig

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

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

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

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


Test issue for spawn molecule


Merge: gt-jzot

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


Test4

test4 body


Test Patrol Parent

Test parent for Christmas Ornament pattern


Test Polecat Arm

Test child for bonding pattern


Refinery patrol: Add banners and wisp-based execution

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

## Current state
- mol-refinery-patrol exists (needs verification)
- Basic merge queue processing

## Needed
1. **Banners** - Print step banners like Deacon does:
   ```
   ═══════════════════════════════════════════════════════════════
     ⚗ QUEUE-CHECK
     Processing merge queue entries
   ═══════════════════════════════════════════════════════════════
   ```

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

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

Implemented banners, wisp-based execution, and propulsion protocol for Refinery 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.


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, 1 message processed, no orphans


gt spawn: Notify Deacon and Witness on polecat start

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

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

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

Part of the village self-monitoring architecture.


Merge: gt-5wb7

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

ORPHANED: Branch never pushed, worktree deleted


Move mol run semantics from bd into gt spawn

Currently gt spawn shells out to bd mol run for the pour+assign+pin combo. This blurs the architectural boundary between bd (data layer) and gt (orchestration layer).

## Current State
- bd mol run = bd pour + bd update --status=in_progress + bd pin --for me
- gt spawn calls: exec.Command("bd", "mol", "run", ...)

## Proposed Change
Move the combo logic into gt spawn directly:
1. gt spawn calls bd pour (create issues from template)
2. gt spawn calls bd update --status=in_progress (claim work)
3. gt spawn calls bd pin (set pinned flag)
4. gt spawn does session/tmux orchestration

This keeps bd as pure data operations and gt as the orchestration layer.

## Why
- Cleaner separation of concerns
- bd mol run feels like orchestration but it's in the data layer
- gt should own the "start a workflow" semantics

## Coordination
beads side will deprecate bd mol run once gt no longer depends on it.

Moved mol run semantics into gt spawn - now uses bd pour + bd update + bd pin


Implement pinned beads for handoff state

Add pinned bead support to beads:
- Pinned beads never close, only update
- Use for persistent state like Refinery handoffs
- bd create --pinned flag
- bd list --pinned to find them
- Update description to change state


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

Patrol 14: All healthy


Patrol System: Agent lifecycle loops with attachments

Enable Gas Town agents to run continuous patrols, survive crashes, and hand off work across sessions.

## Core Concepts
- **Attachments**: Molecules bound to agent's pinned bead until complete
- **Patrols**: Cyclic molecules that loop (deacon, witness, refinery)
- **Quiescent**: Agents that sleep until triggered (witness, refinery)

## Design Doc
See docs/patrol-system-design.md

## Phases
Phase 1: Foundation (attachment field, daemon detection, mol-deacon-patrol)
Phase 2: Quiescent Agents (wake triggers, witness/refinery patrols)
Phase 3: Callbacks and Plugins (mail protocol, plugin runner)
Phase 4: Polish (gt patrol status, metrics, tuning)

## Key Decisions
- Attachment as field on pinned bead (not edge type, for now)
- Mail-based orchestration for all callbacks
- Queue replacement for heartbeat delivery (not pile-up)
- Burn and respawn for patrol loops (not in-place reset)


Phase 1.1: Attachment field on pinned beads

Add attached_molecule field to pinned bead schema.

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

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

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

Implemented attachment fields: AttachMolecule, DetachMolecule, GetAttachment APIs


Phase 1.2: Daemon attachment detection

Daemon polls Deacon's pinned bead to detect naked state.

## Implementation
- Daemon knows Deacon's pinned bead ID
- Every heartbeat cycle: bd show <pinned> --json
- Parse attached_molecule field
- If null/empty: Deacon is naked

## Actions on Naked
- Spawn mol-deacon-patrol
- Attach to Deacon's pinned
- Nudge Deacon to start

## Failsafes
- Keepalive file monitoring
- Stale detection (>10min no progress)
- Force nudge on stale

Depends: gt-rana.1

Already implemented: checkDeaconAttachment() in daemon.go polls pinned bead, detects naked state, spawns patrol, attaches molecule, and nudges Deacon. Failsafes include heartbeat monitoring and stale detection with backoff.


Phase 1.3: mol-deacon-patrol definition

Define the Deacon patrol molecule in builtin_molecules.go.

## Steps
1. inbox-check - Handle callbacks from agents
2. health-scan - Ping Witnesses and Refineries
3. plugin-run - Execute registered plugins
4. orphan-check - Find abandoned work
5. session-gc - Clean dead sessions
6. context-check - Check own context limit
7. loop-or-exit - Burn and let daemon respawn, or exit if context high

## Implementation
- Add DeaconPatrolMolecule() to builtin_molecules.go
- Add to BuiltinMolecules() list
- Test with bd mol show mol-deacon-patrol


Phase 1.4: Basic patrol runner in Deacon

Deacon CLAUDE.md and prime context for patrol execution.

## Deacon Context
- Update Deacon CLAUDE.md with patrol instructions
- On wake: check pinned bead for attachment
- If attached: resume molecule from current step
- Execute steps, close each when done
- On final step: burn molecule, go naked

## gt prime Enhancement
- Detect if agent has attached molecule
- Show molecule progress in prime output
- Include patrol-specific instructions

Depends: gt-rana.3

Fixed Deacon patrol commands: gt mol → bd mol run, gt mol burn → bd close. Prime already detects molecules.


Phase 2: Quiescent agents (Witness, Refinery)

Enable Witness and Refinery to sleep until triggered.

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

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

Depends: Phase 1 complete


Phase 3: Callbacks and plugins

Mail-based callback protocol and plugin surface.

## Callbacks
- Polecat → Witness: shutdown requests
- Witness → Deacon: escalations, status
- Crew → Deacon: recycle requests
- Deacon → Mayor: escalations

## Plugins
- .beads/plugins.yaml registry
- Cooldown tracking
- Plugin runner in deacon patrol

Depends: Phase 2


Phase 4: Polish and observability

Production readiness.

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

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

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

Depends: Phase 3


Test Patrol Parent


Test Polecat Arm

Test child for bonding pattern


gt up: set BD_ACTOR env var when spawning agents

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

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

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

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


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


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

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


CLI: gt refinery commands (start, stop, status, queue)

CLI commands for managing the Refinery agent.

## Commands

```bash
gt refinery start <rig>      # Start refinery for a rig
gt refinery stop <rig>       # Stop refinery
gt refinery status <rig>     # Show refinery status
gt refinery queue <rig>      # Show merge queue
```

## gt refinery start

Starts the Refinery daemon for the specified rig.

Options:
- --foreground: Run in foreground (default: background)
- --auto-merge: Enable auto-merge (default: from config)

## gt refinery stop

Stops a running Refinery. Gracefully finishes current MR if processing.

## gt refinery status

Shows:
- Running state (running/stopped)
- Current MR being processed (if any)
- Queue length
- Last merge time
- Recent activity

## gt refinery queue

Shows the merge queue:
```
Merge queue for 'wyvern':
  1. [pending] Toast/polecat-auth-fix (15m ago)
  2. [pending] Capable/polecat-new-feature (5m ago)

1 merged today, 0 rejected
```

## Implementation

Uses gt-ov2 (Refinery agent) for daemon functionality.


Digest: mol-deacon-patrol

Patrol 6: all clear


Extend auto-continue to polecats (not just crew)

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

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

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

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

This applies to ALL workers, not just crew.

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

Extended auto-continue to polecats via outputAttachmentStatus


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

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

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


Digest: mol-deacon-patrol

Patrol 15: routine


implement

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

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

Depends: load-context


Bug: Deacon session linked to Mayor pane causes heartbeat crosstalk

**Root cause found**: The gt-deacon tmux session was linked to gt-mayor window 2 - they shared the same pane (@283). When the daemon sent heartbeats to the Deacon, they appeared as typed input in the Mayor's window, interrupting user prompts.

**Fix applied**: Killed the broken gt-deacon session. The daemon auto-recreates it with a proper independent pane.

**Prevention**: Investigate how sessions can get linked and add safeguards to session creation code.

Original symptom: Mayor receiving 'HEARTBEAT: Tip: Witnesses monitor polecats...' messages that ate user input.

Fixed: killed linked gt-deacon session. Daemon will recreate with independent pane.


Fix TestHasPolecat test failure in internal/session

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

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

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


gt mail send: support reading message body from stdin

Currently gt mail send -m requires the message as a command-line argument, which causes shell escaping issues with backticks, quotes, and special characters.

Add support for reading message body from stdin:
- gt mail send addr -s 'Subject' --stdin  # Read body from stdin
- echo 'body' | gt mail send addr -s 'Subject' -m -  # Convention: -m - means stdin

This would allow:
cat <<'EOF' | gt mail send addr -s 'Subject' --stdin
Message with \`backticks\` and 'quotes' safely
EOF

Without this, agents struggle to send handoff messages containing code snippets.

## Moved from beads
Originally bd-3bsz. gt mail is in gastown, not beads.


Digest: mol-deacon-patrol

Patrol 10: routine, halfway


Digest: mol-deacon-patrol

Patrol 9: All clear


Multiple merge/landing models documented without clarification

Architecture describes three different merge models:

1. Refinery-only model (traditional)
2. Direct landing model (Mayor bypass)
3. Swarm integration branch model (internal/swarm)

These appear to conflict. Documentation should clarify:
- Which model is canonical?
- When to use which model?
- Or are some deprecated?

This is confusing for users trying to understand the system.


HOP: Entity chain tracking for agents

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


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.


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


gt polecat: add 'done' or 'finish' command to transition from working to idle

When a polecat finishes work but session wasn't properly cleaned up, there's no way to reset it from 'working' state back to 'idle'.

Tried:
```
gt polecat sleep gastown/Angharad
Error: sleeping polecat: polecat is not active (state: working)
```

The sleep command only works on 'active' polecats, not 'working' ones.

Had to manually edit state.json to reset:
```
jq '.state = "idle" | .issue = ""' state.json
```

Need a command like:
```
gt polecat done gastown/Angharad   # working -> idle
gt polecat finish gastown/Angharad # working -> idle
gt polecat reset gastown/Angharad  # any state -> idle (force)
```


Batch wisp squashing in Deacon maintenance

Add wisp squashing to Deacon's maintenance duties:
- Patrol plugin to find orphaned/completed wisps across all rigs
- Squash completed patrol wisps to digests
- Burn abandoned wisps that have no audit value
- Part of the hygiene/cleanup system

Also: Witness polecat shutdown should spawn its own short wisp for the cleanup protocol.


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


Digest: mol-deacon-patrol

Test patrol cycle - verifying wisp flow


Remove gt context --usage estimation

The external context estimation approach doesn't work:
- tmux scrollback trick breaks with --cycle
- Can't see actual context usage from outside
- Only the agent knows its internal state

Remove or deprecate:
- gt context --usage flag
- Any external context monitoring logic

Document why in comments: 'Context management is agent-initiated, not externally monitored.
See self-check guidance in role templates.'

This is P3 because it's cleanup - the feature just doesn't work, not actively harmful.


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.


inbox-check

Process witness mail: lifecycle requests, help requests.

```bash
gt mail inbox
```

Handle by message type:
- LIFECYCLE/Shutdown: Queue for pre-kill verification
- Blocked/Help: Assess if resolvable or escalate
- HANDOFF: Load predecessor state
- Work complete: Verify issue closed, proceed to pre-kill

Record any pending actions for later steps.
Mark messages as processed when complete.

Parent gt-751s superseded by Christmas Ornament pattern


Enhanced polecat decommission prompting

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

## Checklist for AGENTS.md.template

```markdown
## Decommission Checklist

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

### Pre-Done Verification

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

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

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

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

### If Any Check Fails

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

### Signaling Done

Only after ALL checks pass:

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

## Implementation

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


gt spawn: add --polecat flag for explicit worker selection

Currently gt spawn requires positional arg format:
```
gt spawn gastown/Angharad --issue gt-xyz
```

But I tried the more intuitive flag form:
```
gt spawn --issue gt-xyz --polecat Angharad
```

This failed with 'unknown flag: --polecat'.

The flag form is more discoverable and consistent with other commands. Add --polecat flag as alternative to positional arg.


Create Refinery role template

Add Refinery template to internal/templates/roles/:
- refinery.md.tmpl with full role context
- Variables: rig name, working directory, handoff bead ID
- Update SeedRoleTemplates to include it
- gt prime uses this template for Refinery context


Fix TestHasPolecat test failure


Digest: mol-deacon-patrol

Patrol 5: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol 8: routine, all healthy


Digest: mol-deacon-patrol

Patrol #18


Fix docs: Formulas are JSON not YAML

The molecular chemistry docs (molecule-algebra.md, molecular-chemistry.md) incorrectly refer to formulas as YAML. Formulas are JSON (.formula.json). Fix all references: .formula.yaml -> .formula.json, 'YAML files' -> 'JSON files', 'formula YAML' -> 'formula JSON', code blocks from yaml to json syntax.


gt session restart/status: Complete session management

Add missing session subcommands:

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

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


Test merge request

branch: polecat/Test/gt-test
target: main
source_issue: gt-test
worker: TestWorker
rig: gastown


Deacon patrol molecules stored in wrong beads location

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


gt spawn beads sync warning is misleading for redirect-based polecats

## Problem

When spawning a polecat, gt spawn shows a warning:
```
Warning: beads sync: exit status 1
```

This is misleading because polecats using the redirect architecture (`.beads/redirect`) share the canonical database at `mayor/rig/.beads/beads.db`. The 'stale beads' indicated by the warning is just git branch divergence (main vs beads-sync), not actual data staleness.

## Expected Behavior

gt spawn should either:
1. Skip the beads sync check for polecats using redirects (they share the canonical DB)
2. Or provide a clearer message like 'beads redirect active, using shared database'

## Reproduction

```bash
gt spawn --issue gt-xxx --rig gastown --create
# Shows 'Warning: beads sync: exit status 1' even though beads are current
```

## Root Cause

spawn.go calls beads sync and treats any non-zero exit as a warning. But with redirects, the polecat doesn't need its own beads - it uses the canonical source via the redirect chain:
```
polecat/.beads/redirect -> ../../.beads -> gastown/.beads/redirect -> mayor/rig/.beads
```

## Fix Options

1. Check for .beads/redirect before calling sync
2. Have bd sync return 0 when redirect is present
3. Suppress the warning in spawn when redirect exists


Digest: mol-deacon-patrol

Patrol 18: All clear


Implement gt mq CLI commands

Add gt mq subcommands as sugar over bd:

- gt mq submit: Create MR for current branch
- gt mq list: Show open merge requests
- gt mq next: Show next MR ready to process
- gt mq process: Engineer processes the queue
- gt mq reorder <id> --after <x>: Change ordering via deps
- gt mq status <id>: Show MR details

All commands should work with the Beads data plane.


gt mq submit: create MR from current branch

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

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

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

Creates merge-request bead and prints MR ID.

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


gt mq list: show queue with status/priority/age

Implement 'gt mq list' command to display the merge queue.

Output format:
ID          STATUS       PRIORITY  BRANCH                    WORKER  AGE
gt-mr-001   ready        P0        polecat/Nux/gt-xyz        Nux     5m
gt-mr-002   in_progress  P1        polecat/Toast/gt-abc      Toast   12m
gt-mr-003   blocked      P1        polecat/Capable/gt-def    Capable 8m
            (waiting on gt-mr-001)

Options:
- --ready: show only ready-to-merge (no blockers, not in progress)
- --status STATUS: filter by status
- --worker WORKER: filter by worker
- --epic EPIC: show MRs targeting integration/EPIC

Under the hood: bd list --type=merge-request with filters.

Reference: docs/merge-queue-design.md#gt-mq-list


gt mq status: detailed MR view

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

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

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

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


gt mq retry: retry a failed MR

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

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

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

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


gt mq reject: manual MR rejection

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

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

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

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


Merge: gt-3x0z.4

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


Mayor startup protocol prompting

Add startup protocol to Mayor CLAUDE.md template.

## On Session Start

1. Check for handoff:
   town inbox | grep "Session Handoff"

2. If handoff found:
   - Read it: town read <msg-id>
   - Process pending escalations (highest priority)
   - Check status of noted swarms
   - Verify rig health matches notes
   - Continue with documented next steps

3. If no handoff:
   town status     # Overall health
   town rigs       # Each rig
   bd ready        # Work items
   town inbox      # Any messages
   Build your own picture of current state.

4. After processing handoff:
   - Archive or delete the handoff message
   - You now own the current state

## Handoff Best Practices

- Be specific: 'Toast has merge conflict in auth/middleware.go' not 'Toast is stuck'
- Include context: Why decisions are pending, what you were thinking
- Prioritize next steps: What is most urgent
- Note time-sensitive items: Anything that might have changed since handoff


gt spawn --create should auto-add polecat if missing

## Problem

`gt spawn gastown --issue gt-xxx --create` fails if no polecats exist.

## Current Behavior

```
Error: auto-select polecat: no available polecats in rig 'gastown'
```

## Expected Behavior

`--create` should:
1. Create a new polecat if none exist
2. Or create the specified polecat if `gt spawn gastown/NewName --create`

## Workaround

Must manually run `gt polecat add gastown Name` first.

## Principle

Agent UX should be forgiving - if I say spawn with --create, make it work.


gt nudge: support no-arg invocation with default message

Currently gt nudge requires a message argument:

```
gt nudge <rig/polecat> <message>
```

Would be nice to support:
```
gt nudge <rig/polecat>
```

With a sensible default message like 'nudge' or 'continue' or checking for pending work automatically.


Digest: mol-deacon-patrol

Patrol 12: Nominal


Merge: gt-8v8

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


Hardcoded session ID prefixes and paths

Multiple hardcoded values throughout code:
- internal/mail/router.go: 'gt-mayor', 'gt-' session prefixes
- internal/lock/lock.go: '.runtime', 'agent.lock' paths
- Session ID generation uses string literals

Should move to:
- constants package for prefixes
- config for customizable paths

Low priority but improves maintainability.


test with labels


Deacon trigger-pending-spawns: Auto-nudge polecats when ready

The Deacon's mol-deacon-patrol defines a trigger-pending-spawns step, but it's not implemented.

## Problem
After gt spawn creates a polecat session, Claude initializes for 10-20s. Nobody sends the initial 'Begin.' message to start work, so polecats sit at prompts forever.

## Current Workaround
Manual: gt nudge gt-<rig>-<polecat> 'Begin.'

## Required Implementation
1. Track pending spawns (polecats spawned but not triggered)
2. In Deacon patrol, poll WaitForClaudeReady for each pending spawn
3. When ready, send 'Begin.' via NudgeSession
4. Mark as triggered

## Evidence
Tracer bullet 2025-12-23: Had to manually nudge polecat/tracer to start work.

Implemented gt deacon trigger-pending command


Digest: mol-deacon-patrol

Patrol 3: All nominal


Polecat template cleanup

Collection of improvements to the polecat role template (polecat.md.tmpl). Focus: reduce prose redundancy, move behavior into molecules, fix terminology, improve clarity.


Polecats should auto-cleanup after MR submission

Currently polecats must manually run 'gt handoff --shutdown' after completing work. This is error-prone and leaves stale polecats around.

## Desired Flow

1. Polecat completes work
2. Polecat runs 'gt mq submit' (or similar)
3. MR is added to integration queue
4. **Polecat automatically cleans up** (no manual handoff needed)

## Implementation Options

### Option A: mq submit triggers cleanup
In 'gt mq submit':
1. Submit MR to queue
2. Automatically run cleanup (same as gt handoff --shutdown)
3. Polecat session terminates

### Option B: Refinery triggers cleanup
When Refinery picks up MR:
1. Refinery processes MR
2. Sends message to Witness: 'CLEANUP: <polecat>'
3. Witness cleans up polecat

### Option C: Molecule-driven
Define cleanup as final phase of polecat-work molecule:
1. code → test → submit-mr → cleanup

## Note
This reinforces the ephemeral model: polecats exist only for the duration of a single task.

Implemented: mq submit now auto-cleanups polecats after MR submission


Find abandoned work

Find abandoned work.

Scan for orphaned state:
- Issues marked in_progress with no active polecat
- Polecats that stopped responding mid-work
- Merge queue entries with no polecat owner
- Wisp sessions that outlived their spawner

```bash
bd list --status=in_progress
gt polecats --all --orphan
```

For each orphan:
- Check if polecat session still exists
- If not, mark issue for reassignment or retry
- File incident beads if data loss occurred

4 in_progress items found, no active polecats - noted for awareness


Digest: mol-deacon-patrol

Patrol #2: Routine - all 6 agents healthy


Add agent abstraction layer to support non-Claude agents

Currently Gas Town hardcodes 'claude --dangerously-skip-permissions' throughout the codebase for spawning agents. We should add an abstraction layer to support other AI agents (e.g., Gemini CLI, OpenAI agents, local models).

Locations that spawn Claude:
- internal/cmd/mayor.go:131
- internal/cmd/deacon.go:150
- internal/cmd/witness.go:280
- internal/cmd/crew.go (multiple locations)
- internal/cmd/up.go:190, 229
- internal/session/manager.go:146
- internal/refinery/manager.go:207

Suggested approach:
1. Create an agent package with an interface
2. Add configuration for agent type in town/rig config
3. Replace hardcoded claude commands with agent.Spawn() calls
4. Support agents: claude, gemini, openai, local (ollama, etc.)


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

Patrol 10: All healthy


Test Patrol Parent

Test parent for Christmas Ornament pattern


Test Polecat Arm

Test child for bonding pattern


MR: gt-test (main)

branch: main
target: main
source_issue: gt-test


Polecat beads not synced with rig beads

When gt spawn assigns an issue to a polecat, the polecat cannot find the issue because:

1. Rig beads at /gt/gastown/.beads contains gt-th7
2. Polecat beads at /gt/gastown/polecats/dementus/.beads does NOT have gt-th7
3. bd sync in polecat dir pulls from beads-sync branch which doesn't have the new issue
4. Rig bd sync uses 'main' branch, causing a branch mismatch

The polecat gets a work assignment for an issue it literally cannot see.

## Root Cause

- Rig beads and polecat beads are separate git-tracked copies
- No mechanism to propagate newly created issues from rig to polecats before assignment
- Sync branch configuration mismatch between rig and polecats

## Fix Options

1. gt spawn should sync rig beads before assigning work
2. gt spawn should sync polecat beads after assignment
3. Use shared beads (symlink or same DB) instead of copies
4. Push new issues immediately on create

Note: This sync mismatch is resolved by gt-9nf (fresh polecats). Rather than fixing sync between stale clones, we'll always create fresh worktrees. This issue documents the root cause for posterity.

Fixed by gt-9nf: fresh polecats now use shared rig beads via redirect


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


Draft mol-ready-work protomolecule definition

Draft the actual protomolecule definition in markdown format.

## Molecule Structure

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

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

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

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

Capture counts and candidates.

Needs: orient

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

Needs: scan-backlogs

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

Commit, push, close/update as appropriate.

Needs: select-work

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

Needs: execute-work

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

Needs: check-context
```

## Variables

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

## Notes

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


Implement context-checking for agent sessions

Implement the context-checking step that allows agents to assess their remaining context capacity.

## Challenge

Agents don't have direct access to token counts. Need heuristics:

### Approach 1: Message count heuristic
- Count messages in conversation
- Estimate tokens per message
- Compare to model's context window

### Approach 2: External tool
- Claude Code could expose a /context command
- Returns estimated usage percentage
- Agent queries before each work item

### Approach 3: Conservative fixed limits
- After N work items, always handoff
- Simple but may waste context or handoff too early

### Approach 4: Hook-based injection
- SessionStart hook injects context estimate
- Updated periodically via tool call

## Recommendation

Start with Approach 3 (fixed limits) as MVP:
- Default: 3-5 work items per session
- Agent can override via variable
- Upgrade to smarter heuristics later

## Integration

- Add check-context step to mol-ready-work
- Implement handoff trigger logic
- Test with various context states


Implement/document gt sling mechanism

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


Document crew worker patrol integration

Document how mol-ready-work integrates with crew worker workflow. Cover: starting the patrol, patrol vs normal operation, backlog configuration, handoff mechanics, discovered work handling. Update CLAUDE.md with patrol section.


Implement Christmas Ornament pattern for mol-witness-patrol

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

## Completed

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

## Remaining

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

## Design Docs

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

Core Christmas Ornament pattern implemented. P2 plugin hooks can be tracked separately.


Update WitnessPatrolMolecule() with Christmas Ornament structure

Update builtin_molecules.go WitnessPatrolMolecule() to use dynamic bonding pattern.

Changes:
1. Add survey-workers step that documents dynamic bonding
2. Add run-plugins step for plugin hook support
3. Add aggregate step with WaitsFor: all-children
4. Update step dependencies for new structure

The molecule prose guides the Witness agent on how to use bd mol bond.

Implemented Christmas Ornament pattern for mol-witness-patrol and mol-polecat-arm


Create PolecatArmMolecule() for per-polecat inspection

Add PolecatArmMolecule() to builtin_molecules.go.

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

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

This proto is bonded dynamically by survey-workers step.


Add witness plugin hook support

Implement plugin directories for witness patrol.

Structure:
  <rig>/plugins/witness/
  ├── pre-inspection/
  │   └── stale-branch-check/
  │       └── CLAUDE.md
  └── post-action/
      └── mq-health/
          └── CLAUDE.md

run-plugins step scans these directories and bonds mol-plugin-runner for each.


Integration test: Christmas Ornament with live polecats

Test the dynamic bonding pattern with actual polecats.

Test scenarios:
1. Patrol with 0 polecats (empty arms)
2. Patrol with 3 polecats (parallel arms)
3. Polecat appears mid-patrol (picked up next cycle)
4. Nudge progression (idle -> nudge-1 -> nudge-2 -> nudge-3)
5. Pre-kill verification flow
6. Activity feed output verification

Integration tests for Christmas Ornament pattern complete. Added christmas_ornament_test.go with tests for: mol-witness-patrol structure, mol-polecat-arm structure, WaitsFor parsing, template expansion, bonding metadata, parent-child relationships, empty patrol handling, nudge progression, pre-kill verification, mol bond CLI simulation, and activity feed output.


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


MCP beads tools fail from polecat directories

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

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

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

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


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

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


Build rig/worker tree view component

Bubbletea component showing hierarchical rig list with workers. Each rig expandable to show workers. Each worker shows: status indicator, current molecule title, step progress (X/Y), time since last activity.


Zombie session detection for refinery/witness

A Claude session can crash or hang while still appearing as 'running' in tmux. The current IsRunning checks only verify tmux session exists, not that Claude is actually processing.

## Problem
- Refinery session might be hung (Claude crashed, infinite loop, etc.)
- tmux HasSession returns true, so auto-start doesn't trigger
- MRs pile up with no processing

## Solution Options
1. **Activity-based detection**: Check last output timestamp in tmux
2. **Heartbeat file**: Agents write timestamp to file, check staleness
3. **Prompt detection**: Look for Claude '>' prompt indicating idle/stuck

## Related
- gt-bjft (spawn auto-start) assumes IsRunning means healthy
- Witness patrol assumes running refinery is processing


Merge: gt-h5n.5

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


Digest: mol-deacon-patrol

Patrol 13: all clear


Track operational stats as entity/audit beads

Witness and refinery track operational stats in JSON files:
- total_merged, today_merged, total_failed (refinery)
- total_checks, total_nudges, total_escalations (witness)

For HOP entity CV tracking, these could become:
- type=audit beads (daily roll-ups of operational metrics)
- Entity chain entries showing validator activity

This provides observability and contributes to entity reputation tracking (e.g., refinery X has merged 500 PRs with 2% failure rate).

Not critical for launch but aligns with HOP Platform of Platforms vision.


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

## Problem

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

## Evidence

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

## Impact

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

## Fix

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


Digest: mol-deacon-patrol

Patrol 6: All clear


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.


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.


Digest: mol-deacon-patrol

Final patrol cycle 20: all systems healthy


Merge: gt-qna4

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


Port Gas Town to Go

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

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

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

Go port complete - Python version deprecated


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


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

Essential CLI commands for Gas Town operation.

## Commands

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

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

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

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

## Implementation

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

Register in cmd/gt/main.go.


CLI: session commands (start, stop, at, list, capture, inject)

Session management CLI commands.

## Commands

### gt session start
Start a polecat session.
```
gt session start <rig>/<polecat> [--issue <id>]
```
- Creates tmux session
- Launches claude in polecat workdir
- Optionally injects initial issue context

### gt session stop
Stop a polecat session.
```
gt session stop <rig>/<polecat> [--force]
```
- Graceful shutdown by default
- --force kills immediately

### gt session at (attach)
Attach to running session.
```
gt session at <rig>/<polecat>
```
- Attaches tmux session to current terminal
- Detach with Ctrl-B D

### gt session list
List all sessions.
```
gt session list [--rig <rig>] [--json]
```
- Shows running/stopped status
- Optionally filter by rig

### gt session capture
Capture recent output from session.
```
gt session capture <rig>/<polecat> [--lines <n>]
```
- Default: last 100 lines
- Useful for checking polecat progress

### gt session inject
Send message to session.
```
gt session inject <rig>/<polecat> -m "message"
gt session inject <rig>/<polecat> -f <file>
```
- Injects text via tmux send-keys
- Used for nudges, notifications

## Address Format

`<rig>/<polecat>` e.g., `wyvern/Toast`

## Implementation

Session subcommand group:
```go
var sessionCmd = &cobra.Command{Use: "session"}
sessionCmd.AddCommand(startCmd, stopCmd, atCmd, listCmd, captureCmd, injectCmd)
```


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


Beads CLI wrapper: shell out to bd

Wrapper for bd (beads CLI) commands.

## Interface

```go
type Beads struct {
    workDir string
}

func NewBeads(workDir string) *Beads

// Query
func (b *Beads) List(opts ListOptions) ([]*Issue, error)
func (b *Beads) Ready() ([]*Issue, error)
func (b *Beads) Show(id string) (*Issue, error)
func (b *Beads) Blocked() ([]*Issue, error)

// Mutations
func (b *Beads) Create(opts CreateOptions) (*Issue, error)
func (b *Beads) Update(id string, opts UpdateOptions) error
func (b *Beads) Close(ids ...string) error

// Sync
func (b *Beads) Sync() error
func (b *Beads) SyncStatus() (*SyncStatus, error)
```

## Data Types

```go
type Issue struct {
    ID          string
    Title       string
    Status      string
    Priority    int
    Type        string
    Description string
    Parent      string
    Children    []string
    DependsOn   []string
    Blocks      []string
}

type ListOptions struct {
    Status   string  // "open", "closed", "all"
    Type     string
    Priority int
}

type CreateOptions struct {
    Title       string
    Type        string
    Priority    int
    Description string
    Parent      string
}
```

## Implementation

Shell out to bd binary, parse JSON output where available.
```go
func (b *Beads) runBd(args ...string) ([]byte, error) {
    cmd := exec.Command("bd", args...)
    cmd.Dir = b.workDir
    return cmd.Output()
}
```

## Error Handling

- bd not installed: Clear error with install instructions
- Not a beads repo: Detect and report
- Sync conflicts: Parse and report

Beads CLI wrapper fully implemented in internal/beads/beads.go


Merge queue: per-rig queue management

Per-rig merge queue for coordinating polecat work.

## Concept

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

## Data Model

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

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

## Interface

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

func NewMergeQueue(rig *Rig) *MergeQueue

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

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

## Queue Storage

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

## Git Coordination

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

## Conflict Handling

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


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.


CLI: rig commands (list, show, add)

Rig management CLI commands.

## Commands

### gt rig list
List all registered rigs.
```
gt rig list [--json]
```
Output:
- Rig name
- Git URL
- Polecat count
- Witness/Refinery status

### gt rig show
Show details for a specific rig.
```
gt rig show <name> [--json]
```
Output:
- Full rig info
- Polecats with status
- Recent activity
- Beads summary (open issues)

### gt rig add
Add a new rig to the town.
```
gt rig add <name> <git-url>
gt rig add <name> --local <path>
```
Steps:
- Clone repo to town root (or link local)
- Register in rigs.json
- Create agent directories
- Configure git exclude

### gt rig remove
Remove a rig from the town.
```
gt rig remove <name> [--force]
```
- Warns if active polecats
- --force required if uncommitted changes

## Implementation

```go
var rigCmd = &cobra.Command{Use: "rig"}
rigCmd.AddCommand(rigListCmd, rigShowCmd, rigAddCmd, rigRemoveCmd)
```


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

Polecat management CLI commands.

## Commands

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

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

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

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

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

## Address Format

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

## Implementation

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


CLI: witness commands (start, stop, status)

Witness daemon CLI commands.

## Commands

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

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

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

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

## Daemon Management

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

## Implementation

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

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


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


Bubbletea TUI dashboard

Interactive TUI using Charm Bubbletea. Root model, view routing, Lipgloss theme. Includes: dashboard, rig explorer, polecat detail with live tail, mail view, beads view, spawn wizard.