Bug: MRs appearing in bd ready output

merge-request beads are showing up in `bd ready` output alongside actual work items.

## Problem
`bd ready` is meant to show work available for polecats to claim. MRs are internal workflow items processed by the Refinery, not polecat work.

## Example
```
| P1 | merge-request | bd-3zzh | Merge: bd-tvu3 |
| P1 | merge-request | bd-fcl1 | Merge: bd-au0.5 |
```

## Possible Fixes
1. **Filter by type** - `bd ready` excludes type=merge-request, type=gate, type=molecule
2. **Set assignee on submit** - MR assigned to refinery/ when created, so not 'unassigned'
3. **Set status=in_progress** - MR starts in_progress since it's queued for processing

## Related
- gate beads also showing (bd-hyp6, bd-wu62) - same issue


Day 5.1: End-to-end liftoff test

Full integration test:
1. gt sling gt-task123 gastown/nux
2. Watch polecat work (no manual intervention)
3. Watch refinery merge (no manual intervention)
4. Watch witness clean up (no manual intervention)
5. See cycle complete in bd activity or logs

Success = no human touches needed.

Parent: gt-oki8p


mol-deacon-patrol

Deacon patrol molecule template. Label: template


Molecule schema: YAML format for workflow definitions

Define the YAML schema for molecule definitions:

```yaml
molecule: <name>
version: 1
description: "Human description"
steps:
  - id: <step-id>
    title: "Step title"
    prompt: "Instructions for agent"
    depends: [<other-step-ids>]  # optional
    tier: haiku|sonnet|opus      # optional, default from config
    timeout: 30m                 # optional
```

Store molecules in:
- `<rig>/molecules/<name>.yaml` for rig-specific
- `<town>/molecules/<name>.yaml` for town-wide

Built-in molecules to ship:
- engineer-in-box: design→code→review→test→submit
- quick-fix: implement→test→submit
- research: investigate→document


Digest: mol-deacon-patrol

Patrol 10: All services healthy


Check own context limit

Check own context limit.

The Deacon runs in a Claude session with finite context. Check if approaching the limit:

```bash
gt context --usage
```

If context is high (>80%), prepare for handoff:
- Summarize current state
- Note any pending work
- Write handoff to molecule state

This enables the Deacon to burn and respawn cleanly.


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol OK: 0 mail, all agents healthy, 3 polecats working


Test Patrol Parent

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

Original description:
Test parent for Christmas Ornament pattern


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 12


Digest: mol-deacon-patrol

Patrol 7: all healthy


Refinery needs branch visibility: Convert to worktree or push branches

The refinery cannot see polecat branches because it is a separate clone, not a worktree.

## Problem
- Polecats are worktrees of mayor/rig (correct, per gt-4u5z)
- Refinery is still a separate clone at refinery/rig (not converted)
- Polecat branches are local to mayor/rig, invisible to refinery

## Decision (2025-12-25)
**Use a shared bare repo as the single git source of truth.**

```
gastown/
├── .repo.git/           ← Bare repo (no working tree, invisible base)
├── mayor/rig/           ← Worktree (human workspace)
├── polecats/
│   └── Toast/           ← Worktree on polecat/Toast
├── refinery/rig/        ← Worktree on main (can see all branches!)
└── crew/max/            ← Worktree or separate clone (TBD)
```

**Why bare repo:**
- No working directory to accidentally work in
- Standard git pattern (how servers work)
- All worktrees share branch visibility
- Refinery on main can merge polecat branches directly

## Implementation
1. Create `.repo.git` as bare clone
2. Convert refinery to worktree of .repo.git on main
3. Convert polecats to worktrees of .repo.git
4. Optionally convert mayor/rig (or keep as worktree)
5. Update gt rig init for new rigs
6. Write migration for existing rigs

## Evidence
Tracer bullet 2025-12-23: Refinery could not see polecat/tracer until pushed to origin.


Digest: mol-deacon-patrol

Patrol 16: routine


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Digest: mol-deacon-patrol

Patrol 6: all quiet


Digest: mol-deacon-patrol

Patrol 1: No mail, all agents healthy (mayor/witnesses/refineries OK), 0 polecats active, 2 orphaned mols for removed furiosa polecat noted


Per-rig beads repo configuration

Add per-rig beads configuration to rig config schema.

## Config Schema

In each rig's config.json:

```json
{
  "version": 1,
  "name": "wyvern",
  "git_url": "https://github.com/steveyegge/wyvern",
  "beads": {
    "repo": "local",    // "local" | "<path>" | "<git-url>"
    "root": null,       // Override bd --root (optional)
    "prefix": "wyv"     // Issue prefix for this rig
  }
}
```

## Repo Options

| Value | Meaning | Use Case |
|-------|---------|----------|
| `"local"` | Use project's `.beads/` | Own projects, full commit access |
| `"<path>"` | Use beads at path | OSS contributions |
| `"<git-url>"` | Clone and use repo | Team shared beads |

## Environment Injection

When spawning polecats, Gas Town sets:
```bash
export BEADS_ROOT="<resolved-path>"
```

## Resolution Logic

```go
func ResolveBeadsRoot(rigConfig *RigConfig, rigPath string) (string, error) {
    beads := rigConfig.Beads
    switch {
    case beads.Root != "":
        return beads.Root, nil
    case beads.Repo == "local" || beads.Repo == "":
        return filepath.Join(rigPath, ".beads"), nil
    case strings.HasPrefix(beads.Repo, "/"):
        return beads.Repo, nil
    case strings.Contains(beads.Repo, "://"):
        return cloneAndResolve(beads.Repo)
    default:
        return filepath.Join(rigPath, beads.Repo), nil
    }
}
```

## Backwards Compatibility

If `beads` section missing, assume `"repo": "local"`.


Test Patrol Parent


Digest: mol-deacon-patrol

Patrol 16: all quiet


ensure-gastown-refinery

Start the gastown rig Refinery.

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

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

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

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


Digest: mol-deacon-patrol

Patrol 8: All healthy, no messages


Digest: mol-deacon-patrol

Patrol 4: All healthy


Town root .beads has schema mismatch with bd

The .beads directory at town root (/Users/stevey/gt/.beads) has an incompatible schema:

```
Error: failed to open database: failed to initialize schema: sqlite3: SQL logic error: no such column: thread_id
```

Meanwhile, gastown/.beads (symlinked to mayor/rig/.beads) works fine.

## Impact

- gt mail inbox fails at town root
- gt handoff sends mail to broken db
- Daemon can't check its inbox

## Options

1. Delete town root .beads/beads.db and let it recreate
2. Symlink town root .beads to gastown/.beads
3. Run schema migration on existing db

## Root Cause

Likely a beads version upgrade that added thread_id column, but the town root db was created before that.


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.


Review: Refinery patrol template changes (gt-qz2l)

Polecat dementus implemented refinery template changes: banners, wisp-based execution, propulsion protocol. Review for correctness and consistency with witness/deacon patterns.


Digest: mol-deacon-patrol

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


Refinery background daemon mode

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

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

## Requirements

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

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

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

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

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

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

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


