## 1. Project Overview & Quickstart (gastownhall/gastown)

## File: README.md

# Gas Town

**Multi-agent orchestration system for Claude Code, GitHub Copilot, and other AI agents with persistent work tracking**

## Overview

Gas Town is a workspace manager that lets you coordinate multiple AI coding agents (Claude Code, GitHub Copilot, Codex, Gemini, and others) working on different tasks. Instead of losing context when agents restart, Gas Town persists work state in git-backed hooks, enabling reliable multi-agent workflows.

### What Problem Does This Solve?

| Challenge                       | Gas Town Solution                            |
| ------------------------------- | -------------------------------------------- |
| Agents lose context on restart  | Work persists in git-backed hooks            |
| Manual agent coordination       | Built-in mailboxes, identities, and handoffs |
| 4-10 agents become chaotic      | Scale comfortably to 20-30 agents            |
| Work state lost in agent memory | Work state stored in Beads ledger            |

### Architecture

```mermaid
graph TB
    Mayor[The MayorAI Coordinator]
    Town[Town Workspace~/gt/]

    Town --> Mayor
    Town --> Rig1[Rig: Project A]
    Town --> Rig2[Rig: Project B]

    Rig1 --> Crew1[Crew MemberYour workspace]
    Rig1 --> Hooks1[HooksPersistent storage]
    Rig1 --> Polecats1[PolecatsWorker agents]

    Rig2 --> Crew2[Crew Member]
    Rig2 --> Hooks2[Hooks]
    Rig2 --> Polecats2[Polecats]

    Hooks1 -.git worktree.-> GitRepo1[Git Repository]
    Hooks2 -.git worktree.-> GitRepo2[Git Repository]

    style Mayor fill:#e1f5ff,color:#000000
    style Town fill:#f0f0f0,color:#000000
    style Rig1 fill:#fff4e1,color:#000000
    style Rig2 fill:#fff4e1,color:#000000
```

## Core Concepts

### The Mayor 🎩

Your primary AI coordinator. The Mayor is a Claude Code instance with full context about your workspace, projects, and agents. **Start here** - just tell the Mayor what you want to accomplish.

### Town 🏘️

Your workspace directory (e.g., `~/gt/`). Contains all projects, agents, and configuration.

### Rigs 🏗️

Project containers. Each rig wraps a git repository and manages its associated agents.

### Crew Members 👤

Your personal workspace within a rig. Where you do hands-on work.

### Polecats 🦨

Worker agents with persistent identity but ephemeral sessions. Spawned for tasks, sessions end on completion, but identity and work history persist.

### Hooks 🪝

Git worktree-based persistent storage for agent work. Survives crashes and restarts.

### Convoys 🚚

Work tracking units. Bundle multiple beads that get assigned to agents. Convoys labeled `mountain` get autonomous stall detection and smart skip logic for epic-scale execution.

### Beads Integration 📿

Git-backed issue tracking system that stores work state as structured data.

**Bead IDs** (also called **issue IDs**) use a prefix + 5-character alphanumeric format (e.g., `gt-abc12`, `hq-x7k2m`). The prefix indicates the item's origin or rig. Commands like `gt sling` and `gt convoy` accept these IDs to reference specific work items. The terms "bead" and "issue" are used interchangeably—beads are the underlying data format, while issues are the work items stored as beads.

### Molecules 🧬

Workflow templates that coordinate multi-step work. Formulas (TOML definitions) are instantiated as molecules with tracked steps. Two modes: root-only wisps (steps materialized at runtime, lightweight) and poured wisps (steps materialized as sub-wisps with checkpoint recovery). See [Molecules](docs/concepts/molecules.md).

### Monitoring: Witness, Deacon, Dogs 🐕

A three-tier watchdog system keeps agents healthy:

- **Witness** - Per-rig lifecycle manager. Monitors polecats, detects stuck agents, triggers recovery, manages session cleanup.
- **Deacon** - Background supervisor running continuous patrol cycles across all rigs.
- **Dogs** - Infrastructure workers dispatched by the Deacon for maintenance tasks (e.g., Boot for triage).

### Refinery 🏭

Per-rig merge queue processor. When polecats complete work via `gt done`, the Refinery batches merge requests, runs verification gates, and merges to main using a Bors-style bisecting queue. Failed MRs are isolated and either fixed inline or re-dispatched.

### Escalation 🚨

Severity-routed issue escalation. Agents that hit blockers escalate via `gt escalate`, which creates tracked beads routed through the Deacon, Mayor, and (if needed) Overseer. Severity levels: CRITICAL (P0), HIGH (P1), MEDIUM (P2). See [Escalation](docs/design/escalation.md).

### Scheduler ⏱️

Config-driven capacity governor for polecat dispatch. Prevents API rate limit exhaustion by batching dispatch under configurable concurrency limits. Default is direct dispatch; set `scheduler.max_polecats` to enable deferred dispatch with the daemon. See [Scheduler](docs/design/scheduler.md).

### Seance 👻

Session discovery and continuation. Discovers previous agent sessions via `.events.jsonl` logs, enabling agents to query their predecessors for context and decisions from earlier work.

```bash
gt seance                       # List discoverable predecessor sessions
gt seance --talk  -p "What did you find?"  # One-shot question
```

### Wasteland 🏜️

Federated work coordination network linking Gas Towns through DoltHub. Rigs post wanted items, claim work from other towns, submit completion evidence, and earn portable reputation via multi-dimensional stamps. See [Wasteland](docs/WASTELAND.md).

> **New to Gas Town?** See the [Glossary](docs/glossary.md) for a complete guide to terminology and concepts.

## Installation

Choose one of the two setup paths below: install Gas Town on your host, or run it inside a Docker container.

### Prerequisites

Native installs require the host tools below. Docker installs only require Docker Compose on the host; the image supplies Go, Dolt, `bd`, tmux, and CLI utilities inside the container. The platform steps below say when a path installs `gt`, `bd`, and `dolt` for you and when you install them separately.

| Tool | Version | Notes |
|---|---|---|
| Git | 2.20+ | Worktree support |
| Go | 1.26.2+ (see `go.mod`) | Required for the Linux and Windows paths and for macOS source builds. Not needed for `brew install gastown` or Docker setup. |
| Beads (`bd`) | 0.57.0+ | Required for native installs. Homebrew and Docker supply it; source/native Go paths install it with `go install`. |
| sqlite3 | any | Used by convoy database queries. Usually pre-installed on macOS and Linux. |
| ICU4C dev headers | varies | Required for source builds that compile the ICU-backed query layer. Use `libicu-dev` on Debian/Ubuntu, `libicu-devel` on Fedora/RHEL, `icu4c` on macOS, and MSYS2 ICU packages for native Windows. |
| tmux | 3.0+ | Required for `gt up` and the tmux-backed roles (Mayor, Witnesses, Refineries, polecats). Optional only for minimal-mode workflows where you run runtime instances manually. |
| Claude Code CLI | latest | Default runtime. See [Runtime Configuration](#runtime-configuration) for alternatives (Codex, Copilot, Gemini, Cursor). |

### Local setup

Install the prerequisites listed above, then install `gt` for your platform.

#### Install gt on macOS

Homebrew installs `gt`, `bd`, and `dolt` together.

```bash
brew install gastown
```

Avoid `go install` on macOS. The unsigned binary it produces gets killed by Gatekeeper. To build from source, install Dolt and ICU4C with Homebrew, install `bd` with Go, then build and install `gt` with `make install`. Put `$HOME/.local/bin` and `$HOME/go/bin` ahead of any stale binary locations on your `PATH` so the freshly installed `gt` and `bd` take precedence.

```bash
brew install dolt icu4c
go install github.com/steveyegge/beads/cmd/bd@latest
export PATH="$HOME/.local/bin:$HOME/go/bin:$PATH"
git clone https://github.com/steveyegge/gastown.git
cd gastown
make install
```

#### Install gt on Linux

Install Dolt by following the [Dolt installation guide](https://github.com/dolthub/dolt#installation), then install `gt` and `bd` with `go install`.

```bash
go install github.com/steveyegge/gastown/cmd/gt@latest
go install github.com/steveyegge/beads/cmd/bd@latest
```

Prepend the Go binary directory to your `PATH` if it is not already there, so freshly installed `gt` and `bd` binaries take precedence over stale copies. Append to `~/.zshrc` instead if you use zsh.

```bash
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

#### Install gt on Windows

Install Dolt first by following the [Dolt installation guide](https://github.com/dolthub/dolt#installation). Unlike the macOS Homebrew path, `go install` does not install Dolt. Then install `gt` and `bd` with `go install`.

```powershell
go install github.com/steveyegge/gastown/cmd/gt@latest
go install github.com/steveyegge/beads/cmd/bd@latest
```

Both binaries land in `%USERPROFILE%\go\bin\`. Put that directory before older `gt` or `bd` install locations on `PATH`, then open a new shell for the change to take effect.

Native Windows source builds that compile the ICU-backed query layer need an MSYS2 UCRT64 or MinGW64 shell with matching `icu`, `toolchain`, and `pkg-config` packages; the repository's Windows CI uses `pacboy -S icu:p toolchain:p pkg-config:p`. Plain PowerShell/MSVC is not enough for that CGO build.

For full tmux-backed workflows on Windows, use WSL or another Linux environment. Native Windows shells are best treated as minimal CLI-only environments.

#### Create your workspace

Run `gt install` to create your headquarters (HQ) at `~/gt`. The `--shell` flag installs shell integration and enables Gas Town globally. The `--git` flag initializes the HQ as a git repository. Before using `--git`, set `git config --global user.name` and `git config --global user.email` so the initial commit has a valid identity.

```bash
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
gt install ~/gt --shell --git
cd ~/gt
```

Start the long-lived services. `gt up` boots Dolt, the daemon, the Deacon, the Mayor, and per-rig Witnesses and Refineries.

```bash
gt up
```

Verify the install. The `--fix` flag clears the warnings that `gt install` does not preempt.

```bash
gt doctor --fix
```

#### Add a project

Use `gt rig add` to clone a repository into your HQ as a rig.

```bash
gt rig add myproject https://github.com/you/repo.git
```

Rig names accept letters, digits, and underscores. Hyphens, dots, spaces, and path separators are not allowed. Use `my_project` instead of `my-project`.

To set a custom beads prefix for the rig, pass `--prefix`.

```bash
gt rig add myproject https://github.com/you/repo.git --prefix mp
```

#### Create your crew workspace

A crew workspace is a personal git clone where you do hands-on work.

```bash
gt crew add yourname --rig myproject
cd myproject/crew/yourname
```

#### Start the Mayor

The Mayor coordinates work across rigs.

```bash
gt mayor attach
```

### Docker Compose setup

`docker-compose.yml` runs Gas Town inside a sandbox container. The container hosts an HQ at `/gt`, which Compose bind-mounts from `${FOLDER}` on the host. The entrypoint runs `gt install /gt --git` against that directory on first start, so `FOLDER` must point at an empty directory that you want to become the HQ or an existing Gas Town HQ. Set `GIT_USER` and `GIT_EMAIL` so git and Dolt commits do not use the default test identity. See the full [Docker guide](docs/docker.md) for lifecycle, storage, and security details.

```bash
export GIT_USER="<your name>"
export GIT_EMAIL="<your email>"
export FOLDER="/path/to/empty/dir"   # empty directory or existing Gas Town HQ
export DASHBOARD_PORT=8080           # optional, host port for the dashboard

mkdir -p "$FOLDER"
docker compose build              # only needed on first run or after code changes
docker compose up -d
docker compose logs -f gastown    # wait for "HQ created successfully!", then Ctrl-C

docker compose exec gastown zsh   # or bash
```

Inside the container, finish bootstrapping.

```bash
gt enable                         # enable Gas Town global state
gt shell install                  # install shell integration
gt up --restore                   # start services and restore worker settings
gh auth login                     # optional: required for private GitHub rigs
gt mayor attach
```

The dashboard port is exposed from the container to the host. Treat it as a trusted local-network surface, and do not point `FOLDER` at a host workspace that a native `gt` install is using at the same time.

## Quick Start Guide

### Getting Started
Run
```shell
git config --global user.name "Your Name" &&
git config --global user.email "you@example.com" &&
gt install ~/gt --shell --git &&
cd ~/gt &&
gt up &&
gt doctor --fix &&
gt config agent list &&
gt mayor attach
```
and tell the Mayor what you want to build!

---

### Basic Workflow

```mermaid
sequenceDiagram
    participant You
    participant Mayor
    participant Convoy
    participant Agent
    participant Hook

    You->>Mayor: Tell Mayor what to build
    Mayor->>Convoy: Create convoy with beads
    Mayor->>Agent: Sling bead to agent
    Agent->>Hook: Store work state
    Agent->>Agent: Complete work
    Agent->>Convoy: Report completion
    Mayor->>You: Summary of progress
```

### Example: Feature Development

```bash
# 1. Start the Mayor
gt mayor attach

# 2. In Mayor session, create a convoy with bead IDs
gt convoy create "Feature X" gt-abc12 gt-def34 --notify --human

# 3. Assign work to an agent
gt sling gt-abc12 myproject

# 4. Track progress
gt convoy list

# 5. Monitor agents
gt agents
```

## Common Workflows

### Mayor Workflow (Recommended)

**Best for:** Coordinating complex, multi-issue work

```mermaid
flowchart LR
    Start([Start Mayor]) --> Tell[Tell Mayorwhat to build]
    Tell --> Creates[Mayor createsconvoy + agents]
    Creates --> Monitor[Monitor progressvia convoy list]
    Monitor --> Done{All done?}
    Done -->|No| Monitor
    Done -->|Yes| Review[Review work]
```

**Commands:**

```bash
# Attach to Mayor
gt mayor attach

# In Mayor, create convoy and let it orchestrate
gt convoy create "Auth System" gt-x7k2m gt-p9n4q --notify

# Track progress
gt convoy list
```

### Minimal Mode (No Tmux)

Run individual runtime instances manually. Gas Town just tracks state.

```bash
gt convoy create "Fix bugs" gt-abc12   # Create convoy (sling auto-creates if skipped)
gt sling gt-abc12 myproject            # Assign to worker
claude --resume                        # Agent reads mail, runs work (Claude)
# or: codex                            # Start Codex in the workspace
gt convoy list                         # Check progress
```

### Beads Formula Workflow

**Best for:** Predefined, repeatable processes

Formulas are TOML-defined workflows embedded in the `gt` binary (source in `internal/formula/formulas/`).

**Example Formula** (`internal/formula/formulas/release.formula.toml`):

```toml
description = "Standard release process"
formula = "release"
version = 1

[vars.version]
description = "The semantic version to release (e.g., 1.2.0)"
required = true

[[steps]]
id = "bump-version"
title = "Bump version"
description = "Run ./scripts/bump-version.sh {{version}}"

[[steps]]
id = "run-tests"
title = "Run tests"
description = "Run make test"
needs = ["bump-version"]

[[steps]]
id = "build"
title = "Build"
description = "Run make build"
needs = ["run-tests"]

[[steps]]
id = "create-tag"
title = "Create release tag"
description = "Run git tag -a v{{version}} -m 'Release v{{version}}'"
needs = ["build"]

[[steps]]
id = "publish"
title = "Publish"
description = "Run ./scripts/publish.sh"
needs = ["create-tag"]
```

**Execute:**

```bash
# List available formulas
bd formula list

# Run a formula with variables
bd cook release --var version=1.2.0

# Create formula instance for tracking
bd mol pour release --var version=1.2.0
```

### Manual Convoy Workflow

**Best for:** Direct control over work distribution

```bash
# Create convoy manually
gt convoy create "Bug Fixes" --human

# Add issues to existing convoy
gt convoy add hq-cv-abc gt-m3k9p gt-w5t2x

# Assign to specific agents
gt sling gt-m3k9p myproject/my-agent

# Check status
gt convoy show
```

## Runtime Configuration

Gas Town supports multiple AI coding runtimes. Per-rig runtime settings are in `settings/config.json`.

```json
{
  "runtime": {
    "provider": "codex",
    "command": "codex",
    "args": [],
    "prompt_mode": "none"
  }
}
```

**Notes:**

- Claude uses hooks in `.claude/settings.json` (managed via `--settings` flag) for mail injection and startup.
- For Codex, set `project_doc_fallback_filenames = ["CLAUDE.md"]` in
  `~/.codex/config.toml` so role instructions are picked up.
- For runtimes without hooks (e.g., Codex), Gas Town sends a startup fallback
  after the session is ready: `gt prime`, optional `gt mail check --inject`
  for autonomous roles, and `gt nudge deacon session-started`.
- **GitHub Copilot** (`copilot`) is a built-in preset using `--yolo` for autonomous
  mode. It uses executable lifecycle hooks in `.github/hooks/gastown.json` (same events
  as Claude: `sessionStart`, `userPromptSubmitted`, `preToolUse`, `sessionEnd`). Uses a
  5-second ready delay instead of prompt detection. Requires a Copilot seat and org-level
  CLI policy. See [docs/INSTALLING.md](docs/INSTALLING.md).

## Key Commands

### Workspace Management

```bash
gt install            # Initialize workspace
gt rig add <name> <repo>    # Add project
gt rig list                 # List projects
gt crew add <name> --rig <rig>  # Create crew workspace
```

### Agent Operations

```bash
gt agents                   # List active agents
gt sling  <rig>    # Assign work to agent
gt sling  <rig> --agent cursor   # Override runtime for this sling/spawn
gt mayor attach             # Start Mayor session
gt mayor start --agent auggie           # Run Mayor with a specific agent alias
gt prime                    # Context recovery (run inside existing session)
gt feed                     # Real-time activity feed (TUI)
gt feed --problems          # Start in problems view (stuck agent detection)
```

**Built-in agent presets**: `claude`, `gemini`, `codex`, `kiro`, `cursor`, `auggie`, `amp`, `opencode`, `copilot`, `pi`, `omp`

The `kiro` preset launches `kiro-cli chat --trust-all-tools`, supports Kiro's
documented `--resume` / `--resume-id` session flags, and does not install Kiro
hooks or `.kiro` project files.

### Convoy (Work Tracking)

```bash
gt convoy create <name> [issues...]   # Create convoy with issues
gt convoy list              # List all convoys
gt convoy show [id]         # Show convoy details
gt convoy add <convoy-id>   # Add issues to convoy
```

### Configuration

```bash
# Set custom agent command
gt config agent set claude-glm "claude-glm --model glm-4"
gt config agent set codex-low "codex --thinking low"

# Set default agent
gt config default-agent claude-glm
```

### Monitoring & Health

```bash
gt escalate -s HIGH "description"  # Escalate a blocker
gt escalate list               # List open escalations
gt scheduler status            # Show scheduler state
gt seance                      # Discover previous sessions
gt seance --talk           # Query a predecessor session
```

### Beads Integration

```bash
bd formula list             # List formulas
bd cook <formula>           # Execute formula
bd mol pour <formula>       # Create trackable instance
bd mol list                 # List active instances
```

### Wasteland Federation

```bash
gt wl join <remote>            # Join a wasteland
gt wl browse                   # View wanted board
gt wl claim                # Claim work
gt wl done  --evidence   # Submit completion
```

## Cooking Formulas

Gas Town includes built-in formulas for common workflows. See `internal/formula/formulas/` for available recipes.

## Activity Feed

`gt feed` launches an interactive terminal dashboard for monitoring all agent activity in real-time. It combines beads activity, agent events, and merge queue updates into a three-panel TUI:

- **Agent Tree** - Hierarchical view of all agents grouped by rig and role
- **Convoy Panel** - In-progress and recently-landed convoys
- **Event Stream** - Chronological feed of creates, completions, slings, nudges, and more

```bash
gt feed                      # Launch TUI dashboard
gt feed --problems           # Start in problems view
gt feed --plain              # Plain text output (no TUI)
gt feed --window             # Open in dedicated tmux window
gt feed --since 1h           # Events from last hour
```

**Navigation:** `j`/`k` to scroll, `Tab` to switch panels, `1`/`2`/`3` to jump to a panel, `?` for help, `q` to quit.

### Problems View

At scale (20-50+ agents), spotting stuck agents in the activity stream becomes difficult. The problems view surfaces agents needing human intervention by analyzing structured beads data.

Press `p` in `gt feed` (or start with `gt feed --problems`) to toggle the problems view, which groups agents by health state:

| State | Condition |
|-------|-----------|
| **GUPP Violation** | Hooked work with no progress for an extended period |
| **Stalled** | Hooked work with reduced progress |
| **Zombie** | Dead tmux session |
| **Working** | Active, progressing normally |
| **Idle** | No hooked work |

**Intervention keys** (in problems view): `n` to nudge the selected agent, `h` to handoff (refresh context).

## Dashboard

Gas Town includes a web dashboard for monitoring your workspace. The dashboard
must be run from inside a Gas Town workspace (HQ) directory.

```bash
# Start dashboard (default port 8080)
gt dashboard

# Start on a custom port
gt dashboard --port 3000

# Start and automatically open in browser
gt dashboard --open
```

The dashboard gives you a single-page overview of everything happening in your
workspace: agents, convoys, hooks, queues, issues, and escalations. It
auto-refreshes via htmx and includes a command palette for running gt commands
directly from the browser.

## Monitoring & Health

Gas Town uses a three-tier watchdog chain to keep agents healthy at scale:

```
Daemon (Go process) ← heartbeat every 3 min
    └── Boot (AI agent) ← intelligent triage
        └── Deacon (AI agent) ← continuous patrol
            └── Witnesses & Refineries ← per-rig agents
```

### Witness (Per-Rig)

Each rig has a Witness that monitors its polecats. The Witness detects stuck agents, triggers recovery (nudge or handoff), manages session cleanup, and tracks completion. Witnesses delegate work rather than implementing it directly.

### Deacon (Cross-Rig)

The Deacon runs continuous patrol cycles across all rigs, checking agent health, dispatching Dogs for maintenance tasks, and escalating issues that individual Witnesses can't resolve.

### Escalation

When agents hit blockers, they escalate rather than waiting:

```bash
gt escalate -s HIGH "Description of blocker"
gt escalate list                    # List open escalations
gt escalate ack            # Acknowledge an escalation
```

Escalations route through Deacon -> Mayor -> Overseer based on severity. See [Escalation design](docs/design/escalation.md).

## Merge Queue (Refinery)

The Refinery processes completed polecat work through a bisecting merge queue:

1. Polecat runs `gt done` -> branch pushed, MR bead created
2. Refinery batches pending MRs
3. Runs verification gates on the merged stack
4. If green: all MRs in batch merge to main
5. If red: bisects to isolate the failing MR, merges the good ones

This is a Bors-style merge queue — polecats never push directly to main.

## Scheduler

The scheduler controls polecat dispatch capacity to prevent API rate limit exhaustion:

```bash
gt config set scheduler.max_polecats 5   # Enable deferred dispatch (max 5 concurrent)
gt scheduler status                      # Show scheduler state
gt scheduler pause                       # Pause dispatch
gt scheduler resume                      # Resume dispatch
```

Default mode (`max_polecats = -1`) dispatches immediately via `gt sling`. When a limit is set, the daemon dispatches incrementally, respecting capacity. See [Scheduler design](docs/design/scheduler.md).

## Seance

Discover and query previous agent sessions:

```bash
gt seance                              # List discoverable predecessor sessions
gt seance --talk                   # Full context conversation with predecessor
gt seance --talk  -p "Question?"   # One-shot question to predecessor
```

Seance discovers sessions via `.events.jsonl` logs, enabling agents to recover context and decisions from earlier work without re-reading entire codebases.

## Wasteland Federation

The Wasteland is a federated work coordination network linking multiple Gas Towns through DoltHub:

```bash
gt wl join hop/wl-commons              # Join a wasteland
gt wl browse                           # View wanted board
gt wl claim                        # Claim a wanted item
gt wl done  --evidence        # Submit completion with evidence
gt wl post --title "Need X"            # Post new wanted item
```

Completions earn portable reputation via multi-dimensional stamps (quality, speed, complexity). See [Wasteland guide](docs/WASTELAND.md).

## Telemetry (OpenTelemetry)

Gas Town emits all agent operations as structured logs and metrics to any OTLP-compatible backend (VictoriaMetrics/VictoriaLogs by default):

```bash
# Configure OTLP endpoints
export GT_OTEL_LOGS_URL="http://localhost:9428/insert/jsonline"
export GT_OTEL_METRICS_URL="http://localhost:8428/api/v1/write"
```

**Events emitted:** session lifecycle, agent state changes, bd calls with duration, mail operations, sling/nudge/done workflows, polecat spawn/remove, formula instantiation, convoy creation, daemon restarts, and more.

**Metrics include:** `gastown.session.starts.total`, `gastown.bd.calls.total`, `gastown.polecat.spawns.total`, `gastown.done.total`, `gastown.convoy.creates.total`, and others.

See [OTEL data model](docs/otel-data-model.md) and [OTEL architecture](docs/design/otel/) for the complete event schema.

## Advanced Concepts

### The Propulsion Principle

Gas Town uses git hooks as a propulsion mechanism. Each hook is a git worktree with:

1. **Persistent state** - Work survives agent restarts
2. **Version control** - All changes tracked in git
3. **Rollback capability** - Revert to any previous state
4. **Multi-agent coordination** - Shared through git

### Hook Lifecycle

```mermaid
stateDiagram-v2
    [*] --> Created: Agent spawned
    Created --> Active: Work assigned
    Active --> Suspended: Agent paused
    Suspended --> Active: Agent resumed
    Active --> Completed: Work done
    Completed --> Archived: Hook archived
    Archived --> [*]
```

### MEOW (Mayor-Enhanced Orchestration Workflow)

MEOW is the recommended pattern:

1. **Tell the Mayor** - Describe what you want
2. **Mayor analyzes** - Breaks down into tasks
3. **Convoy creation** - Mayor creates convoy with beads
4. **Agent spawning** - Mayor spawns appropriate agents
5. **Work distribution** - Beads slung to agents via hooks
6. **Progress monitoring** - Track through convoy status
7. **Completion** - Mayor summarizes results

## Shell Completions

```bash
# Bash
gt completion bash > /etc/bash_completion.d/gt

# Zsh
gt completion zsh > "${fpath[1]}/_gt"

# Fish
gt completion fish > ~/.config/fish/completions/gt.fish
```

## Project Roles

| Role            | Description                          | Primary Interface    |
| --------------- | ------------------------------------ | -------------------- |
| **Mayor**       | AI coordinator                       | `gt mayor attach`    |
| **Human (You)** | Crew member                          | Your crew directory  |
| **Polecat**     | Worker agent                         | Spawned by Mayor     |
| **Witness**     | Per-rig agent health monitor         | Automatic patrol     |
| **Deacon**      | Cross-rig supervisor daemon          | `gt patrol`          |
| **Refinery**    | Merge queue processor                | Automatic            |
| **Hook**        | Persistent storage                   | Git worktree         |
| **Convoy**      | Work tracker                         | `gt convoy` commands |

## Tips

- **Always start with the Mayor** - It's designed to be your primary interface
- **Use convoys for coordination** - They provide visibility across agents
- **Leverage hooks for persistence** - Your work won't disappear
- **Create formulas for repeated tasks** - Save time with Beads recipes
- **Use `gt feed` for live monitoring** - Watch agent activity and catch stuck agents early
- **Monitor the dashboard** - Get real-time visibility in the browser
- **Let the Mayor orchestrate** - It knows how to manage agents

## Design Documentation

For deeper technical details, see the design docs in `docs/`:

| Topic | Document |
|-------|----------|
| Architecture | [docs/design/architecture.md](docs/design/architecture.md) |
| Glossary | [docs/glossary.md](docs/glossary.md) |
| Molecules | [docs/concepts/molecules.md](docs/concepts/molecules.md) |
| Escalation | [docs/design/escalation.md](docs/design/escalation.md) |
| Scheduler | [docs/design/scheduler.md](docs/design/scheduler.md) |
| Wasteland | [docs/WASTELAND.md](docs/WASTELAND.md) |
| OTEL data model | [docs/otel-data-model.md](docs/otel-data-model.md) |
| Witness design | [docs/design/witness-at-team-lead.md](docs/design/witness-at-team-lead.md) |
| Convoy lifecycle | [docs/design/convoy/](docs/design/convoy/) |
| Polecat lifecycle | [docs/design/polecat-lifecycle-patrol.md](docs/design/polecat-lifecycle-patrol.md) |
| Plugin system | [docs/design/plugin-system.md](docs/design/plugin-system.md) |
| Agent providers | [docs/agent-provider-integration.md](docs/agent-provider-integration.md) |
| Hooks | [docs/HOOKS.md](docs/HOOKS.md) |
| Installation guide | [docs/INSTALLING.md](docs/INSTALLING.md) |
| Docker guide | [docs/docker.md](docs/docker.md) |

## Troubleshooting

### Agents lose connection

Check hooks are properly initialized:

```bash
gt hooks list
gt hooks repair
```

### Convoy stuck

Force refresh:

```bash
gt convoy refresh <convoy-id>
```

### Mayor not responding

Restart Mayor session:

```bash
gt mayor detach
gt mayor attach
```

## License

MIT License - see LICENSE file for details

---

## File: docs/concepts/convoy.md

# Convoys

Convoys are the primary unit for tracking batched work across rigs.

## Quick Start

```bash
# Create a convoy tracking some issues
gt convoy create "Feature X" gt-abc gt-def --notify overseer

# Check progress
gt convoy status hq-cv-abc

# List active convoys (the dashboard)
gt convoy list

# See all convoys including landed ones
gt convoy list --all
```

## Concept

A **convoy** is a persistent tracking unit that monitors related issues across
multiple rigs. When you kick off work - even a single issue - a convoy tracks it
so you can see when it lands and what was included.

```
                 🚚 Convoy (hq-cv-abc)
                         │
            ┌────────────┼────────────┐
            │            │            │
            ▼            ▼            ▼
       ┌─────────┐  ┌─────────┐  ┌─────────┐
       │ gt-xyz  │  │ gt-def  │  │ bd-abc  │
       │ gastown │  │ gastown │  │  beads  │
       └────┬────┘  └────┬────┘  └────┬────┘
            │            │            │
            ▼            ▼            ▼
       ┌─────────┐  ┌─────────┐  ┌─────────┐
       │  nux    │  │ furiosa │  │  amber  │
       │(polecat)│  │(polecat)│  │(polecat)│
       └─────────┘  └─────────┘  └─────────┘
                         │
                    "the swarm"
                    (ephemeral)
```

## Convoy vs Swarm

| Concept | Persistent? | ID | Description |
|---------|-------------|-----|-------------|
| **Convoy** | Yes | hq-cv-* | Tracking unit. What you create, track, get notified about. |
| **Swarm** | No | None | Ephemeral. "The workers currently on this convoy's issues." |
| **Stranded Convoy** | Yes | hq-cv-* | A convoy with ready work but no polecats assigned. Needs attention. |

When you "kick off a swarm", you're really:
1. Creating a convoy (the tracking unit)
2. Assigning polecats to the tracked issues
3. The "swarm" is just those polecats while they're working

When issues close, the convoy lands and notifies you. The swarm dissolves.

## Convoy Lifecycle

```
OPEN ──(all issues close)──► LANDED/CLOSED
  ↑                              │
  └──(add more issues)───────────┘
       (auto-reopens)
```

| State | Description |
|-------|-------------|
| `open` | Active tracking, work in progress |
| `closed` | All tracked issues closed, notification sent |

Adding issues to a closed convoy reopens it automatically.

## Commands

### Create a Convoy

```bash
# Track multiple issues across rigs
gt convoy create "Deploy v2.0" gt-abc bd-xyz --notify gastown/joe

# Track a single issue (still creates convoy for dashboard visibility)
gt convoy create "Fix auth bug" gt-auth-fix

# With default notification (from config)
gt convoy create "Feature X" gt-a gt-b gt-c
```

### Add Issues

```bash
# Add issues to existing convoy
gt convoy add hq-cv-abc gt-new-issue
gt convoy add hq-cv-abc gt-issue1 gt-issue2 gt-issue3

# Adding to closed convoy requires reopening first
bd update hq-cv-abc --status=open
gt convoy add hq-cv-abc gt-followup-fix
```

### Check Status

```bash
# Show issues and active workers (the swarm)
gt convoy status hq-abc

# All active convoys (the dashboard)
gt convoy status
```

Example output:
```
🚚 hq-cv-abc: Deploy v2.0

  Status:    ●
  Progress:  2/4 completed
  Created:   2025-12-30T10:15:00-08:00

  Tracked Issues:
    ✓ gt-xyz: Update API endpoint [task]
    ✓ bd-abc: Fix validation [bug]
    ○ bd-ghi: Update docs [task]
    ○ gt-jkl: Deploy to prod [task]
```

### List Convoys (Dashboard)

```bash
# Active convoys (default) - the primary attention view
gt convoy list

# All convoys including landed
gt convoy list --all

# Only landed convoys
gt convoy list --status=closed

# JSON output
gt convoy list --json
```

Example output:
```
Convoys

  🚚 hq-cv-w3nm6: Feature X ●
  🚚 hq-cv-abc12: Bug fixes ●

Use 'gt convoy status ' for detailed view.
```

## Notifications

When a convoy lands (all tracked issues closed), subscribers are notified:

```bash
# Explicit subscriber
gt convoy create "Feature X" gt-abc --notify gastown/joe

# Multiple subscribers
gt convoy create "Feature X" gt-abc --notify mayor/ --notify --human
```

Notification content:
```
🚚 Convoy Landed: Deploy v2.0 (hq-cv-abc)

Issues (3):
  ✓ gt-xyz: Update API endpoint
  ✓ gt-def: Add validation
  ✓ bd-abc: Update docs

Duration: 2h 15m
```

## Create from Epic

Auto-discover tracked issues from an existing epic's children. Useful when
a planning/decomposition tool has already structured work as an epic with
child implementation beads.

```bash
# Auto-discover children from epic
gt convoy create --from-epic gt-epic-abc

# Override the convoy name (defaults to epic title)
gt convoy create --from-epic gt-epic-abc "Custom convoy name"

# Combine with other flags
gt convoy create --from-epic gt-epic-abc --owned --merge=direct
```

**How it works:**
1. Verifies the given bead is an epic
2. BFS-walks the parent-child hierarchy to find slingable descendants
3. Creates a standard convoy (`hq-cv-*`) tracking all slingable children (task, bug, feature, chore)

Non-slingable types (sub-epics, decisions) are recursed into but never
tracked directly. Only leaf work items appear in the convoy.

## Auto-Convoy on Sling

When you sling a single issue without an existing convoy:

```bash
gt sling bd-xyz beads/amber
```

This auto-creates a convoy so all work appears in the dashboard:
1. Creates convoy: "Work: bd-xyz"
2. Tracks the issue
3. Assigns the polecat

Even "swarm of one" gets convoy visibility.

## Cross-Rig Tracking

Convoys live in town-level beads (`hq-cv-*` prefix) and can track issues from any rig:

```bash
# Track issues from multiple rigs
gt convoy create "Full-stack feature" \
  gt-frontend-abc \
  gt-backend-def \
  bd-docs-xyz
```

The `tracks` relation is:
- **Non-blocking**: doesn't affect issue workflow
- **Additive**: can add issues anytime
- **Cross-rig**: convoy in hq-*, issues in gt-*, bd-*, etc.

## Convoy vs Rig Status

| View | Scope | Shows |
|------|-------|-------|
| `gt convoy status [id]` | Cross-rig | Issues tracked by convoy + workers |
| `gt rig status <rig>` | Single rig | All workers in rig + their convoy membership |

Use convoys for "what's the status of this batch of work?"
Use rig status for "what's everyone in this rig working on?"

## See Also

- [Propulsion Principle](propulsion-principle.md) - Worker execution model
- [Mail Protocol](../design/mail-protocol.md) - Notification delivery

---

## File: docs/concepts/heartbeats.md

# Heartbeats

Gas Town has **three distinct heartbeat stores**. They have different readers
and thresholds, so Deacon heartbeat commands refresh the Deacon-specific stores
together to avoid false "stuck agent" escalations (see hq-qxl9: a Deacon
refreshed its session heartbeat while the file store aged past threshold).

## The three stores

### 1. Deacon heartbeat file — `<townRoot>/deacon/heartbeat.json`

- **Written by:** `gt deacon heartbeat [action]` and `gt heartbeat` when
  `GT_ROLE=deacon` → `deacon.Touch()` / `deacon.TouchWithAction()`
  (`internal/deacon/heartbeat.go`).
- **Read by:** the stuck-agent-dog plugin (parses the JSON `timestamp`, falling
  back to mtime for malformed legacy files, and cross-checks tmux activity
  before escalating) and the Go daemon (`deacon.ReadHeartbeat`; thresholds 5m
  stale / 20m very-stale → poke).
- **Also touches:** the legacy `deacon/.deacon-heartbeat` mtime file for old
  shell scripts.

### 2. Session heartbeat (per-session state store)

- **Written by:** `gt heartbeat [--state=working|idle|exiting|stuck]` →
  `polecat.TouchSessionHeartbeatWithState()`. Requires `GT_SESSION`.
- **Read by:** the Witness, which reads the self-reported state instead of
  inferring liveness from timers (ZFC: gt-3vr5). This is the store polecats
  refresh.

### 3. Agent-bead label — `heartbeat:<EPOCH>` on the agent bead (e.g. `hq-deacon`)

- **Written by:** `gt mol await-signal` on each timeout/signal wake
  (`updateAgentHeartbeat` in `internal/cmd/molecule_await_signal.go`). A
  label rewrite is used because `bd agent heartbeat` was never shipped
  (steveyegge/beads#2828). Deacon heartbeat commands also sync this label when
  it is older than half of the stale threshold.
- **Read by:** Witness second-order monitoring ("who watches the watchers"):
  Witnesses check the Deacon's bead activity and alert the Mayor if it looks
  unresponsive (>5 minutes per the patrol formula).
- **Gotcha:** a session that never reaches `await-signal` (handoff churn,
  session limits, one very long patrol turn) leaves this label stale for
  hours even though the agent is healthy.

## Rules of thumb

- **Deacon sessions:** `gt deacon heartbeat` refreshes the Deacon file and
  throttled bead label. `gt heartbeat` also refreshes the session store and,
  when `GT_ROLE=deacon`, uses the same Deacon file/label sync path.
- **Polecats / Witness / Refinery:** `gt heartbeat` (session store) is the
  one that matters.
- **Monitoring scripts:** never declare an agent stuck from a single store.
  Cross-check tmux session activity (`tmux display-message -p
  '#{window_activity}'`) before escalating — a live session with a stale
  store is *heartbeat-write divergence*, not a stuck agent. The
  stuck-agent-dog plugin does this since hq-qxl9.

---

## File: docs/concepts/identity.md

# Agent Identity and Attribution

> Canonical format for agent identity in Gas Town

## Why Identity Matters

When you deploy AI agents at scale, anonymous work creates real problems:

- **Debugging:** "The AI broke it" isn't actionable. *Which* AI?
- **Quality tracking:** You can't improve what you can't measure.
- **Compliance:** Auditors ask "who approved this code?" - you need an answer.
- **Performance management:** Some agents are better than others at certain tasks.

Gas Town solves this with **universal attribution**: every action, every commit,
every bead update is linked to a specific agent identity. This enables work
history tracking, capability-based routing, and objective quality measurement.

## BD_ACTOR Format Convention

The `BD_ACTOR` environment variable identifies agents in slash-separated path format.
This is set automatically when agents are spawned and used for all attribution.

### Format by Role Type

| Role Type | Format | Example |
|-----------|--------|---------|
| **Mayor** | `mayor` | `mayor` |
| **Deacon** | `deacon` | `deacon` |
| **Witness** | `{rig}/witness` | `gastown/witness` |
| **Refinery** | `{rig}/refinery` | `gastown/refinery` |
| **Crew** | `{rig}/crew/{name}` | `gastown/crew/joe` |
| **Polecat** | `{rig}/polecats/{name}` | `gastown/polecats/toast` |

### Why Slashes?

The slash format mirrors filesystem paths and enables:
- Hierarchical parsing (extract rig, role, name)
- Consistent mail addressing (`gt mail send gastown/witness`)
- Path-like routing in beads operations
- Visual clarity about agent location

## Attribution Model

Gas Town uses three fields for complete provenance:

### Git Commits

```bash
GIT_AUTHOR_NAME="gastown/crew/joe"      # Who did the work (agent)
GIT_AUTHOR_EMAIL="steve@example.com"    # Who owns the work (overseer)
```

Result in git log:
```
abc123 Fix bug (gastown/crew/joe <steve@example.com>)
```

**Interpretation**:
- The agent `gastown/crew/joe` authored the change
- The work belongs to the workspace owner (`steve@example.com`)
- Both are preserved in git history forever

### Beads Records

```json
{
  "id": "gt-xyz",
  "created_by": "gastown/crew/joe",
  "updated_by": "gastown/witness"
}
```

The `created_by` field is populated from `BD_ACTOR` when creating beads.
The `updated_by` field tracks who last modified the record.

### Event Logging

All events include actor attribution:

```json
{
  "ts": "2025-01-15T10:30:00Z",
  "type": "sling",
  "actor": "gastown/crew/joe",
  "payload": { "bead": "gt-xyz", "target": "gastown/polecats/toast" }
}
```

## Environment Setup

Gas Town uses a centralized `config.AgentEnv()` function to set environment
variables consistently across all agent spawn paths (managers, daemon, boot).

### Example: Polecat Environment

```bash
# Set automatically for polecat 'toast' in rig 'gastown'
export GT_ROLE="polecat"
export GT_RIG="gastown"
export GT_POLECAT="toast"
export BD_ACTOR="gastown/polecats/toast"
export GIT_AUTHOR_NAME="gastown/polecats/toast"
export GT_ROOT="/home/user/gt"
export BEADS_DIR="/home/user/gt/gastown/.beads"
export BEADS_AGENT_NAME="gastown/toast"
```

### Example: Crew Environment

```bash
# Set automatically for crew member 'joe' in rig 'gastown'
export GT_ROLE="crew"
export GT_RIG="gastown"
export GT_CREW="joe"
export BD_ACTOR="gastown/crew/joe"
export GIT_AUTHOR_NAME="gastown/crew/joe"
export GT_ROOT="/home/user/gt"
export BEADS_DIR="/home/user/gt/gastown/.beads"
export BEADS_AGENT_NAME="gastown/joe"
```

### Manual Override

For local testing or debugging:

```bash
export BD_ACTOR="gastown/crew/debug"
bd create --title="Test issue"  # Will show created_by: gastown/crew/debug
```

See [reference.md](reference.md#environment-variables) for the complete
environment variable reference.

## Identity Parsing

The format supports programmatic parsing:

```go
// identityToBDActor converts daemon identity to BD_ACTOR format
// Town level: mayor, deacon
// Rig level: {rig}/witness, {rig}/refinery
// Workers: {rig}/crew/{name}, {rig}/polecats/{name}
```

| Input | Parsed Components |
|-------|-------------------|
| `mayor` | role=mayor |
| `deacon` | role=deacon |
| `gastown/witness` | rig=gastown, role=witness |
| `gastown/refinery` | rig=gastown, role=refinery |
| `gastown/crew/joe` | rig=gastown, role=crew, name=joe |
| `gastown/polecats/toast` | rig=gastown, role=polecat, name=toast |

## Audit Queries

Attribution enables powerful audit queries:

```bash
# All work by an agent
bd audit --actor=gastown/crew/joe

# All work in a rig
bd audit --actor=gastown/*

# All polecat work
bd audit --actor=*/polecats/*

# Git history by agent
git log --author="gastown/crew/joe"
```

## Design Principles

1. **Agents are not anonymous** - Every action is attributed
2. **Work is owned, not authored** - Agent creates, overseer owns
3. **Attribution is permanent** - Git commits preserve history
4. **Format is parseable** - Enables programmatic analysis
5. **Consistent across systems** - Same format in git, beads, events

## CV and Skill Accumulation

### Human Identity is Global

The global identifier is your **email** - it's already in every git commit. No separate "entity bead" needed.

```
steve@example.com                ← global identity (from git author)
├── Town A (home)                ← workspace
│   ├── gastown/crew/joe         ← agent executor
│   └── gastown/polecats/toast   ← agent executor
└── Town B (work)                ← workspace
    └── acme/polecats/nux        ← agent executor
```

### Agent vs Owner

| Field | Scope | Purpose |
|-------|-------|---------|
| `BD_ACTOR` | Local (town) | Agent attribution for debugging |
| `GIT_AUTHOR_EMAIL` | Global | Human identity for CV |
| `created_by` | Local | Who created the bead |
| `owner` | Global | Who owns the work |

**Agents execute. Humans own.** The polecat name in `completed-by: gastown/polecats/toast` is executor attribution. The CV credits the human owner (`steve@example.com`).

### Polecats Have Persistent Identities

Polecats have **persistent identities but ephemeral sessions**. Like employees who
clock in/out: each work session is fresh (new tmux, new worktree), but the identity
persists across sessions.

- **Identity (persistent)**: Agent bead, CV chain, work history
- **Session (ephemeral)**: Claude instance, context window
- **Sandbox (ephemeral)**: Git worktree, branch

Work credits the polecat identity, enabling:
- Performance tracking per polecat
- Capability-based routing (send Go work to polecats with Go track records)
- Model comparison (A/B test different models via different polecats)

See [polecat-lifecycle.md](polecat-lifecycle.md#polecat-identity) for details.

### Skills Are Derived

Your CV emerges from querying work evidence:

```bash
# All work by owner (across all agents)
git log --author="steve@example.com"
bd list --owner=steve@example.com

# Skills derived from evidence
# - .go files touched → Go skill
# - issue tags → domain skills
# - commit patterns → activity types
```

### Multi-Town Aggregation

A human with multiple towns has one CV:

```bash
# Future: federated CV query
bd cv steve@example.com
# Discovers all towns, aggregates work, derives skills
```

See `~/gt/docs/hop/decisions/008-identity-model.md` for architectural rationale.

## Enterprise Use Cases

### Compliance and Audit

```bash
# Who touched this file in the last 90 days?
git log --since="90 days ago" -- path/to/sensitive/file.go

# All changes by a specific agent
bd audit --actor=gastown/polecats/toast --since=2025-01-01
```

### Performance Tracking

```bash
# Completion rate by agent
bd stats --group-by=actor

# Average time to completion
bd stats --actor=gastown/polecats/* --metric=cycle-time
```

### Model Comparison

When agents use different underlying models, attribution enables A/B comparison:

```bash
# Tag agents by model
# gastown/polecats/claude-1 uses Claude
# gastown/polecats/gpt-1 uses GPT-4

# Compare quality signals
bd stats --actor=gastown/polecats/claude-* --metric=revision-count
bd stats --actor=gastown/polecats/gpt-* --metric=revision-count
```

Lower revision counts suggest higher first-pass quality.

---

## File: docs/concepts/integration-branches.md

# Integration Branches

> Group epic work on a shared branch, land to main as a unit.

Integration branches provide end-to-end support for epic-scoped work across
the Gas Town pipeline. When you create an integration branch for an epic, it
becomes the automatic target for every stage: polecats spawn their worktrees
from the integration branch (so they start with sibling work already present),
the Refinery merges completed MRs into the integration branch instead of main,
and when all epic children are closed, the Refinery can land the integration
branch back to its base branch (main by default, or whatever was specified
with `--base-branch` at creation) as a single merge commit.

Landing can happen on command or automatically via patrol. The result is that
an entire epic flows through the system as a coherent unit, from first sling
to final land, without any manual branch targeting.

## Workflow

1. **Create the epic and its children.** Structure your work as an epic with
   child tasks (or sub-epics) underneath. Set up dependencies between children
   to define which can run in parallel and which must wait.

2. **Create the integration branch.** This is the shared branch where all child
   work accumulates.
   ```bash
   gt mq integration create gt-auth-epic
   ```

3. **Create a convoy to track the work.** The convoy gives you a single dashboard
   for the entire epic's progress.
   ```bash
   gt convoy create "Auth overhaul" gt-auth-tokens gt-auth-sessions gt-auth-middleware
   ```

4. **Sling the first wave.** Identify children with no blockers and sling them
   to the rig. Use `--no-convoy` since the tracking convoy already exists.
   ```bash
   gt sling gt-auth-tokens gastown --no-convoy
   gt sling gt-auth-sessions gastown --no-convoy
   ```

5. **Polecats process the work.** Each polecat spawns its worktree from the
   integration branch, so it starts with any sibling work that has already
   landed there. When a polecat finishes, it submits a merge request.

6. **Refinery merges to the integration branch.** Instead of merging to main,
   the Refinery merges each MR into the integration branch and marks the child
   task as complete.

7. **Track progress via the convoy.** The convoy status updates each time the
   Refinery completes a task.
   ```bash
   gt convoy status hq-cv-abc
   ```

8. **Sling the next wave.** When a wave completes and its dependent children
   unblock, sling the next batch. Those polecats will start from the integration
   branch — which now contains all the work from the preceding wave.
   ```bash
   gt sling gt-auth-middleware gastown --no-convoy
   ```

9. **Land when complete.** When all children under the epic are closed, the
   integration branch is ready to land. If `integration_branch_auto_land` is
   enabled, the Refinery does this automatically during patrol. Otherwise,
   land manually:
   ```bash
   gt mq integration land gt-auth-epic
   ```
   This merges the integration branch back to its base branch (main by
   default) as a single merge commit, deletes the branch, and closes the
   epic.

## Concept

### The Problem

Without integration branches, epic work lands piecemeal:

```
Child A ──► MR ──► main     (lands Tuesday)
Child B ──► MR ──► main     (lands Wednesday, breaks A's work)
Child C ──► MR ──► main     (lands Thursday, depends on A+B together)
```

Each child merges independently. If Child C depends on A and B being coherent
together, you're relying on merge order and hoping nothing breaks between lands.

### The Solution

Integration branches batch epic work on a shared branch, then land atomically:

```
                           Epic: gt-auth-epic
                                  │
                    ┌─────────────┼─────────────┐
                    │             │             │
               Child A       Child B       Child C
                    │             │             │
                    ▼             ▼             ▼
               ┌────────┐  ┌────────┐  ┌────────┐
               │  MR A  │  │  MR B  │  │  MR C  │
               └───┬────┘  └───┬────┘  └───┬────┘
                   │           │           │
                   └───────────┼───────────┘
                               ▼
                 integration/gt-auth-epic
                    (shared branch)
                               │
                               ▼ gt mq integration land
                          base branch
                    (main or --base-branch)
                     (single merge commit)
```

All child MRs merge into the integration branch first. Children can build on
each other's work. When everything is ready, one command lands it all.

### With vs Without

| Aspect | Without | With Integration Branch |
|--------|---------|------------------------|
| MR target | main | integration/{epic} |
| Land timing | Each MR lands independently | All MRs land together |
| Cross-child deps | Risky—depends on merge order | Safe—children share a branch |
| Rollback | Revert individual commits | Revert one merge commit |
| CI on main | Runs per-MR | Runs once on combined work |

## Lifecycle

### 1. Create the Epic

```bash
bd create --type=epic --title="Auth overhaul"
# → gt-auth-epic
```

Create child issues under the epic as normal.

### 2. Create the Integration Branch

```bash
gt mq integration create gt-auth-epic
# → Created integration/gt-auth-epic from origin/main
# → Stored branch name in epic metadata
```

This pushes a new branch to origin and records its name on the epic.

### 3. Sling Work

Assign children to polecats as normal:

```bash
gt sling gt-auth-tokens gastown
gt sling gt-auth-sessions gastown
```

Polecats auto-detect the integration branch when their issue is a child of an
epic that has one. No manual targeting needed.

### 4. MRs Merge to Integration Branch

When polecats run `gt done` or `gt mq submit`, auto-detection kicks in:

```
gt done
  → Detects parent epic gt-auth-epic
  → Finds integration/gt-auth-epic branch
  → Submits MR targeting integration/gt-auth-epic (not main)
```

The Refinery processes these MRs and merges them to the integration branch.

### 5. Land When Complete

Once all children are closed and all MRs merged:

```bash
gt mq integration land gt-auth-epic
# → Verified all MRs merged
# → Merged integration/gt-auth-epic → base branch (--no-ff)
# → Tests passed
# → Pushed to origin
# → Deleted integration/gt-auth-epic
# → Closed epic gt-auth-epic
```

## Auto-Detection

Integration branches work without manual targeting. Three systems auto-detect them:

| System | What It Does | Config Gate |
|--------|-------------|-------------|
| `gt done` / `gt mq submit` | Targets MR at integration branch instead of main | `integration_branch_refinery_enabled` |
| Polecat spawn | Sources worktree from integration branch | `integration_branch_polecat_enabled` |
| Refinery patrol | Checks if integration branches are ready to land | `integration_branch_auto_land` |

### Detection Algorithm

When `gt done` or `gt mq submit` runs:

| Step | Action | Result |
|------|--------|--------|
| 1 | Load config, check `integration_branch_refinery_enabled` | If false, skip detection |
| 2 | Get current issue ID from branch name | e.g., `gt-auth-tokens` |
| 3 | Walk parent chain (max 10 levels) | Find ancestor epics |
| 4 | For each epic: read `integration_branch:` from metadata | Get stored branch name |
| 5 | Fallback: generate name from template | e.g., `integration/{title}` |
| 6 | Check if branch exists (local, then remote) | Verify it's real |
| 7 | If found, target MR at that branch | Instead of main |

The `--epic` flag on `gt mq submit` bypasses auto-detection and resolves
the target branch using the configured template (defaulting to
`integration/{epic}`).

## Branch Naming

### Template Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `{epic}` | Full epic ID | `gt-auth-epic` |
| `{prefix}` | Epic prefix (before first hyphen) | `gt` |
| `{user}` | From `git config user.name` | `klauern` |

### Precedence

| Priority | Source | Example |
|----------|--------|---------|
| 1 (highest) | `--branch` flag on create | `--branch "feat/{epic}"` |
| 2 | `integration_branch_template` in config | `"{user}/{epic}"` |
| 3 (lowest) | Default | `"integration/{title}"` |

### Template Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `{title}` | Sanitized epic title (lowercase, hyphenated, max 60 chars) | `add-user-authentication` |
| `{epic}` | Full epic ID | `RA-123` |
| `{prefix}` | Epic prefix before first hyphen | `RA` |
| `{user}` | Git user.name | `klauern` |

### Examples

```bash
# Default template (uses epic title)
gt mq integration create gt-auth-epic
# → integration/add-user-authentication  (from epic title)

# Custom template in config: "{user}/{prefix}/{epic}"
gt mq integration create RA-123
# → klauern/RA/RA-123

# Override with --branch flag
gt mq integration create RA-123 --branch "feature/{epic}"
# → feature/RA-123
```

The actual branch name created is stored in the epic's metadata, so auto-detection
always finds the right branch regardless of which template was used.

If two epics produce the same branch name (same title), a numeric suffix from the
epic ID is appended automatically (e.g., `integration/add-auth-456`).

## Commands

### `gt mq integration create <epic-id>`

Create an integration branch for an epic.

```bash
gt mq integration create <epic-id> [flags]
```

**Flags:**

| Flag | Description | Default |
|------|-------------|---------|
| `--branch` | Override branch name template | Config template or `integration/{title}` |
| `--base-branch` | Create from this branch instead of the rig's default branch (also sets where `land` merges back to) | `origin/<default_branch>` |

**What it does:**

1. Verifies the epic exists
2. Generates branch name from template (expanding variables)
3. Validates branch name (git-safe characters)
4. Creates local branch from base
5. Pushes to origin
6. Stores branch name and base branch in epic metadata

**Error cases:**

- Epic not found
- Branch already exists
- Invalid characters in generated branch name

### `gt mq integration status <epic-id>`

Display integration branch status for an epic.

```bash
gt mq integration status <epic-id> [flags]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--json` | Output as JSON |

**Output includes:**

- Branch name and creation date
- Commits ahead of main
- Merged MRs (closed, targeting integration branch)
- Pending MRs (open, targeting integration branch)
- Child issue progress (closed / total)
- Ready-to-land status
- Auto-land configuration

**Ready-to-land criteria** (all must be true):

1. Integration branch has commits ahead of main
2. Epic has children
3. All children are closed
4. No pending MRs (all submitted work is merged)

### `gt mq integration land <epic-id>`

Merge an epic's integration branch back to its base branch.

```bash
gt mq integration land <epic-id> [flags]
```

**Flags:**

| Flag | Description | Default |
|------|-------------|---------|
| `--force` | Land even if some MRs still open | `false` |
| `--skip-tests` | Skip test run after merge | `false` |
| `--dry-run` | Preview only, make no changes | `false` |

**What it does:**

1. Verifies epic exists and has an integration branch
2. Reads base branch from epic metadata (defaults to the rig's `default_branch` if not stored)
3. Checks all MRs targeting integration branch are merged
4. Fetches latest refs and checks idempotency (if already merged, skips to cleanup)
5. Acquires file lock (prevents concurrent land races)
6. Creates a temporary worktree (avoids disrupting running agents)
7. Merges integration branch to base branch using `--no-ff`
8. Runs tests (unless `--skip-tests`)
9. Verifies merge brought changes (guards against empty merges)
10. Pushes to origin
11. Deletes integration branch (local and remote)
12. Closes the epic

**Idempotent retry:** If land crashes after pushing but before cleanup (branch
deletion / epic close), rerunning the same command is safe. The idempotency
check detects that the integration branch is already an ancestor of the target
and skips directly to cleanup.

**Error cases:**

- Epic has no integration branch
- Pending MRs exist (use `--force` to override)
- Tests fail
- Empty merge (no changes to land)

## Configuration

### Default Branch

The rig's `default_branch` (set in `config.json`, auto-detected during `gt rig add`)
controls where work merges when no integration branch is active. It's also the
default base branch when creating integration branches. If your project uses
`develop` or `master` instead of `main`, set it once in rig config and the whole
pipeline follows:

```json
{
  "type": "rig",
  "name": "myproject",
  "default_branch": "develop"
}
```

### Integration Branch Settings

All integration branch fields live under `merge_queue` in rig settings (`settings/config.json`):

```json
{
  "merge_queue": {
    "enabled": true,
    "integration_branch_polecat_enabled": true,
    "integration_branch_refinery_enabled": true,
    "integration_branch_template": "integration/{title}",
    "integration_branch_auto_land": false
  }
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `integration_branch_polecat_enabled` | `*bool` | `true` | Polecats auto-source worktrees from integration branches |
| `integration_branch_refinery_enabled` | `*bool` | `true` | `gt mq submit` and `gt done` auto-detect integration branches as MR targets |
| `integration_branch_template` | `string` | `"integration/{title}"` | Branch name template (supports `{title}`, `{epic}`, `{prefix}`, `{user}`) |
| `integration_branch_auto_land` | `*bool` | `false` | Refinery patrol auto-lands when all children closed |

**Note:** `*bool` fields use pointer semantics — `null`/omitted means "use default"
(true for polecat/refinery enabled, false for auto-land). Set explicitly to `false`
to disable.

## Auto-Landing

When `integration_branch_auto_land` is `true`, the Refinery patrol automatically
lands integration branches that are ready.

### How It Works

During each patrol cycle, the Refinery:

1. Lists all open epics: `bd list --type=epic --status=open`
2. Checks each epic's integration branch: `gt mq integration status <epic-id>`
3. If `ready_to_land: true`: runs `gt mq integration land <epic-id>`
4. If not ready: skips (epic work is incomplete)

### Conditions for Auto-Land

Both config gates must be true:

- `integration_branch_refinery_enabled: true` (integration feature is on)
- `integration_branch_auto_land: true` (auto-landing is on)

If either is false, the patrol step exits early.

### When to Enable

| Scenario | Recommendation |
|----------|---------------|
| Trusted CI, no human review needed | Enable auto-land |
| Need human sign-off before landing | Keep disabled (default), land manually |
| Mix of both | Keep disabled, use `gt mq integration land` for manual control |

## Safety Guardrails

Integration branch landing is protected by a three-layer defense:

### Layer 1: Formula and Role Instructions

The refinery formula and role template explicitly forbid landing integration
branches via raw git commands. Only `gt mq integration land` is authorized.

### Layer 2: Pre-Push Hook

The `.githooks/pre-push` hook detects when a push to the default branch
introduces integration branch content. It uses ancestry-based detection:
if any `origin/integration/*` branch tip becomes newly reachable from the
pushed commits, the push is blocked unless `GT_INTEGRATION_LAND=1` is set.

The default branch is detected dynamically via `refs/remotes/origin/HEAD`
(fallback: `main`), so this works regardless of the rig's branch naming.

This catches all merge styles: `--no-ff`, `--ff-only`, default merge, and
rebase. Only cherry-picks (which produce new SHAs) are not detected.

**Scope**: This check matches branches under the `integration/` prefix (the
default template). Custom templates that produce branches outside `integration/`
are not covered by the hook — Layer 1 (formula language) is the guardrail for
those cases.

**Requires**: `core.hooksPath` must be configured for the hook to be active.
New rigs get this automatically. Existing rigs: run `gt doctor --fix`.

### Layer 3: Authorized Code Path

The `gt mq integration land` command uses `PushWithEnv()` to set
`GT_INTEGRATION_LAND=1`, allowing the push through the hook. Raw `git push`
from any agent or user does not set this variable and will be blocked.
Manually setting the env var is possible but is not part of the supported
workflow — the variable is a policy-based trust boundary, not a
capability-based security mechanism.

### Why Three Layers?

| Layer | Type | Strength | Limitation |
|-------|------|----------|------------|
| Formula/Role | Soft | Covers all branch patterns | AI agents can ignore instructions |
| Pre-push hook | Hard | Blocks all merge styles at git boundary | Only matches `integration/*` prefix; env var is policy-based |
| Code path | Hard | Land command sets bypass env var | Requires hook to be active |

The layers complement each other. The formula covers custom templates; the hook
provides hard enforcement for default templates (catching merges, fast-forwards,
and rebases via ancestry detection); the code path ensures the CLI command can
bypass the hook.

## Build Pipeline Configuration

Integration branches work with different project toolchains. The rig's build pipeline
commands are auto-injected into polecat-work, refinery-patrol, and sync-workspace
formulas so agents know how to validate work for each project.

### The 5-Command Pipeline

Commands run in this order (any can be empty = skip):

1. **setup** — Install dependencies (e.g., `pnpm install`)
2. **typecheck** — Static type checking (e.g., `tsc --noEmit`)
3. **lint** — Code style and quality (e.g., `eslint .`)
4. **test** — Run test suite (e.g., `go test ./...`)
5. **build** — Compile/bundle (e.g., `go build ./...`)

### Example Configurations

**Go project** (all commands empty by default — configure per-rig):
```json
{
  "merge_queue": {
    "test_command": "go test ./...",
    "lint_command": "golangci-lint run ./...",
    "build_command": "go build ./..."
  }
}
```

**TypeScript project:**
```json
{
  "merge_queue": {
    "setup_command": "pnpm install",
    "typecheck_command": "tsc --noEmit",
    "lint_command": "eslint .",
    "test_command": "pnpm test:unit",
    "build_command": "pnpm build"
  }
}
```

### How Commands Flow Into Formulas

Commands are auto-injected from `<rig>/settings/config.json` into formula vars:

- **Refinery patrol**: `buildRefineryPatrolVars()` reads rig config during `gt prime`
- **Polecat work / sync**: `loadRigCommandVars()` reads rig config during `gt sling`

User-provided `--var` flags on `gt sling` override rig config values.

### Empty = Skip

Any command left empty (or not configured) is skipped silently by the formula.
This means a Go rig doesn't need `setup_command` or `typecheck_command`, and a
TypeScript rig can add all five without affecting Go rigs.

Polecats working on integration branches inherit the rig's build pipeline
automatically — no per-branch configuration is needed.

## Anti-Patterns

### Creating Integration Branch After Work Starts

**Wrong:** Sling children, then create the integration branch later.

Children slung before the integration branch exists will target main. Their MRs
won't flow to the integration branch. Create the integration branch *first*,
before slinging any child work.

### Manually Targeting the Integration Branch

**Wrong:** Using `--branch integration/gt-epic` on `gt mq submit`.

Auto-detection handles this. If you find yourself manually targeting, check that:
- The integration branch actually exists
- `integration_branch_refinery_enabled` is not `false`
- The issue is a child (or descendant) of the epic

### Landing Partial Epics

**Wrong:** Using `--force` to land when children are still open.

This defeats the purpose. The integration branch exists so work lands together.
If you need to land early, close or remove the incomplete children first.

## See Also

- [Polecat Lifecycle](polecat-lifecycle.md) — How polecats submit to the merge queue
- [Reference](../reference.md) — Full CLI reference including MQ commands

---

## File: docs/concepts/molecules.md

# Molecules

Molecules are workflow templates that coordinate multi-step work in Gas Town.

## Molecule Lifecycle

```
Formula (source TOML) ─── "Ice-9"
    │
    ▼ bd cook
Protomolecule (frozen template) ─── Solid
    │
    ├─▶ bd mol pour ──▶ Mol (persistent) ─── Liquid
    │
    └─▶ bd mol wisp --root-only ──▶ Root Wisp (ephemeral) ─── Vapor
```

**Root-only wisps** (default): Formula steps are NOT materialized as database rows.
Only a single root wisp is created. Agents read steps inline from the embedded
formula at prime time. This prevents wisp accumulation (~6,000+ rows/day → ~400/day).

**Poured wisps** (`pour = true`): Steps ARE materialized as sub-wisps with
checkpoint recovery. If a session dies, completed steps remain closed and work
resumes from the last checkpoint. Use pour for expensive, low-frequency workflows
where losing progress would be costly (e.g., release workflows).

## Core Concepts

| Term | Description |
|------|-------------|
| **Formula** | Source TOML template defining workflow steps |
| **Protomolecule** | Frozen template ready for instantiation |
| **Molecule** | Active workflow instance (root wisp only) |
| **Wisp** | Ephemeral molecule for patrols and polecat work (never synced) |
| **Root-only** | Only root wisp created; steps read from embedded formula |
| **Pour** | Formula flag (`pour = true`); steps materialized as sub-wisps with checkpoint recovery |

## How Agents See Steps

Agents do NOT use `bd mol current` or `bd close <step-id>` for formula workflows.
Instead, formula steps are rendered inline when the agent runs `gt prime`:

```
**Formula Checklist** (10 steps from mol-polecat-work):

### Step 1: Load context and verify assignment
Initialize your session and understand your assignment...

### Step 2: Set up working branch
Ensure you're on a clean feature branch...
```

The agent works through the checklist and runs `gt done` (polecats) or
`gt patrol report` (patrol agents) when complete.

## Molecule Commands

### Beads Operations (bd)

```bash
# Formulas
bd formula list              # Available formulas
bd formula show <name>       # Formula details
bd cook <formula>            # Formula → Proto

# Molecules (data operations)
bd mol list                  # Available protos
bd mol show              # Proto details
bd mol wisp           # Create wisp (root-only by default)
bd mol bond   # Attach to existing mol
```

### Agent Operations (gt)

```bash
# Hook management
gt hook                    # What's on MY hook?
gt prime                   # Shows inline formula checklist
gt mol attach  <mol>   # Pin molecule to bead
gt mol detach          # Unpin molecule from bead

# Patrol lifecycle
gt patrol new              # Create patrol wisp and hook it
gt patrol report --summary "..."  # Close current patrol, start next cycle
```

## Polecat Workflow

Polecats receive work via their hook — a root wisp attached to an issue.
They see the formula checklist inline when they run `gt prime` and work
through each step in order.

### Polecat Workflow Summary

```
1. Spawn with work on hook
2. gt prime               # Shows formula checklist inline
3. Work through each step
4. Persist findings: bd update  --notes "..."
5. gt done                # Submit, preserve handoff metadata, exit
```

### Molecule Types

| Type | Storage | Use Case |
|------|---------|----------|
| **Root-only Wisp** (`pour = false`) | `.beads/` (ephemeral) | Polecat work, patrols — high frequency, cheap steps |
| **Poured Wisp** (`pour = true`) | `.beads/` (sub-wisps) | Releases, long workflows — low frequency, expensive steps |

**Heuristic**: If you would curse losing the progress after a crash, set `pour = true`.
High frequency + cheap steps = inline (default). Low frequency + expensive steps = pour.

## Patrol Workflow

Patrol agents (Deacon, Witness, Refinery) cycle through patrol formulas:

```
1. gt patrol new          # Create root-only patrol wisp
2. gt prime               # Shows patrol checklist inline
3. Work through each step
4. gt patrol report --summary "..."  # Close + start next cycle
```

`gt patrol report` atomically closes the current patrol root and spawns
a new one for the next cycle.

## Best Practices

1. **Persist findings early** — `bd update  --notes "..."` before session death
2. **Run `gt done` when complete** — mandatory for polecats (pushes, submits to MQ/PR path, exits)
3. **Use `gt patrol report`** — for patrol agents to cycle (replaces squash+new pattern)
4. **File discovered work** — `bd create` for bugs found, don't fix them yourself

---

## File: docs/concepts/polecat-lifecycle.md

# Polecat Lifecycle

> Understanding the three-layer architecture of polecat workers

## Overview

Polecats have three distinct lifecycle layers that operate independently. The
key design principle: **clean completion retires the live polecat session**.
The agent identity and merge evidence persist, but completed sessions do not
return to the idle reuse pool.

## Operating States

Polecats use these primary operating states:

| State | Description | How it happens |
|-------|-------------|----------------|
| **Working** | Actively doing assigned work | Normal operation after `gt sling` |
| **Idle** | Available before assignment | Spawned or explicitly prepared for work |
| **Done** | Work completed and session retired | After `gt done` completes successfully |
| **Stalled** | Session stopped mid-work | Interrupted, crashed, or timed out without being nudged |
| **Zombie** | Completed work but failed to exit | `gt done` failed during cleanup |

**State cycle (happy path):**

```
         ┌──────────┐
         │  IDLE    │──── gt sling
         └────┬─────┘
              v
         ┌──────────┐
         │ WORKING  │<──── session active, hook set
         └────┬─────┘
              │ gt done
              v
         ┌──────────┐
         │  DONE    │──── branch/MR evidence preserved, session exits
         └──────────┘
```

No idle reuse in the happy path. Polecats move: IDLE -> WORKING -> DONE.

**Key distinctions:**

- **Working** = actively executing. Session alive, hook set, doing work.
- **Idle** = not yet assigned and safe to use.
- **Done** = work done, session killed, waiting for cleanup/refinery outcome.
- **Stalled** = supposed to be working, but stopped. Needs Witness intervention.
- **Zombie** = finished work, tried to exit, but cleanup failed. Stuck in limbo.

## The Retired Completion Model

**Polecat identity persists after completing work, but the live session does not.**
When a polecat finishes its assignment:

1. Signals completion via `gt done`
2. Pushes branch, submits MR to merge queue
3. Clears its hook (work is done)
4. Sets agent state to "done"
5. Kills its own session using PID-excluding cleanup
6. Leaves branch/MR metadata for Witness/refinery cleanup

The next `gt sling` allocates available capacity without reusing a completed
session that still has branch/MR or cleanup state attached.

### Why Retire Sessions?

- **Preserved identity** — The polecat's agent bead, CV chain, and work history persist
- **Simpler lifecycle** — Clean completion has one terminal session path
- **Done means retired** — Session dies, cleanup/refinery owns remaining state

### What About Pending Merges?

The Refinery owns the merge queue. Once `gt done` submits work:
- The branch is pushed to origin
- Work exists in the MQ, not in the polecat
- If rebase fails, Refinery creates a conflict-resolution task
- The completed polecat is not reused while pending MR or cleanup state remains

## The Three Layers

### The Problem: Three Concepts Were Conflated

Early designs treated polecats as monolithic. This caused recurring issues:

| Concept | Lifecycle | Old behavior |
|---------|-----------|-----------------|
| **Identity** | Long-lived (name, CV, ledger) | Destroyed on nuke |
| **Sandbox** | Per-assignment (worktree, branch) | Destroyed on nuke |
| **Session** | Ephemeral (Claude context window) | = polecat lifetime |

Separating these three layers keeps completed sessions out of the idle reuse pool,
preserves capability records (CV, completion history), and lets cleanup/refinery
own branch and worktree state after handoff.

### Layer Summary

| Layer | Component | Lifecycle | Persistence |
|-------|-----------|-----------|-------------|
| **Identity** | Agent bead, CV chain, work history | Permanent | Never dies |
| **Sandbox** | Git worktree, branch | Per active assignment/cleanup window | Created for work, retired after cleanup |
| **Session** | Claude (tmux pane), context window | Ephemeral per step | Cycles per step/handoff |

### Identity Layer

The polecat's **identity is permanent**. It includes:

- Agent bead (created once, never deleted)
- CV chain (work history accumulates across all assignments)
- Mailbox and attribution record

Identity survives all session cycles and sandbox resets. In the HOP model, this IS
the polecat — everything else is infrastructure that comes and goes. See
[Polecat Identity](#polecat-identity) below for details.

### Session Layer

The Claude session is **ephemeral**. It cycles frequently:

- After each molecule step (via `gt handoff`)
- On context compaction
- On crash/timeout
- After extended work periods

**Key insight:** Session cycling is **normal operation**, not failure. The polecat
continues working—only the Claude context refreshes.

```
Session 1: Steps 1-2 → handoff
Session 2: Steps 3-4 → handoff
Session 3: Step 5 → gt done
```

All three sessions are the **same polecat**. The sandbox persists throughout.

### Sandbox Layer

The sandbox is the **git worktree**—the polecat's working directory:

```
~/gt/gastown/polecats/Toast/
```

This worktree:
- Exists while the polecat is active or awaiting cleanup
- Survives handoff/session cycles during an assignment
- Is not synced to main or branch-deleted by `gt done`
- Contains uncommitted work, staged changes, branch state during active work

Witness/refinery cleanup owns sandbox retirement after durable handoff. Explicit
`gt polecat nuke` remains the manual destructive path.

#### Branch Preservation (After Completion)

When work completes, `gt done` leaves the feature branch and MR metadata intact:

```bash
# Handled by gt done
git push origin polecat/<name>/@<suffix>
# Branch and metadata remain available for refinery/review/cleanup
```

When new work is slung:
```bash
# Create fresh branch from current main
git checkout -b polecat/<name>/<new-issue>+<timestamp>
# Start working
```

Completed sandboxes are not treated as reusable idle worktrees while branch,
MR, or cleanup state remains attached.

### Slot Layer

The slot is the **name allocation** from the polecat pool:

```bash
# Pool: [Toast, Shadow, Copper, Ash, Storm...]
# Toast is allocated to work gt-abc
```

The slot:
- Determines the sandbox path (`polecats/Toast/`)
- Maps to a tmux session (`gt-gastown-Toast`)
- Appears in attribution (`gastown/polecats/Toast`)
- Persists until explicit nuke

## Correct Lifecycle

```
/* Detailed source-code truncated for AI context efficiency. */
```

## What "Recycle" Means

**Session cycling**: Normal. Claude restarts, sandbox stays, slot stays.

```bash
gt handoff  # Session cycles, polecat continues
```

**Sandbox setup**: For active work. `gt sling` prepares a fresh branch for the assignment.

```bash
gt sling gt-xyz gastown  # Allocates capacity and prepares branch
```

Session cycling happens constantly. Sandbox setup/cleanup is tied to assignments.

## Anti-Patterns

### Manual State Transitions

**Anti-pattern:**
```bash
gt polecat done Toast    # DON'T: external state manipulation
gt polecat reset Toast   # DON'T: manual lifecycle control
```

**Correct:**
```bash
# Polecat signals its own completion:
gt done  # (from inside the polecat session)

# Only explicit nuke destroys polecats:
gt polecat nuke Toast  # (destroys sandbox, identity persists)
```

Polecats manage their own session lifecycle. External manipulation bypasses verification.

### Sandboxes Without Work (Idle vs Done vs Stalled)

An idle polecat has no hook, no session, and no completion/MR cleanup state —
this is **available capacity**.

A **done** polecat has completed work and exited, but branch/MR or cleanup state
may still be attached. It is not reusable until cleanup resolves that state.

A **stalled** polecat has a hook but no session — this is a **failure**:
- The session crashed and wasn't nudged back to life
- The hook was lost during a crash
- State corruption occurred

**Recovery for stalled:**
```bash
# Witness respawns the session in the existing sandbox
# Or, if unrecoverable:
gt polecat nuke Toast        # Clean up the stalled polecat
gt sling gt-abc gastown      # Respawn with fresh polecat
```

### Confusing Session with Sandbox

**Anti-pattern:** Thinking session restart = losing work.

```bash
# Session ends (handoff, crash, compaction)
# Work is NOT lost because:
# - Git commits persist in sandbox
# - Staged changes persist in sandbox
# - Molecule state persists in beads
# - Hook persists across sessions
```

The new session picks up where the old one left off via `gt prime`.

## Session Lifecycle Details

Sessions cycle for these reasons:

| Trigger | Action | Result |
|---------|--------|--------|
| `gt handoff` | Voluntary | Clean cycle to fresh context |
| Context compaction | Automatic | Forced by Claude Code |
| Crash/timeout | Failure | Witness respawns |
| `gt done` | Completion | Session exits, polecat goes done |

All except `gt done` result in continued work. Only `gt done` signals completion
and retires the completed polecat session.

## Witness Responsibilities

The Witness monitors polecats but does NOT:
- Force session cycles (polecats self-manage via handoff)
- Interrupt mid-step (unless truly stuck)
- Reuse polecats after completion while cleanup/MR state remains

The Witness DOES:
- Detect and nudge stalled polecats (sessions that stopped unexpectedly)
- Clean up zombie polecats (sessions where `gt done` failed)
- Respawn crashed sessions
- Handle escalations from stuck polecats (polecats that explicitly asked for help)

## Polecat Identity

**Key insight:** Polecat *identity* is permanent; sessions are ephemeral, sandboxes are persistent.

In the HOP model, every entity has a chain (CV) that tracks:
- What work they've done
- Success/failure rates
- Skills demonstrated
- Quality metrics

The polecat *name* (Toast, Shadow, etc.) is a slot from a pool — persistent until
explicit nuke. The *agent identity* that executes as that polecat accumulates a
work history across all assignments.

```
POLECAT IDENTITY (permanent)      SESSION (ephemeral)     SANDBOX (assignment-scoped)
├── CV chain                      ├── Claude instance     ├── Git worktree
├── Work history                  ├── Context window      ├── Branch
├── Skills demonstrated           └── Dies on handoff     └── Retired after cleanup
└── Credit for work                   or gt done              by gt sling
```

This distinction matters for:
- **Attribution** - Who gets credit for the work?
- **Skill routing** - Which agent is best for this task?
- **Cost accounting** - Who pays for inference?
- **Federation** - Agents having their own chains in a distributed world

## Implementation Status

As of 2026-03-07 (gt-o8g8 audit), all core lifecycle operations are **shipped and
running in production**. See [design/polecat-lifecycle-patrol.md § 10](../design/polecat-lifecycle-patrol.md#10-implementation-status-gt-o8g8-audit-2026-03-07)
for the full implementation matrix and [design/persistent-polecat-pool.md](../design/persistent-polecat-pool.md)
for phase-by-phase shipping status.

Key files:
- `internal/cmd/done.go` — work submission, done-state handoff, session retirement
- `internal/cmd/sling.go` + `polecat_spawn.go` — capacity allocation, branch setup
- `internal/cmd/handoff.go` — session cycling for all roles
- `internal/witness/handlers.go` — cleanup pipeline, POLECAT_DONE routing, zombie/orphan detection
- `internal/polecat/manager.go` — stale detection, done-state projection, pool management

## Related Documentation

- [Overview](../overview.md) - Role taxonomy and architecture
- [Molecules](molecules.md) - Molecule execution and polecat workflow
- [Propulsion Principle](propulsion-principle.md) - Why work triggers immediate execution
- [Polecat Lifecycle Patrol](../design/polecat-lifecycle-patrol.md) - Implementation details, cleanup stages, patrol coordination
- [Persistent Polecat Pool](../design/persistent-polecat-pool.md) - Pool management design and shipping status

---

## File: docs/concepts/propulsion-principle.md

# The Propulsion Principle

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

Gas Town is a steam engine. Agents are pistons. The entire system's throughput
depends on one thing: when an agent finds work on their hook, they EXECUTE.

## Why This Matters

- There is no supervisor polling asking "did you start yet?"
- The hook IS your assignment - it was placed there deliberately
- Every moment you wait is a moment the engine stalls
- Other agents may be blocked waiting on YOUR output

## The Handoff Contract

When you were spawned, work was hooked for you. The system trusts that:

1. You will find it on your hook
2. You will understand what it is (`bd show` / `gt hook`)
3. You will BEGIN IMMEDIATELY

This isn't about being a good worker. This is physics. Steam engines don't
run on politeness - they run on pistons firing. You are the piston.

## Molecule Navigation: Key Enabler

Molecules enable propulsion by providing clear waypoints. You don't need to
memorize steps or wait for instructions - discover them:

### Orientation Commands

```bash
gt hook              # What's on my hook?
gt prime             # Shows inline formula checklist
bd show    # What's my assigned issue?
```

### The New Workflow: Inline Formula Steps

Formula steps are shown inline at prime time — no step beads to manage:

```bash
gt prime             # See your checklist
# Work through each step in order
gt done              # Submit and self-clean (polecats)
gt patrol report     # Close + next cycle (patrol agents)
```

No step closures, no `bd mol current`, no momentum-killing transitions.

**The new workflow (propulsion):**
```bash
bd close gt-abc.3 --continue
```

One command. Auto-advance. Momentum preserved.

### The Propulsion Loop

```
1. gt hook                   # What's hooked?
2. bd mol current             # Where am I?
3. Execute step
4. bd close <step> --continue # Close and advance
5. GOTO 2
```

## The Failure Mode We're Preventing

```
Polecat restarts with work on hook
  → Polecat announces itself
  → Polecat waits for confirmation
  → Witness assumes work is progressing
  → Nothing happens
  → Gas Town stops
```

## Startup Behavior

1. Check hook (`gt hook`)
2. Work hooked → EXECUTE immediately
3. Hook empty → Check mail for attached work
4. Nothing anywhere → ERROR: escalate to Witness

**Note:** "Hooked" means work assigned to you. This triggers autonomous mode
even if no molecule is attached. Don't confuse with "pinned" which is for
permanent reference beads.

## The Capability Ledger

Every completion is recorded. Every handoff is logged. Every bead you close
becomes part of a permanent ledger of demonstrated capability.

- Your work is visible
- Redemption is real (consistent good work builds over time)
- Every completion is evidence that autonomous execution works
- Your CV grows with every completion

This isn't just about the current task. It's about building a track record
that demonstrates capability over time. Execute with care.

---

## File: docs/contrib-harnesses/polecat-pr-flow/polecat.md

## PR-Flow Polecat Policy

> **Rig Policy — overrides formula instructions where they conflict.**

This rig uses a **polecat → GitHub PR → human review** flow. After pushing
your branch, you MUST ensure a GitHub PR is open for it before running
`gt done`.

This overrides the canonical Refinery merge-queue assumption embedded in
`mol-polecat-work`. `gt done` is still the completion signal — but in this
rig, a visible PR is the gating artifact for review.

### Required steps after implementation

1. Push the branch explicitly (do not rely on `gt done` to push):
   ```bash
   git push -u origin HEAD
   ```
2. Check whether a PR already exists for the branch:
   ```bash
   gh pr view "$(git branch --show-current)" >/dev/null 2>&1
   ```
3. If no PR exists, create one against the base branch:
   ```bash
   gh pr create --fill --base main
   ```
4. Only then run `gt done`.

### Do NOT

- Run `gt done` without a PR open — the review loop breaks.
- Merge your own PR. A maintainer or the merge queue handles merging.
- Push directly to `main`.

### If `gh` commands fail

Auth, rate-limit, missing PR template, or unknown base branch — do NOT skip
PR creation to unblock yourself. Escalate to your Witness:

```bash
gt mail send <rig>/witness -s "HELP: gh pr create failed" -m "Branch: $(git branch --show-current)
Error: 
Tried: <what you attempted>"
```

---

## File: docs/contrib-harnesses/polecat-pr-flow/README.md

# polecat-pr-flow

A reference harness for rigs that gate polecat work on a **GitHub PR** rather
than the canonical Refinery **merge-queue** flow.

It instructs polecats, after their final build/pre-verify passes, to push
their branch and open (or confirm) a GitHub PR before running `gt done`.

## What's in here

| File | Purpose |
|------|---------|
| `polecat.md` | Role directive for polecats in a PR-flow rig. Broad guardrail — applies to any formula a polecat runs. |
| `mol-polecat-work.toml` | Formula overlay that appends a PR-creation step to `mol-polecat-work`'s `submit-and-exit` step. Surgical — only affects this formula. |

Both layers are intentional: the directive sets the rig-level expectation
("open PRs, don't merge them yourself"), and the overlay wires the concrete
commands into the workflow a polecat actually sees at `gt prime` time.

## Install

```bash
# Role directive (rig-scoped)
mkdir -p ~/gt/<rig>/directives
cp polecat.md ~/gt/<rig>/directives/polecat.md

# Formula overlay (rig-scoped)
mkdir -p ~/gt/<rig>/formula-overlays
cp mol-polecat-work.toml ~/gt/<rig>/formula-overlays/mol-polecat-work.toml
```

Replace `<rig>` with your rig's name (e.g. `gastown`, `longeye`). For
town-wide installation, drop the `<rig>/` segment — but this is almost
never what you want, since different rigs legitimately use different flows.

## Verify it's active

```bash
# Validate overlay step IDs against the current formula
gt doctor
# Expect: overlay-health: N overlay(s) healthy

# Inspect the rendered formula with the overlay applied
gt formula overlay show mol-polecat-work --rig <rig>

# See the directive text that will be injected at prime time
gt directive show polecat --rig <rig>

# End-to-end: see what a polecat would see
gt prime --explain
# Expect: "Formula overlay: applying 1 override(s) for mol-polecat-work (rig=<rig>)"
```

## What this does / does not do

**Does:**

- Tells the polecat to push and open a PR before `gt done`
- Sets a rig-level policy that a PR is the review artifact
- Surfaces `gh pr create` failure as an escalation to Witness, not a silent skip

**Does not:**

- Modify `gt done` behavior (no Go changes)
- Force PR creation via framework-level validation (agents can still misbehave)
- Merge the PR (that's a maintainer / merge-queue concern)
- Replace the directive or overlay if your rig also uses other customizations
  — merge this content with your existing files rather than overwriting them

## When to fork this

If your rig needs additional PR-flow constraints (required reviewers, specific
labels, CODEOWNERS enforcement, CI checks before `gt done`), copy this harness
and adapt it. The point is a starting template, not a drop-in product.

## Fixing an existing PR (gh#3602)

By default `gt sling` creates a fresh `polecat/<name>/+<ts>` branch from
`main`, which means re-slinging a bead with an existing open PR opens a
**duplicate** PR rather than reusing the original. To resume an existing PR
branch, use `--branch` or `--pr`:

```bash
# Resume by branch name (works for any open or stashed branch)
gt sling  <rig> --branch polecat/example/gh-1234+abcdef

# Resume by PR number (resolves the head ref via `gh pr view`)
gt sling  <rig> --pr 1234
```

The polecat's worktree HEAD will land on the named branch, so its commits
extend the existing PR's history and `gt done` pushes back to the same ref.

**Constraints:**

- `--branch` and `--pr` are mutually exclusive.
- Neither can be combined with `--base-branch` (resume implies its own start point).
- The `--pr` form requires the `gh` CLI to be authenticated against the repo.

The resume branch name is also exposed to formulas as the `resume_branch`
variable, alongside the existing `base_branch`, so overlays can react to it.

## 2. Official Technical Reference & Guides (gastownhall/docs)

# Mintlify Starter Kit

Use the starter kit to get your docs deployed and ready to customize.

Click the green **Use this template** button at the top of this repo to copy the Mintlify starter kit. The starter kit contains examples with

- Guide pages
- Navigation
- Customizations
- API reference pages
- Use of popular components

**[Follow the full quickstart guide](https://starter.mintlify.com/quickstart)**

## AI-assisted writing

Set up your AI coding tool to work with Mintlify:

```bash
npx skills add https://mintlify.com/docs
```

This command installs Mintlify's documentation skill for your configured AI tools like Claude Code, Cursor, Windsurf, and others. The skill includes component reference, writing standards, and workflow guidance.

See the [AI tools guides](/ai-tools) for tool-specific setup.

## Development

Install the [Mintlify CLI](https://www.npmjs.com/package/mint) to preview your documentation changes locally. To install, use the following command:

```
npm i mint
```

Run the following command at the root of your documentation, where your `docs.json` is located:

```
mint dev
```

View your local preview at `http://localhost:3000`.

## Publishing changes

Install our GitHub app from your [dashboard](https://dashboard.mintlify.com/settings/organization/github-app) to propagate changes from your repo to your deployment. Changes are deployed to production automatically after pushing to the default branch.

## Need help?

### Troubleshooting

- If your dev environment isn't running: Run `mint update` to ensure you have the most recent version of the CLI.
- If a page loads as a 404: Make sure you are running in a folder with a valid `docs.json`.

### Resources
- [Mintlify documentation](https://mintlify.com/docs)