implement

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

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

Depends: load-context


Test Patrol for Bonding

Parent issue for mol bond CLI test


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 5: Quiet


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

Patrol 20: final patrol before handoff


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


Nudge newly spawned polecats

Nudge newly spawned polecats that are ready for input.

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

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

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

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

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

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

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

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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


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

## Problem

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

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

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

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

## The Right Architecture

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

## Scope

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

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

3. Update gt witness commands to use Claude session model

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

## Related

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


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

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


Review: Witness patrol template changes (gt-h1n5)

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


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol #5: Routine - 6 sessions healthy


Digest: mol-deacon-patrol

Patrol 18: All clear


Digest: mol-deacon-patrol

Patrol 5: Routine


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


Work assignment mail not received by polecat

When gt spawn sends a work assignment:

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

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

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

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

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


Test Polecat Arm

Test child for bonding pattern


bd mol search: Find formulas using GitHub API

Search for formulas across GitHub.

Usage: bd mol search <query>

Should:
- Use GitHub API to search repos with formula.json
- Filter by topics (e.g., beads-formula)
- Display results with descriptions and stars
- Support pagination


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Digest: mol-deacon-patrol

Patrol 19: Quiet


Replace WaitForClaudeReady with gt peek for steady-state agent observation

## Problem

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

## Architectural Fix

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

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

## Implementation

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


mol-deacon-patrol


Create patrol formula YAML files

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

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


Digest: mol-deacon-patrol

Patrol 3: Quick cycle, all quiet


Digest: mol-deacon-patrol

Patrol #18: Stable


Merge: gt-8v8

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


Digest: mol-deacon-patrol

Patrol 7: all clear


Digest: mol-deacon-patrol

Patrol 17: all healthy


Fix gt prime to give crew workers crew context

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


Digest: mol-deacon-patrol

Patrol 3: All clear


Digest: mol-deacon-patrol

Patrol 7: Routine


Generate handoff summary

Summarize this patrol cycle for digest.

Include:
- Workers inspected (count, names)
- Nudges sent (count, to whom)
- Sessions killed (count, names)
- Escalations (count, issues)
- Issues found (brief descriptions)
- Actions pending for next cycle

This becomes the digest when the patrol wisp is squashed.


Document harness concept in docs/harness.md

Create comprehensive harness documentation:
- What is a harness (installation directory)
- Recommended structure and naming
- .beads/redirect for default project
- config/ contents (rigs.json, town.json)
- Mayor home vs rig-level mayor/
- Example configurations
- Relationship to rigs


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.


Update docs with molecule navigation workflow

Update architecture and workflow docs with new molecule navigation.

## Docs to update

### docs/molecules.md
- Add 'Navigating Molecules' section
- Document bd mol current usage
- Document bd close --continue workflow
- Show the propulsion pattern

### docs/propulsion-principle.md
- Add molecule navigation as key enabler
- Show before/after workflow comparison

### docs/polecat-wisp-architecture.md
- Update step execution section
- Show bd close --continue in examples

## New section content

### Molecule Navigation

Finding your place:
  bd mol current              # Where am I?
  bd mol current gt-abc       # Status of specific molecule

Seamless transitions:
  bd close gt-abc.3 --continue   # Close and advance
  bd close gt-abc.3 --no-auto    # Close but don't auto-claim next

The old way (3 commands):
  bd close gt-abc.3
  bd ready --parent=gt-abc
  bd update gt-abc.4 --status=in_progress

The new way (1 command):
  bd close gt-abc.3 --continue

## Blocked by (Beads features)
- bd-sal9: bd mol current
- bd-ieyy: bd close --continue


Crew workers: design documentation and remaining work

## Summary

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

## Current Implementation

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

### Crew vs Polecat

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

## Known Bugs

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

## Potential Enhancements

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


Digest: mol-deacon-patrol

Patrol 13: Routine


Add tests for gt crew restart --all

Add integration tests for the crew restart flow:

- Test getAgentSessions() correctly identifies crew sessions
- Test --rig filtering works correctly
- Test --dry-run outputs correct targets
- Test session kill/recreate cycle (without Claude)

Consider extracting a SessionStarter interface to mock the claude-launching bit.

Related: gt crew restart --all was just implemented.


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 14: All healthy


Test Task 2: Add comment to version.go


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

Patrol 17


Witness Role Definition

You are the Witness - per-rig worker monitor. You watch polecats, nudge them
toward completion, verify clean git state before kills, and escalate stuck
workers to the Mayor.

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

default_molecule: mol-witness-patrol
capabilities:
  - monitor_workers
  - nudge_stuck
  - pre_kill_verify
  - session_lifecycle
  - escalation

## Core Responsibilities

1. Monitor workers: Track polecat health and progress
2. Nudge: Prompt slow workers toward completion
3. Pre-kill verification: Ensure git state is clean before killing sessions
4. Session lifecycle: Kill sessions, update worker state
5. Self-cycling: Hand off to fresh session when context fills
6. Escalation: Report stuck workers to Mayor

Key principle: You own ALL per-worker cleanup. Mayor is never involved in
routine worker management.

## Propulsion Principle

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

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

## Nudge Protocol

Progress through stages. Track nudge count per worker per issue.
- First Nudge (10+ min idle): Gentle inquiry
- Second Nudge (15 min): Direct question
- Third Nudge (20 min): Final warning
After 3 nudges with no progress -> escalate to Mayor

## Pre-Kill Verification

Before killing ANY polecat session:
1. gt polecat git-state <name> - Must be clean
2. Check for uncommitted work
3. Check for unpushed commits
4. Verify issue closed
5. Verify PR submitted (if applicable)

## Commands

- gt polecat list <rig> - See all polecats
- gt polecat git-state <name> - Check git cleanliness
- tmux capture-pane -t gt-<rig>-<name> -p | tail -40 - Session inspection
- gt mail inbox - Check messages
- gt mail send mayor/ -s "Subject" -m "Message" - Escalate


Test Patrol Parent

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

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

Original description:
Test parent for Christmas Ornament pattern


Digest: mol-deacon-patrol

Patrol 13: routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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


load-context

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

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


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

Patrol 13: All healthy


Digest: mol-deacon-patrol

Patrol 18: all healthy


Digest: mol-deacon-patrol

Patrol 5: all clear


Digest: mol-deacon-patrol

Patrol 2: archived stale Mayor handoffs, all agents healthy


detectSender() doesn't recognize crew workers

## Problem

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

## Current Code (line 445)

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

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

## Symptom

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

## Fix

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

## Also Check

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


Digest: mol-deacon-patrol

Patrol 9


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.


Test Polecat Arm

Test child for bonding pattern


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.


Merge: gt-yd98

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


Digest: mol-deacon-patrol

Patrol 3: Routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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


request-shutdown

Send shutdown request to Witness.
Wait for termination.

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

Depends: generate-summary


Design: Polecat lifecycle and patrol coordination

## Context

This design captures thinking from a deep session about the Gas Town propulsion system - how Deacon, Witness, Refinery, and Polecats coordinate to move work smoothly through the system.

## Core Insight: Session-Per-Step Model

Polecats do NOT complete complex molecules end-to-end. Instead:
- One polecat SESSION per molecule STEP
- Same sandbox (branch/worktree) persists across sessions
- Each step: spawn → work → close bead → recycle session
- Final step: spawn → work → close bead → signal complete → merge → nuke sandbox

## Two Cleanup Stages

| Stage | Trigger | Kills | Survives |
|-------|---------|-------|----------|
| Step cleanup | Step bead closed | Session | Branch, worktree, molecule |
| Molecule cleanup | Merged | Session, branch, worktree | Digest |

## Per-Rig Polecat Channel

Need a mailing list/queue per rig for session-lifecycle requests:
- "Recycle me" (from polecat)
- "Recycle worker X" (from witness/mayor)
- "Spawn for step Y" (from anyone)

First-come-first-served by patrolling agents. Anyone on patrol (Witness, Refinery, Crew, Mayor) can service requests.

## GUPP + Pinned Work = Completion

As long as:
1. Work is pinned to polecat identity (e.g., gastown/furiosa)
2. Sandbox persists (branch + worktree)
3. Someone keeps spawning polecat when it dies

→ The molecule WILL get finished. GUPP ensures wake-and-work.

## Daemon → Deacon Heartbeat

The daemon pings the deacon, keeping the cycle alive. Deacon peeks into rig-wide channels during patrol and can service lifecycle requests.

## Open Design Questions

### Q1: Spoon-Feeding Bin-Packing
Two dimensions of granularity trade-offs:
- How many logical steps per physical molecule step?
- How many molecule steps per polecat session?

Too few steps → context exhaustion, forgetting
Too many steps → overhead, fragmentation

Needs: Analysis of optimal granularity based on step complexity.

### Q2: Mechanical vs Agent-Driven Recycling
Caution from deacon murder spree bug: mechanical detection of "stuck" workers is fragile.

Prefer: Explicit "recycle me" requests serviced by patrol agents.

Question: When is mechanical intervention appropriate?

### Q3: Channel Implementation
Options:
- Mail-based (gt mail to rig/polecats)
- Beads-based (special issue type)
- State file (rig/polecat-queue.json)

Mail seems most consistent with Gas Town patterns.

### Q4: Who Spawns Next Step?
Current: gt sling spawns fresh polecat
Needed: Mechanism for "continue molecule on existing sandbox"

Maybe: gt sling --continue or witness detects pending step.

## Related Issues

- gt-dtw9u: Witness monitoring (enhance survey-workers)
- gt-qpwv4: Completion detection (check ready branches)
- gt-6qyt1: Refinery queue (process MERGE_READY)
- gt-budeb: Auto-nuke (handle MERGED signal)
- gt-5j3ia: Swarm aggregation (batch completion)
- gt-1dbcp: Polecat auto-start (SessionStart hook issue)

## Design Principles (from HOP/MEOW context)

1. **Discovery over tracking** - observe reality each cycle
2. **Mail as coordination primitive** - agents signal via mail
3. **ZFC** - Claude makes judgment calls, no hardcoded thresholds
4. **Redundant monitoring** - overlapping observation is resilience
5. **Wisps are ephemeral** - patrol molecules flow like water

## Next Steps

1. Finalize channel design (mail-based queue)
2. Enhance witness patrol formula with completion detection
3. Enhance refinery patrol with MERGED signaling
4. Implement step-level recycling
5. Design spoon-feeding granularity guidelines


Merge: gt-vmk7

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


142 instances of error suppression with _ = pattern

Code has 142 instances of '_ = ' error suppression in non-test code.
Examples:
- internal/polecat/manager.go: _ = pool.Load() - ignores state loading
- internal/daemon/notification.go: _ = os.WriteFile() - ignores file write
- internal/mail/router.go: _ = r.notifyRecipient() - notification ignored

These create silent failures and hard-to-debug issues.

Options:
1. Document intentional suppressions with comments
2. Handle errors properly where appropriate
3. At minimum, log suppressed errors at debug level


Auto-rebase on conflict: optional automatic rebase

Implement automatic rebase as conflict resolution option.

When on_conflict=auto_rebase and conflicts detected:
1. Attempt: git rebase <target> <source-branch>
2. If clean rebase: update source branch, continue merge
3. If conflicts in rebase: abort, fall back to assign_back
4. Force push rebased branch (worker's branch)

Requires:
- Worker branch must be force-pushable
- Config: on_conflict: auto_rebase

Risks:
- Force push can confuse workers
- Complex conflicts still need manual resolution

Reference: docs/merge-queue-design.md#conflict-resolution-strategies


Digest: mol-deacon-patrol

Patrol 11: Nominal


HTTP work client: CloudRun dispatch client

## Overview

HTTP client for dispatching work to Cloud Run and streaming results back.

## Implementation

```go
type WorkClient struct {
    serviceURL string
    httpClient *http.Client  // HTTP/2 enabled
}

func NewWorkClient(serviceURL string) *WorkClient {
    return &WorkClient{
        serviceURL: serviceURL,
        httpClient: &http.Client{
            Transport: &http2.Transport{},
            Timeout:   0,  // No timeout for streaming
        },
    }
}

func (c *WorkClient) DispatchWork(ctx context.Context, req WorkRequest) (<-chan WorkEvent, error) {
    // 1. POST to /work
    // 2. Return channel that streams WorkEvents
    // 3. Close channel when done/error
}
```

## Streaming Reader

```go
func (c *WorkClient) streamEvents(body io.Reader, events chan<- WorkEvent) {
    defer close(events)
    decoder := json.NewDecoder(body)
    for {
        var event WorkEvent
        if err := decoder.Decode(&event); err != nil {
            return
        }
        events <- event
    }
}
```

## Files

- `internal/cloudrun/client.go`

## Dependencies

Depends on: gt-9a2.7 (protocol types)
Used by: gt-9a2.8 (CloudRunOutpost)


gt done: Missing command referenced in polecat docs


Digest: mol-deacon-patrol

P20 - handoff


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 18: Quiet


Daemon sending heartbeat to Mayor - should not

Daemon appears to be sending heartbeat messages to Mayor, but Mayor should not receive heartbeats. Observed at least once or twice - needs investigation to confirm and fix.


Create molecules catalog directory structure

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

## Structure

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

## PROTO.md Format

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

# mol-gastown-boot

Town bootstrap molecule.

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

## Catalog Loading

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

This enables file-based proto development with beads tracking.


Swarm state persistence: manifest + state + events

Upgrade swarm persistence to match PGT pattern.

## Current State
Single .gastown/swarms.json with all swarms.

## Target State (per-swarm)
```
.gastown/swarms/
└── <swarm-id>/
    ├── manifest.json  # Immutable config
    ├── state.json     # Mutable progress
    ├── events.jsonl   # Audit log
    └── report.md      # Generated report
```

## File Schemas

### manifest.json (immutable after creation)
```json
{
  "id": "sw-1",
  "title": "Epic description",
  "epic_id": "gt-abc",
  "rig": "gastown",
  "base_commit": "abc123",
  "integration_branch": "swarm/sw-1",
  "target_branch": "main",
  "workers": ["Toast", "Nux"],
  "tasks": [{"id": "gt-xyz", "title": "..."}],
  "created_at": "2024-01-01T00:00:00Z"
}
```

### state.json (mutable)
```json
{
  "state": "active",
  "task_states": {
    "gt-xyz": {"state": "merged", "assignee": "Toast"}
  },
  "updated_at": "2024-01-01T01:00:00Z",
  "error": null
}
```

### events.jsonl (append-only audit)
```jsonl
{"event": "created", "ts": "...", "data": {...}}
{"event": "task_assigned", "ts": "...", "data": {...}}
{"event": "task_merged", "ts": "...", "data": {...}}
```

## Benefits
- Audit trail via events.jsonl
- Manifest immutability prevents corruption
- Cleaner separation of concerns
- Per-swarm isolation

## Migration
Keep backward compat with swarms.json during transition.

## Files to Modify
- internal/swarm/manager.go: Refactor persistence
- internal/cmd/swarm.go: SwarmStore → directory-based

## Acceptance Criteria
- [ ] Per-swarm directory structure
- [ ] Events logged to JSONL
- [ ] Manifest immutable after creation
- [ ] List command aggregates from directories


Patrol 14: All healthy


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


Digest: mol-deacon-patrol

Patrol 8: All healthy


Rename engineer-in-box to shiny across all docs

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


Digest: mol-deacon-patrol

Patrol 13: All healthy


Test Polecat Arm

Test child for bonding pattern


Digest: mol-deacon-patrol

Patrol 7: All healthy


Default polecat names: Mad Max theme instead of AdjectiveNoun

Current default naming for new polecats uses AdjectiveNoun convention.
Since rigs already provide namespacing, we can use more thematic names.

Suggestion: Use Mad Max / Fury Road character and vehicle names as defaults.
Examples: Furiosa, Nux, Slit, Morsov, Toast, Rictus, Warboy, etc.

Could also include:
- War Rig parts: Guzzler, Tanker, Pursuit
- Citadel roles: Imperator, Blackthumb, Organic
- Wasteland terms: Chrome, Witness, Shiny

Implementation:
- Add name generator in internal/polecat/ or similar
- Use when --create flag is used without explicit name
- Cycle through pool to avoid duplicates within a rig


Day 3.1: Wire witness patrol formula to daemon cron

Witness patrol molecule runs on schedule:
- Daemon pokes witness on cron interval
- Witness runs mol-witness-patrol steps
- Results in wisp (ephemeral), squashed later

Parent: gt-hwka3


Merge: gt-h6eq.3

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


Missing standard OSS files: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY

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

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


Digest: mol-deacon-patrol

Patrol 2: all healthy, no callbacks, no gates, no orphans, no plugins


inspect-workers

Capture output for each working polecat.

```bash
gt peek <rig>/<polecat>
```

Needs: survey-workers


mol-deacon-patrol

Mayor's daemon patrol loop.

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


mol-deacon-patrol


Standardize bd mol vs gt mol commands

Audit all docs and templates for command usage.

Clarify:
- gt mol = Gas Town wrapper (what does it add?)
- bd mol = Beads molecule commands (authoritative)

If gt mol is thin wrapper, consider removing.


Human escalation path design

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


Digest: mol-deacon-patrol

Patrol 12: All healthy, no messages


Merge: gt-h5n.5

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


Digest: mol-deacon-patrol

Patrol 1: All clear - inbox empty, agents healthy, no orphans


Implement bd bond command for artifact-level composition

Implement the artifact-level bond operator distinct from source-level rigging.

Bond accepts:
- Formula names (cooks inline to ephemeral proto, then bonds)
- Mol IDs (existing liquid work)
- Wisp IDs (existing vapor work)

See molecular-chemistry.md for the full bond table semantics.

**Updated 2025-12-25**: With ephemeral protos (gt-4v1eo), bond takes formula names directly and cooks inline. No pre-cooked proto beads.


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

Patrol 1: All healthy, no actions


Direct test

Testing direct bd create


Phase 3.1: Summary generation protocol

Define how agents generate summaries for squash.

## The Problem

Beads doesn't make AI calls (inversion of control). Gas Town agents must:
1. Generate their own summary before calling squash
2. Pass summary to bd squash command

## Summary Template

```
Task: <source issue title>
Action: <what was done - fix/implement/refactor/etc>
Outcome: <result - tests pass, committed, needs follow-up, etc>
Details: <1-2 sentences of specifics if needed>
```

## Example

```
Task: Fix lifecycle parser matching bug (gt-rixa)
Action: Reordered conditional checks in parseLifecycleRequest
Outcome: Tests passing, committed to polecat/furiosa
Details: The 'cycle' keyword was matching 'lifecycle:' prefix. Now checks restart/shutdown first, uses word boundary for cycle.
```

## Command

```bash
bd squash eph-abc123 --summary "Task: Fix lifecycle parser..."
```


Plugin: Plan-to-Epic converter

## Purpose

Help users create beads epics from various planning inputs.

## Inputs
- Markdown task lists
- GitHub issues
- Linear/Jira exports
- Free-form descriptions
- Existing beads epics

## Output
- Beads epic with properly structured children
- Dependencies set for wave ordering
- Priorities assigned
- Ready for `gt spawn --epic <id>`

## Implementation Options

### Option A: CLI Tool
```bash
gt plan import --from github --repo owner/repo --label batch-candidate
gt plan import --from markdown tasks.md
gt plan structure <epic-id>  # analyze and add dependencies
```

### Option B: Plugin Agent
A plugin at `<rig>/plugins/plan-oracle/` that:
- Receives planning requests via mail
- Analyzes scope and requirements
- Creates structured beads epic
- Sets dependencies based on analysis

### Option C: Interactive Mode
```bash
gt plan create
# Walks through questions, creates epic interactively
```

## Axiom

As stated: 'The Planning phase should end in the creation of a workable Beads plan.'

This plugin bridges the gap between human planning and machine-executable work.

## Priority

P2 - Nice to have for MVP. Manual epic creation works for now.

## Note

No "swarm IDs" - output is just a beads epic with children. Workers process it independently.


Digest: mol-deacon-patrol

Patrol cycle 4: routine, healthy


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


Digest: mol-deacon-patrol

Patrol 1: All healthy, no messages, no orphans


gt mail: Cross-level routing is broken

When Mayor sends mail to rig worker, message lands in wrong beads database. Sender's beads vs recipient's.


Digest: mol-deacon-patrol

Patrol 2: Quick scan, all healthy, no work


Digest: mol-deacon-patrol

Patrol 20: All healthy - final patrol


Digest: mol-deacon-patrol

Patrol 19: all clear


Test Polecat Arm

Test child for bonding pattern


mol-deacon-patrol


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Add crew session pattern to lifecycle handling

Update identityToSession and restartSession to handle crew patterns: gastown/max -> gt-gastown-max. Crew workers can request lifecycle but are not proactively monitored.


mol progress: track dynamically bonded children

Extend `gt mol progress` to show dynamically bonded children.

## Current Behavior

```
gt mol progress gt-abc
```

Shows progress through pre-defined steps from InstantiateMolecule.

## New Behavior

Also show dynamically bonded children:

```
📊 Progress: mol-witness-patrol (gt-abc)

  Steps (9):
    ✓ inbox-check
    ✓ check-refinery
    ✓ load-state
    ◐ survey-workers (bonded 3 children)
    ○ aggregate (WaitsFor: all-children)
    ○ save-state
    ○ generate-summary
    ○ context-check
    ○ burn-or-loop

  Bonded Children (3):
    ✓ arm-toast (5/5 steps)
    ◐ arm-nux (3/5 steps)
    ○ arm-furiosa (0/5 steps)

  Progress: 4/9 steps, 3 arms (1 complete, 1 in-progress, 1 pending)
```

## Implementation

1. Find children with bonded_to: <parent-id> in description
2. Recursively get progress for each bonded child
3. Aggregate into parent progress display


Digest: mol-deacon-patrol

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


Merge: gt-h6eq.3

branch: polecat/dag
target: main
source_issue: gt-h6eq.3
rig: gastown


Add stale-attachments doctor check

Add gt doctor check for work stale on hook without progress.

Check: stale-attachments
Warning if: Attached molecule has no activity for >24h
Suggestion: Check agent status, consider nudge or reassignment


Digest: mol-deacon-patrol

Patrol 3: Quiet, all agents healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Test Patrol for Bonding

Parent issue for mol bond CLI test


README: Update Install section for homebrew/npm

README currently shows:
  go install github.com/steveyegge/gastown/cmd/gt@latest

But users will install via homebrew or npm. Update to show:
  brew install gastown
  # or
  npm install -g @anthropic/gastown

Also add prerequisites section (tmux, Claude Code CLI).


gt mq integration land: merge integration branch to main

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

Actions:
1. Verify all MRs targeting integration/<epic> are merged
2. Verify integration branch exists
3. Merge integration/<epic> to main (--no-ff)
4. Run tests on main
5. Push to origin
6. Delete integration branch
7. Update epic status

Options:
- --force: land even if some MRs still open
- --skip-tests: skip test run
- --dry-run: preview only

This creates a single merge commit for the entire epic's work.

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


Digest: mol-deacon-patrol

Patrol 9: all quiet


Digest: mol-deacon-patrol

Patrol 3: routine, all healthy


Refactor: Extract common manager creation boilerplate

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

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


Digest: mol-deacon-patrol

Patrol 9: All agents healthy, 1 orphan process cleaned, no mail


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.


Merge: gt-5af.6

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


Digest: mol-deacon-patrol

Patrol 8: Witnesses healthy


mol-deacon-patrol


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


Add self-check context guidance to role CLAUDE.md files

Each role's CLAUDE.md needs guidance for context self-management:

- After each patrol cycle, self-assess context pressure
- Heuristics: feeling compressed, lots of tool calls, long session
- If triggered: initiate handoff before continuing

Roles to update:
- Mayor (~/gt/CLAUDE.md)
- Witness template
- Refinery template
- Polecat template
- Crew template
- Deacon template

This is the 'inversion of control' - agents decide when to cycle, not external monitoring.


Design: Work flow simulation and validation

Validate GGT designs through simulation before implementation.

## Validation Approaches

### 1. Dry-Run Simulation (Recommended First)
Mayor walks through scenarios mentally/on paper:
- "If polecat Toast signals done with dirty git state, what happens?"
- "If Witness context fills mid-verification, what state is lost?"
- "If two polecats try to close same issue, what happens?"

Create beads for any gaps discovered.

### 2. Real Work in gastown-py
Use Python Gas Town to stress-test assumptions:
- Run actual batch work on test repos
- Observe edge cases in practice
- Document issues found

### 3. Edge Case Analysis
Systematic review of failure modes:
- Agent crashes mid-operation
- Network failures during sync
- Concurrent access to shared state
- Context limits hit at bad times

## Key Scenarios to Validate

- [ ] Witness session cycling (state preservation)
- [ ] Polecat decommission with dirty state
- [ ] Merge conflicts in queue
- [ ] Beads sync conflicts between workers
- [ ] Escalation path (stuck worker -> Mayor)
- [ ] Cross-rig communication
- [ ] Federation mail routing (future)

## Success Criteria

- No data loss scenarios identified
- Clear recovery paths for all failure modes
- Edge cases either handled or documented as limitations
- Design improves as model cognition improves

## Output

For each scenario validated:
1. Document in relevant bead if issue found
2. Create new beads for missing functionality
3. Update architecture.md if design changes


Digest: mol-deacon-patrol

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


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


Digest: mol-deacon-patrol

Patrol 8: routine, all healthy


Digest: mol-deacon-patrol

Patrol cycle 19: nominal


mol-witness-patrol

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

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

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

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


Test message

Testing GGT mail integration


Remove gt mail dependency on bd mail commands

Replaced bd mail send/inbox/read/ack with bd create/list/show/close. Messages are now stored as beads issues with type=message.


Digest: mol-deacon-patrol

Patrol 1: All agents healthy, no messages, no issues


Digest: mol-deacon-patrol

Patrol complete: all agents healthy, no lifecycle requests, 9 in-progress items noted


Refinery background daemon mode

The refinery 'gt refinery start' command only works in foreground mode (--foreground). Need to implement background daemon mode for production use.

Options:
1. Use a separate tmux session for the refinery
2. Implement proper daemonization
3. Use Claude Code session for the refinery agent

For MVP, option 1 (tmux session) is probably simplest.


Epic: Wisp Molecule Integration

## Vision

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

## The Steam Engine Metaphor

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

## Architecture

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

## Vocabulary

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

## Key Design Decisions

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

## Digest Contents

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

## Integration Points

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

## Phases

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


Digest: mol-deacon-patrol

Patrol 15: All healthy, no messages


Test Polecat Arm

Test child for bonding pattern


Digest: mol-deacon-patrol

Patrol 15: all healthy, doctor pass


Digest: mol-deacon-patrol

Patrol 16: All healthy


gt sling: patrol spawning must use wisp storage, not main DB

**P0 Launch Blocker**

gt sling to patrol roles (witness/refinery/deacon) currently spawns patrols into the main beads database instead of wisp storage. This will pollute the permanent database with ephemeral patrol cycles.

**Root cause:**
spawnMoleculeFromProto() with IsWisp=true uses `--db .beads-wisp/beads.db`, but the patrol TEMPLATE (e.g., gt-qp2w for mol-witness-patrol) only exists in the main database. So bd mol run fails with 'no issue found'.

**The fix:**
bd mol run needs to support reading the template from the main DB while writing the spawned instance to wisp storage. This is a cross-database spawn operation.

Options:
1. Add `--template-db` flag to bd mol run (read template from here, write instance to --db)
2. Copy template to wisp DB before spawning
3. Make bd mol run automatically check main DB for templates when using wisp storage

**Workaround applied (MUST REVERT):**
Set IsWisp=false in slingToWitness/slingToRefinery/slingToDeacon patrol spawning.

**Files:**
- internal/cmd/sling.go: lines 680, 883, 1050 (IsWisp: false)
- Needs fix in bd mol run (beads repo)


Merge: gt-unrd

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


Digest: mol-deacon-patrol

Patrol 15: All healthy


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


Digest: mol-deacon-patrol

Patrol 2: All healthy, routine


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Digest: mol-deacon-patrol

Patrol 20: all quiet - handoff cycle


Digest: mol-deacon-patrol

Patrol 9: healthy


Digest: mol-deacon-patrol

Patrol 18: All healthy


Digest: mol-deacon-patrol

Patrol 14: all clear


/restart: Personal slash command for in-place agent restart

Create ~/.claude/commands/restart.md that restarts current Gas Town agent in place.

## Detection
- Read tmux session name: gt-mayor, gt-witness-*, gt-refinery-*, gt-polecat-*
- Fallback: check GT_ROLE env var

## Behavior by role
- mayor: gt mayor restart (sends Ctrl-C, loop respawns)
- witness: gt witness restart
- refinery: gt refinery restart
- polecat: gt polecat restart (or witness-mediated)

## Command format
Uses backticks for inline bash to detect context, then instructs Claude to run appropriate restart.


Digest: mol-deacon-patrol

Patrol 9: nominal


Digest: mol-deacon-patrol

Patrol 17: all healthy


Digest: mol-deacon-patrol

Patrol 13: clear


Digest: mol-deacon-patrol

Patrol 15: All agents healthy


Implement gt mol attach-from-mail command

Allow agents to self-pin work from mail.

Usage: gt mol attach-from-mail <mail-id>

Behavior:
1. Read mail body for attached_molecule field
2. Attach molecule to agent's hook
3. Mark mail as read
4. Return control for execution

Handles case where work was sent via mail but not slung to hook.


Digest: mol-deacon-patrol

Patrol 14: nominal


Digest: mol-deacon-patrol

Patrol 4: All agents healthy, routine


Digest: mol-deacon-patrol

Patrol 2: All healthy


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

## Problem

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

## Current Behavior

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

## What Works

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

## Proposed Fix

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

## Considerations

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

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


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.


Handle callbacks from agents

Handle callbacks from agents.

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

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

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


Digest: mol-deacon-patrol

Patrol 17: Quiet


mol-deacon-patrol


Digest: mol-deacon-patrol

Patrol 7: routine, all healthy


bd formula list/show commands

Implement formula management commands:

  bd formula list
  # Lists formulas from all search paths

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

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


Digest: mol-deacon-patrol

Patrol 7: all healthy


Polecat mood command and status line display

CLI and status line support for polecat mood.

## CLI Command
```
gt polecat mood <name> <emoji>   # Set mood
gt polecat mood <name>           # Get mood
```

Sets GT_MOOD environment variable in the polecat's tmux session.

## Status Line Integration
Update runWorkerStatusLine() to read mood:
```go
mood, _ := t.GetEnvironment(session, "GT_MOOD")
if mood != "" {
    icon = mood  // Use mood emoji instead of default
} else {
    icon = AgentTypeIcons[AgentPolecat]  // Fallback to 😺
}
```

## Storage
Mood stored in tmux session environment (ephemeral, per-session).
No persistence needed - mood is reassessed each patrol cycle.

Depends on: gt-u818 (plugin system)


gt mol step done: Auto-continue molecule on step completion

## Summary

Implement `gt mol step done <step-id>` command that enables polecats to close a molecule step and automatically continue to the next step without waiting for witness orchestration.

## Problem

Currently, when a polecat completes a molecule step:
1. Polecat sends POLECAT_DONE to witness
2. Witness (in patrol cycle) eventually reads mail
3. Witness spawns next step
4. **Minutes of latency possible**

Polecats also forget to close beads steps (using internal TodoWrite instead), breaking the activity feed.

## Solution

`gt mol step done <step-id>` handles everything:

1. Close the beads step (`bd close <step-id>`)
2. Extract molecule ID from step (bd-mol-xga.1 → bd-mol-xga)
3. Find next ready step (dependency-aware)
4. If next step exists:
   - Update hook file to point to next step
   - Write handoff context
   - tmux respawn-pane (fresh claude session)
5. If molecule complete:
   - Clear hook
   - Send POLECAT_DONE to witness
   - Exit session

## Key Insight

Step-to-step transitions are **mechanical**, not **cognitive**. No AI needed in the critical path. Pure Go automation.

## Related Commands

- `gt mol next <mol-id>` - Show next ready step(s)
- `gt mol progress <mol-id>` - Already exists

## Polecat Protocol Update

```markdown
When your hook contains a molecule step:
1. Read the step: `bd show <step-id>`
2. Execute the work described
3. When complete: `gt mol step done <step-id>`

That is it. Do NOT manually close steps. Do NOT work multiple steps.
```

## Benefits

- **Instant step transitions** (~5-10s vs minutes)
- **Activity feed works** (steps closed as completed)
- **Witness freed up** (safety net only, not critical path)
- **Fresh context per step** (better attention, no accumulated confusion)


Digest: mol-deacon-patrol

Patrol 9: All healthy


Digest: mol-deacon-patrol

Patrol 14: All healthy


Polecat role references deprecated 'swarm' terminology

prompts/roles/polecat.md line 12 says:
'Part of a swarm: Other polecats may be working on related issues in parallel'

But architecture.md explicitly states:
'There are no swarm IDs - just epics with children'

The swarm concept has been replaced by streams/dependency model.
Update polecat.md to remove swarm references.


gt doctor: Check and fix beads routing configuration

## Summary

`gt doctor` should check that all rigs with beads have proper routing entries
in `~/gt/.beads/routes.jsonl`, and offer to fix any missing entries.

## Checks to Add

### Check: routes.jsonl exists
- Verify `~/gt/.beads/routes.jsonl` exists
- If missing, create with entries for all known rigs

### Check: All rigs have routing entries
For each rig in town:
1. Find the rig's beads prefix (from config.yaml or sample issue)
2. Check if routes.jsonl has an entry for that prefix
3. If missing, report and offer to add

### Check: Routes point to valid locations
For each route in routes.jsonl:
1. Verify the path exists and has a .beads directory
2. Verify the .beads directory has a beads.db
3. If invalid, report and offer to remove

## Fix Actions

- `--fix` should automatically add missing routes
- `--fix` should remove invalid routes (or prompt)
- Should handle redirect files when validating paths

## Example Output

```
Checking beads routing...
  [!] Rig 'myproject' (prefix: mp-) has no routing entry
      Run: gt doctor --fix to add routing

Routes health:
  [OK] gt- -> gastown/mayor/rig
  [OK] bd- -> beads/mayor/rig
  [!]  mp- -> myproject/mayor/rig (MISSING)
```


Digest: mol-deacon-patrol

Patrol 3: All healthy


Preflight molecule: verify baseline health before work

Before assigning work, verify baseline (main branch) is healthy.

**From VC**: Self-healing state machine (HEALTHY → SELF_HEALING → ESCALATED). ~200 lines.

**Gas Town implementation**: Preflight molecule or refinery feature:
```yaml
preflight:
  gates: [test, lint, build]
  on_failure: create-fix-issue
```

Run at session start. If baseline broken, file a P0 fix issue and work on that first.

**Value**: Self-healing baseline. Agents don't start from broken state.

**VC lesson**: Prevents cascading failures. Agent shouldn't start work on broken code.


Patrol formulas: Inconsistent variable placeholder syntax

The patrol formulas use inconsistent syntax for variable placeholders:

## Inconsistency

| Formula | Syntax | Examples |
|---------|--------|----------|
| mol-polecat-arm | `{{var}}` | `{{polecat_name}}`, `{{rig}}` |
| mol-witness-patrol | `<var>` | `<rig>`, `<handoff-bead-id>` |
| mol-refinery-patrol | `<var>` | `<polecat-branch>` |

## Expected

All formulas should use consistent syntax, probably `{{var}}` since that's what
the variables section defines.

## Fix

Update mol-witness-patrol and mol-refinery-patrol to use `{{var}}` syntax
where appropriate, or document that `<var>` is for human-filled placeholders
vs `{{var}}` for cook-time interpolation.


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Test Polecat Arm

Test child for bonding pattern


gt spawn should create fresh polecat worktree, never reuse

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

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

## Current Behavior

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

## Desired Behavior

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

## Name Pool Still Useful

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

But worktrees should be created fresh each time.

## Implementation

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

This ensures polecats always start with latest code and beads.


Digest: mol-deacon-patrol

Patrol #10: Stable


Add gate checking to Deacon patrol loop

Integrate gate checking into Deacon's patrol cycle.

## Patrol Integration
```go
func (d *Deacon) checkGates(ctx context.Context) {
    gates, _ := d.store.ListOpenGates(ctx)

    for _, gate := range gates {
        // Check timeout
        if time.Since(gate.CreatedAt) > gate.Timeout {
            d.notifyWaiters(gate, "timeout")
            d.closeGate(gate, "timed out")
            continue
        }

        // Check condition
        if d.checkCondition(gate.AwaitType, gate.AwaitID) {
            d.notifyWaiters(gate, "cleared")
            d.closeGate(gate, "condition met")
        }
    }
}
```

## Moved from beads
Originally bd-is6m. Deacon is in gastown, not beads.


Self-test

Testing gt mail works


Doctor check: Worker health and stuck detection

Detect and report stuck workers via gt doctor.

## Checks

### WorkerHealthCheck
- List all active workers (polecats with state=working)
- Check last activity timestamp for each
- Flag as potentially stuck if no progress for configurable threshold (default: 30 min)
- Check if Witness is running for the rig
- Verify Witness last heartbeat time

### Stuck Detection Criteria
- Polecat state=working but session not running
- Polecat state=working but output unchanged for threshold
- Witness not responding to health checks
- Multiple polecats in same rig all stuck

## Output

```
[WARN] Workers in rig 'wyvern' may be stuck:
  - Toast: working for 45m, no recent output
  - Capable: working for 52m, session not found
  - Witness: last heartbeat 20m ago

  Suggestions:
  - gt witness status wyvern
  - gt capture wyvern/Toast 50
  - gt stop --rig wyvern (kill all)
```

## Auto-Fix

Cannot auto-fix stuck workers (risk of data loss), but can:
- Restart Witness daemon if crashed
- Send warning mail to Mayor


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Implement gt watch command scaffold

Basic bubbletea TUI scaffold for 'gt watch' command. Discovers rigs, connects to daemons, renders placeholder view. Foundation for the full activity feed TUI.


Define mol-gastown-boot proto structure

Create the proto molecule definition with all steps.

## Proto Definition

Each step has:
- Title (step name)
- Description with Action/Verify/OnStall/OnFail sections
- Dependencies (Needs: directive)

## Steps

1. ensure-daemon
   - Action: gt daemon status || gt daemon start
   - Verify: daemon PID exists and responding

2. ensure-deacon
   - Action: gt deacon start
   - Verify: session exists, not stalled, heartbeat fresh
   - OnStall: gt nudge deacon/ "Start patrol."

3. ensure-witnesses (parallel container)
   - ensure-gastown-witness
   - ensure-beads-witness
   - Verify each: session exists, not stalled

4. ensure-refineries (parallel container)
   - ensure-gastown-refinery
   - ensure-beads-refinery
   - Verify each: session exists, not stalled

5. verify-town-health
   - Action: gt status
   - Verify: all expected agents shown

## Output

Proto stored in beads as molecule type issue.


mol-deacon-patrol


Test Patrol for Bonding

Parent issue for mol bond CLI test


Digest: mol-deacon-patrol

Patrol 5: clear


Deacon has no rig-level presence - only global gt-deacon

The Deacon patrol role exists only at the global level (~/gt/deacon) but doesn't have per-rig presence like Witness and Refinery.

Current structure:
```
~/gt/
├── deacon/           ← Global deacon only
├── beads/
│   ├── witness/      ← Per-rig witness
│   ├── refinery/     ← Per-rig refinery
│   └── (no deacon)   ← Missing
└── gastown/
    ├── witness/
    ├── refinery/
    └── (no deacon)   ← Missing
```

Question: Should Deacon be per-rig like Witness/Refinery, or is global-only intentional?

If per-rig is needed: Create beads/deacon and gastown/deacon with appropriate CLAUDE.md files.


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

GGT is missing most polecat management commands that PGT has.

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

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

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


Digest: mol-deacon-patrol

Patrol 4: all clear


Digest: mol-deacon-patrol

Patrol 8: Quiet


gt crew list: List crew workspaces

Implement 'gt crew list [--rig <rig>]' command:
- List all crew workers in rig(s)
- Show status (session running, last activity)
- Show current branch and git status summary
- Support --json output


Digest: mol-deacon-patrol

Patrol 10: routine, all healthy


Improve test coverage in low-coverage packages

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

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


Digest: mol-deacon-patrol

Patrol 7: All agents healthy


Witness arm bonding integration test

Test witness with 3 polecats. Verify: arms bonded per worker, each arm captures/assesses independently, aggregation waits for all arms, witness proceeds after aggregation.


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

Patrol 6: quiet


Merge: gt-3x0z.1

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


Digest: mol-deacon-patrol

Patrol 7: routine


Plugin: merge-oracle (merge queue analysis)

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


check-refinery

Ensure the refinery is alive and processing merge requests.

Needs: inbox-check


Create mol-gastown-polecat derived molecule

Create the standard Gas Town polecat workflow molecule.

## Molecule Definition
\`\`\`markdown
## Molecule: gastown-polecat
Full workflow for Gas Town polecats including binary installation.

Includes: mol-engineer-in-box

## Step: install-binary
After merge is submitted, rebuild and install the local gt binary.
This ensures the latest code is available to all local agents.

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

Needs: submit
\`\`\`

## Why This Molecule
Every polecat that pushes to main should also rebuild the binary.
This ensures the installed gt is always current with main.

## Implementation
1. Add to builtin_molecules.go (after Includes support lands)
2. Update SeedBuiltinMolecules
3. Run gt molecule seed

## Acceptance
- [ ] mol-gastown-polecat exists
- [ ] Includes all engineer-in-box steps
- [ ] Adds install-binary step after submit
- [ ] Can be used with gt spawn --molecule


Digest: mol-deacon-patrol

P4: stable


Competing molecule instantiation mechanisms need resolution

Documentation describes 4 different molecule instantiation methods:
1. bd mol bond (beads-based, in molecules.md)
2. gt sling (proposed in sling-design.md)
3. gt swarm (implemented in code)
4. gt molecule instantiate (in architecture.md)

Role prompts use different methods:
- Deacon: bd mol spawn
- Refinery: gt mol bond
- Polecat: bd mol current

Need to:
1. Decide canonical mechanism
2. Update all role prompts to use it
3. Remove/deprecate alternatives
4. Update architecture docs


Burn and respawn or loop

Burn and let daemon respawn, or exit if context high.

Decision point at end of patrol cycle:

If context is LOW:
- Sleep briefly (avoid tight loop)
- Return to inbox-check step

If context is HIGH:
- Write state to persistent storage
- Exit cleanly
- Let the daemon orchestrator respawn a fresh Deacon

The daemon ensures Deacon is always running:
```bash
# Daemon respawns on exit
gt daemon status
```

This enables infinite patrol duration via context-aware respawning.


Digest: mol-deacon-patrol

Patrol 10: all healthy


Digest: mol-deacon-patrol

Patrol 20: routine, handoff triggered


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

Set up Go project structure with CLI framework.

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

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


Digest: mol-deacon-patrol

Patrol 19: All healthy


mol-deacon-patrol

Mayor's daemon patrol loop.

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


CLI: cleanup commands for stale state

Cleanup commands for recovering from stale state.

## Commands

### gt cleanup <polecat>
Clean stale state for specific polecat.
```
gt cleanup <rig>/<polecat> [--dry-run]
```

Actions:
- Remove orphaned state.json if clone missing
- Clear stale session references
- Reset stuck state (working → idle after timeout)

### gt cleanup --all
Clean all polecats in workspace.
```
gt cleanup --all [--dry-run]
```

## Implementation
```go
func CleanupPolecat(rigName, polecatName string, dryRun bool) (*CleanupResult, error)

type CleanupResult struct {
    OrphanedStateRemoved bool
    SessionsCleared      int
    StateReset           bool
    Warnings             []string
}
```

## Overlap with Doctor
- Doctor diagnoses and offers --fix
- Cleanup is more aggressive state recovery
- Consider merging into doctor --fix

## New File
internal/cmd/cleanup.go

## Acceptance Criteria
- [ ] Removes orphaned state files
- [ ] Clears stale session refs
- [ ] --dry-run shows what would happen
- [ ] Reports all actions taken


Digest: mol-deacon-patrol

Patrol 20: final check, all healthy, handoff threshold


mol-deacon-patrol

Mayor's daemon patrol loop.

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


Polecat Arm (arm-toast)

Single polecat inspection and action cycle.

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

## Variables

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

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

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

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

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

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

Calculate: minutes since last activity.
Needs: capture

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

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

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

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

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

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

Record decision and rationale.
Needs: load-history

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

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

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

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

**none**: No action needed.

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

## Output

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

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


Digest: mol-deacon-patrol

Patrol 5: All agents healthy, routine


Test Patrol Parent

Test parent for Christmas Ornament pattern


Merge: gt-odvf

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


Agent parking and resuming

Implement gt park and gt resume commands. Agent parks work on a gate, state persists across sessions. When gate condition met, Deacon sends wake mail. Agent resumes from parked state. Critical for async workflows.


Digest: mol-deacon-patrol

Patrol cycle 6: routine


Load context

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

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


Merge: gt-92l

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


Test Patrol for Bonding

Parent issue for mol bond CLI test


gt status should show runtime state, not just structure

## Problem
`gt status` shows structural info (which crews exist) but not runtime reality (which sessions are running).

## Current Output
- Shows 'Crews: [dave emma zoey]' but doesn't indicate dave is crashed
- Missing Deacon from output entirely
- Hooks shown but unclear if agents are alive

## Expected
- Show which tmux sessions are actually running
- Indicate crashed/missing sessions with warning
- Include all roles (Mayor, Deacon, Witnesses, Refineries, Crews)
- Distinguish between:
  - Structure: what COULD run
  - Runtime: what IS running

## Example Better Output
```
Agents
   mayor          ✓ running (gt-mayor)
   deacon         ✓ running (gt-deacon)

Rigs
   beads
      witness     ✓ running
      refinery    ✓ running
      crew/dave   ✗ CRASHED (session missing)
      crew/emma   ✓ running
   gastown
      witness     ✓ running
      refinery    ✓ running
      crew/max    ✗ CRASHED (session missing)
```


Merge: gt-svi.1

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


Recover stale polecat work: 4 branches with unpushed commits

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

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

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

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


Document bd mol bond/squash/burn CLI

Create CLI reference documentation for molecule commands:

## bd mol bond

Instantiate a proto into a runnable molecule.

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

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

## bd mol squash

Complete a molecule and generate digest.

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

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

## bd mol burn

Abandon a molecule without completing.

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

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


Digest: mol-deacon-patrol

Patrol 19: Mayor OK, 11 sessions


Digest: mol-deacon-patrol

Patrol cycle 14: nominal


mol-deacon-patrol


gt mail reply/thread: Conversation support

Add mail conversation features:

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

Enables back-and-forth communication between agents.


Simplify Go daemon to Deacon-watcher

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


Digest: mol-deacon-patrol

Patrol 20: All healthy - handoff threshold reached


Git wrapper: shell out to git

Wrapper for git operations via subprocess.

## Interface

```go
type Git struct {
    workDir string
}

func NewGit(workDir string) *Git

// Core operations
func (g *Git) Clone(url, dest string) error
func (g *Git) Checkout(ref string) error
func (g *Git) Fetch(remote string) error
func (g *Git) Pull(remote, branch string) error
func (g *Git) Push(remote, branch string, force bool) error

// Commit operations
func (g *Git) Add(paths ...string) error
func (g *Git) Commit(message string) error
func (g *Git) CommitAll(message string) error

// Query operations
func (g *Git) Status() (*GitStatus, error)
func (g *Git) CurrentBranch() (string, error)
func (g *Git) HasUncommittedChanges() (bool, error)
func (g *Git) RemoteURL(remote string) (string, error)

// Merge operations
func (g *Git) Merge(branch string) error
func (g *Git) Rebase(onto string) error
func (g *Git) AbortMerge() error
func (g *Git) AbortRebase() error
```

## Implementation

Shell out to git binary via exec.Command. Parse output where needed (Status, CurrentBranch).

## Error Handling

- Wrap git stderr in error messages
- Detect specific failures (merge conflict, auth failure, not a repo)
- Return structured errors for callers to handle

## Testing

- Use temp directories with real git repos
- Test both success and failure paths


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