{"owner":"gastownhall","repo":"gastown","hasSkills":true,"totalSkillsCount":11,"totalTokensCount":14533,"categories":["command-prompt","anthropic-skill","root-instruction","copilot-instructions"],"hasMcp":false,"mcpConfig":null,"found":[".claude/commands/backup.md",".claude/commands/patrol.md",".claude/commands/reaper.md",".claude/skills/crew-commit/SKILL.md",".claude/skills/ghi-list/SKILL.md",".claude/skills/pr-list/SKILL.md",".claude/skills/pr-sheriff/skill.md",".cursor/skills/gas-town-cursor/SKILL.md","AGENTS.md","docs/skills/convoy/SKILL.md","internal/hooks/templates/copilot/copilot-instructions.md"],"skills":{".claude/commands/backup.md":"---\ndescription: Run Dolt database backup — sync production DBs to backup remotes and iCloud\nallowed-tools: Bash(gt dolt status:*), Bash(dolt backup:*), Bash(dolt log:*), Bash(rsync:*), Bash(du:*), Bash(cat:*), Bash(mkdir:*), Bash(timeout:*), Bash(gt escalate:*), Bash(ls:*)\nargument-hint: [--skip-offsite]\n---\n\n# Dolt Backup\n\nSync production Dolt databases to filesystem backups with smart change detection.\nRuns the same cycle as `mol-dog-backup` / the `dolt-backup` plugin.\n\nArguments: $ARGUMENTS\nIf `--skip-offsite` is passed, skip the iCloud rsync step.\n\n## Configuration\n\n```\nDOLT_DATA_DIR=~/gt/.dolt-data\nBACKUP_DIR=~/gt/.dolt-backup\nICLOUD_DIR=~/Library/Mobile Documents/com~apple~CloudDocs/gt-dolt-backup\nPROD_DBS: auto-discovered (databases with <name>-backup remotes)\nBACKUP_TIMEOUT=120s per database\nHANG_THRESHOLD=30s for server ping\nDOLT_PORT=3307\n```\n\n## Execution Steps\n\n### Step 1: Verify Dolt server is responsive\n\n```bash\ngt dolt status\n```\n\nAlso ping directly to detect hangs:\n\n```bash\ntimeout 30 dolt sql --host 127.0.0.1 --port 3307 --user root --password \"\" \\\n  --no-tls -q \"SELECT 1\" --result-format csv\n```\n\nIf the ping hangs (takes > 30s) or fails:\n```bash\ngt escalate \"dolt-backup: Dolt server hung or unreachable\" -s CRITICAL\n```\nSTOP — do not attempt backups against a hung server.\n\n### Step 2: Discover databases with backup remotes\n\nList directories in `~/gt/.dolt-data/` and check each for a `<name>-backup` remote:\n\n```bash\nls ~/gt/.dolt-data/\n```\n\nFor each directory (skip dotfiles):\n```bash\ncd ~/gt/.dolt-data/<name> && dolt backup\n```\n\nIf the output contains `<name>-backup`, include it in the backup list.\nExpected databases: `hq`, `beads`, `gastown`.\n\n### Step 3: Check each DB for changes and sync\n\nFor each database with a backup remote:\n\n**3a. Get current HEAD hash:**\n```bash\ncd ~/gt/.dolt-data/<name> && dolt log -n 1 --oneline | head -1 | cut -d' ' -f1\n```\n\n**3b. Compare against last backed-up hash:**\n```bash\ncat ~/gt/.dolt-backup/<name>/.last-backup-hash 2>/dev/null\n```\n\nIf hashes match and current hash is not \"unknown\", skip (unchanged).\n\n**3c. Sync if changed:**\n```bash\ncd ~/gt/.dolt-data/<name> && timeout 120 dolt backup sync <name>-backup\n```\n\n**3d. Record successful hash:**\n```bash\nmkdir -p ~/gt/.dolt-backup/<name>\necho \"<current_hash>\" > ~/gt/.dolt-backup/<name>/.last-backup-hash\n```\n\n**3e. Get backup size:**\n```bash\ndu -sh ~/gt/.dolt-backup/<name> 2>/dev/null | cut -f1\n```\n\n### Step 4: Offsite sync to iCloud Drive\n\nUnless `--skip-offsite` was specified:\n\n```bash\nmkdir -p ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup\nrsync -a --delete ~/gt/.dolt-backup/ ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup/\n```\n\nIf iCloud is unavailable, log and continue — not fatal.\n\n### Step 5: Report\n\nPrint a summary in this format:\n\n```\n## Backup Report\n\n**Databases synced**: N/M\n**Databases skipped** (unchanged): N\n**Databases failed**: N\n**Offsite sync**: ok | failed | skipped\n\n### Per Database\n- <name>: synced in Ns (<size>) | unchanged (<hash>) | FAILED: <error>\n\n### Failures\n<list or \"None\">\n```\n\nIf any database failed or server was hung:\n```bash\ngt escalate \"dolt-backup FAILED: <summary>\" -s HIGH\n```\n\nIf server was hung, use `-s CRITICAL` instead.\n",".claude/commands/patrol.md":"---\ndescription: Run a patrol cycle for the current agent role (witness, deacon, or refinery)\nallowed-tools: Bash(gt patrol:*), Bash(gt hook:*), Bash(gt mail:*), Bash(gt nudge:*), Bash(gt peek:*), Bash(gt escalate:*), Bash(gt dolt status:*), Bash(bd :*), Bash(gt mol:*)\nargument-hint: [witness|deacon|refinery]\n---\n\n# Patrol\n\nRun one patrol cycle for the specified role. Patrol is a continuous monitoring\nloop — each invocation executes one cycle of the patrol formula.\n\nArguments: $ARGUMENTS\nIf no role specified, detect from current GT_ROLE environment variable.\n\n## Role Detection\n\n```bash\necho $GT_ROLE\n```\n\nMap to patrol type:\n- `*/witness` → witness patrol (`mol-witness-patrol`)\n- `*/deacon` or `*/deacon/*` → deacon patrol (`mol-deacon-patrol`)\n- `*/refinery` → refinery patrol (`mol-refinery-patrol`)\n- Explicit argument overrides detection\n\n## Patrol Entry Point\n\n```bash\ngt patrol new --role <role>\n```\n\nThis creates a hooked wisp with steps from the patrol formula.\nIf a patrol is already running (wisp exists on hook), resume it instead.\n\n## Witness Patrol Steps\n\nThe witness is the per-rig polecat supervisor. Execute in order:\n\n### 1. inbox-check\n```bash\ngt mail inbox\n```\nProcess any pending messages: POLECAT_DONE, MERGED, HELP, escalations.\nRead each with `gt mail read <id>` and take appropriate action.\n\n### 2. process-cleanups\nCheck for cleanup wisps (dirty state from dead polecats):\n```bash\nbd list --status=open --label=cleanup --json\n```\nProcess each: verify git state, clean worktrees, close cleanup wisps.\n\n### 3. check-refinery\n```bash\ngt peek gastown/refinery\n```\nVerify refinery is alive and processing the merge queue.\nIf stuck, nudge: `gt nudge gastown/refinery \"Health check — are you processing?\"`\n\n### 4. survey-workers\nCheck all active polecats in the rig:\n```bash\ngt peek gastown/polecats\n```\nFor each active polecat:\n- Check if session is alive (has recent activity)\n- Check if work is progressing (commits, bead updates)\n- Detect zombies: session dead but agent_state says working\n- Detect stale spawns: spawning > 10 minutes\n\nNudge idle polecats:\n```bash\ngt nudge gastown/polecats/<name> \"Progress check — what's your status?\"\n```\n\n### 5. check-timer-gates\n```bash\nbd list --label=gate:timer --status=open --json\n```\nEvaluate any timer-based gates that may have elapsed.\n\n### 6. check-swarm\nCheck for convoy/swarm completion across coordinated work:\n```bash\nbd list --label=convoy --status=open --json\n```\n\n### 7. patrol-cleanup\nClose completed patrol wisps, update metrics.\n\n### 8. context-check\nCheck remaining context budget. If approaching limit:\n```bash\ngt handoff -s \"Patrol cycling\" -m \"Patrol cycle N complete, cycling for fresh context\"\n```\n\n### 9. loop-or-exit\nReport cycle results and spawn next cycle:\n```bash\ngt patrol report --summary \"<cycle summary>\" --steps \"inbox:OK,cleanup:OK,...\"\n```\n\n## Deacon Patrol Steps\n\nThe deacon is the town-wide daemon monitor. Key steps:\n\n1. **inbox-check** — Process callbacks from witnesses, refineries, polecats\n2. **trigger-pending-spawns** — Launch queued polecat spawns\n3. **gate-evaluation** — Check async gates (timer, dependency)\n4. **dispatch-gated-molecules** — Release molecules whose gates cleared\n5. **check-convoy-completion** — Track multi-rig coordinated work\n6. **health-scan** — Check Dolt health (`gt dolt status`), agent health\n7. **zombie-scan** — Find dead sessions, orphaned wisps\n8. **plugin-run** — Execute enabled plugins (backup, reaper, etc.)\n9. **dog-pool-maintenance** — Manage utility worker pool\n10. **orphan-check** — Find orphaned test databases (`gt dolt cleanup`)\n11. **session-gc** — Clean up dead session artifacts\n12. **patrol-cleanup** — Close completed wisps, update metrics\n13. **context-check** — Check context budget, handoff if needed\n14. **loop-or-exit** — Report and spawn next cycle\n\n## Refinery Patrol Steps\n\nThe refinery processes the merge queue sequentially:\n\n1. **inbox-check** — Look for MERGE_READY messages from witness\n2. **queue-scan** — List pending MRs in merge queue\n3. **process-branch** — Fetch and rebase next MR branch onto target\n4. **run-tests** — Execute configured gate suite on rebased branch\n5. **handle-failures** — On test failure: bisect, isolate culprit, notify\n6. **merge-push** — Fast-forward push to main: `git push origin temp:main`\n7. **notify** — Send MERGED mail to witness immediately after push\n8. **cleanup** — Close MR bead, delete remote branch, archive mail\n9. **context-check** — Check context budget\n10. **loop-or-exit** — Report and spawn next cycle\n\n## Cycle Completion\n\nEach cycle ends with:\n```bash\ngt patrol report --summary \"<what happened>\" --steps \"<step1:OK,step2:SKIP,...>\"\n```\n\nThis closes the current patrol wisp and spawns the next cycle automatically.\n",".claude/commands/reaper.md":"---\ndescription: Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases\nallowed-tools: Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*)\nargument-hint: [--dry-run]\n---\n\n# Wisp Reaper\n\nReap stale wisps and close stale issues across all production Dolt databases.\nRuns the same cycle as `mol-dog-reaper` but directly, without Dog dispatch.\n\nArguments: $ARGUMENTS\nIf `--dry-run` is passed, report counts without making changes.\n\n## Configuration Defaults\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| max_age | 24h | Wisps older than this are reaped (closed) |\n| purge_age | 72h | Closed wisps older than this are purged (deleted) |\n| stale_issue_age | 168h | Issues stale longer than this are auto-closed |\n| mail_delete_age | 72h | Closed mail older than this is purged |\n| alert_threshold | 3000 | Open wisp count that triggers escalation |\n| dolt_port | 3307 | Dolt server port |\n\n## Execution Steps\n\n### Step 1: Verify Dolt server health\n\n```bash\ngt dolt status\n```\n\nIf the server is unhealthy or unreachable, STOP and escalate:\n```bash\ngt escalate \"Reaper blocked: Dolt server unhealthy\" -s HIGH\n```\n\n### Step 2: Discover databases\n\n```bash\ngt reaper databases --json\n```\n\nThis lists all production databases on the Dolt server.\nExpected databases: `hq`, `beads`, `gastown` (and any rig-specific DBs).\n\n### Step 3: Scan each database for candidates\n\nFor each database returned in Step 2:\n\n```bash\ngt reaper scan --db=<name> --port=3307 \\\n  --max-age=24h --purge-age=72h \\\n  --mail-age=72h --stale-age=168h \\\n  --json\n```\n\nInspect the JSON output:\n- `reap_candidates`: wisps eligible for closing\n- `purge_candidates`: closed wisps eligible for deletion\n- `open_wisps`: total open wisp count\n- `anomalies`: array of detected problems\n\nIf `open_wisps` exceeds 3000 across all databases, note for escalation.\nIf no candidates found across all databases, report \"nothing to reap\" and stop.\n\n### Step 4: Reap stale wisps\n\nFor each database with reap candidates:\n\n```bash\ngt reaper reap --db=<name> --port=3307 --max-age=24h [--dry-run] --json\n```\n\n**IMPORTANT**: Scan/reap count mismatch is NORMAL (witness closes wisps concurrently).\nDo NOT escalate scan > reap mismatches. Only escalate actual errors.\n\n### Step 5: Purge old closed wisps and mail\n\nFor each database with purge candidates:\n\n```bash\ngt reaper purge --db=<name> --port=3307 \\\n  --purge-age=72h --mail-age=72h [--dry-run] --json\n```\n\nWatch for `dolt_commit_failed` anomalies — purged data may not persist.\n\n### Step 6: Auto-close stale issues\n\nFor each database with stale candidates:\n\n```bash\ngt reaper auto-close --db=<name> --port=3307 \\\n  --stale-age=168h [--dry-run] --json\n```\n\nAuto-close NEVER touches: P0/P1 issues, epics, or issues with active dependencies.\n\n### Step 7: Report\n\nPrint a summary in this format:\n\n```\n## Reaper Report\n\n**Databases scanned**: N\n**Wisps reaped**: N (stale open wisps closed)\n**Wisps purged**: N (old closed wisps deleted)\n**Mail purged**: N (old closed mail deleted)\n**Issues auto-closed**: N (stale issues past 168h)\n**Open wisps remaining**: N\n**Anomalies**: <list or \"none\">\n```\n\nIf anomalies were found:\n```bash\ngt escalate \"Reaper anomalies detected\" -s MEDIUM -m \"<anomaly details>\"\n```\n",".claude/skills/crew-commit/SKILL.md":"---\nname: crew-commit\ndescription: >\n  Canonical commit workflow for Gas Town crew members: pre-flight checks,\n  branch creation, gt commit with agent identity, push, and PR creation.\n  Use when ready to commit and submit work for review.\nallowed-tools: \"Bash(git *), Bash(gt *), Bash(gh *)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# Crew Commit — Canonical Git Workflow\n\nThis skill guides crew members through the standard Gas Town commit workflow:\npre-flight → branch → stage → commit → push → PR.\n\n> **⚠️ NEVER commit directly to `main`.** All crew work goes through branches\n> and pull requests. The Refinery handles merges to main.\n\n## Usage\n\n```\n/crew-commit\n```\n\nRun this when you have changes ready to commit. The skill walks you through\neach step in order.\n\n---\n\n## Step 1: Pre-flight Checks\n\nBefore touching anything, sync with origin and verify your state.\n\n```bash\n# Fetch latest from origin\ngit fetch origin\n\n# Check current branch and status\ngit status\ngit branch --show-current\n\n# If you're on main, STOP — create a branch first (Step 2)\n```\n\n**If you're behind origin/main**, rebase now:\n\n```bash\ngit rebase origin/main\n```\n\nIf there are conflicts, resolve them carefully before proceeding.\nIf stuck on a rebase conflict, stop and get help rather than force-pushing.\n\n---\n\n## Step 2: Create a Feature Branch\n\n**If you're already on a feature branch**, skip to Step 3.\n\nBranch naming convention: `<type>/<short-description>`\n\nTypes:\n- `feat/` — new feature\n- `fix/` — bug fix\n- `refactor/` — code restructuring\n- `docs/` — documentation only\n- `chore/` — maintenance, deps, config\n- `test/` — tests only\n\n```bash\n# Create and switch to feature branch\ngit checkout -b feat/my-feature-description\n\n# Or use the crew/<name> prefix for crew-specific branches\ngit checkout -b crew/<your-name>/description\n```\n\n---\n\n## Step 3: Submodule Warning\n\n**Check for submodules before staging.** Accidentally committing a submodule\npointer change causes cascading failures for other crew members.\n\n```bash\n# Check if repo has submodules\ncat .gitmodules 2>/dev/null || echo \"(no submodules)\"\n\n# Check for dirty submodule state\ngit submodule status 2>/dev/null\n```\n\n**Common submodule paths to watch:** `shared/`, `config/`, `vendor/`\n\nIf you see changes in submodule directories:\n- Do NOT `git add shared/` or `git add config/` unless you intentionally\n  bumped the submodule pointer\n- Submodule pointer changes should be explicit and deliberate\n- When in doubt, ask before including submodule changes\n\n---\n\n## Step 4: Stage Your Changes\n\nPrefer staging specific files over `git add .` or `git add -A`.\n\n```bash\n# Review what changed\ngit diff\ngit status\n\n# Stage specific files (preferred)\ngit add src/myfile.go tests/myfile_test.go\n\n# If you need to stage all intentional changes and have verified no secrets:\ngit add -p    # Interactive staging — review each hunk\n```\n\n**Before staging, verify:**\n- [ ] No `.env` files, API keys, or credentials\n- [ ] No debug prints or temporary test code\n- [ ] No unrelated changes mixed in\n- [ ] Submodule directories NOT accidentally staged (unless intentional)\n\n---\n\n## Step 5: Commit with gt commit\n\nUse `gt commit` instead of `git commit`. It automatically sets the correct\nagent identity (name + email) based on your `GT_ROLE`.\n\n```bash\ngt commit -m \"$(cat <<'EOF'\n<type>: <concise description of what and why>\n\n<optional body: context, motivation, or notable details>\nEOF\n)\"\n```\n\n**Commit message format:**\n- First line: `<type>: <subject>` (50 chars or less)\n- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`\n- Use imperative mood: \"add feature\" not \"added feature\"\n- Body is optional but valuable for non-obvious changes\n\n**Good examples:**\n```\nfeat: add retry logic to webhook delivery\nfix: prevent nil pointer when session token expires\ndocs: clarify crew commit workflow in CONTRIBUTING.md\n```\n\n---\n\n## Step 6: Push Branch to Origin\n\n```bash\ngit push origin <your-branch-name>\n\n# Or, if branch doesn't exist on remote yet:\ngit push -u origin <your-branch-name>\n```\n\n---\n\n## Step 7: Create Pull Request\n\n```bash\ngh pr create --title \"<type>: <concise description>\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- <what changed and why>\n\n## Test plan\n\n- [ ] <how to verify this works>\n\n## Notes\n\n<any context reviewers need>\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\nEOF\n)\"\n```\n\nAfter creating the PR, note the PR number from the output.\n\n---\n\n## Step 8: Notify (Optional)\n\nIf your work affects others or is high priority:\n\n```bash\nnotify \"PR ready: <brief description> — #<PR number>\"\n```\n\n---\n\n## Completion Checklist\n\n- [ ] Synced with origin/main (git fetch + rebase)\n- [ ] On a feature branch (NOT main)\n- [ ] Submodules NOT accidentally staged\n- [ ] Specific files staged (no secrets, no debug code)\n- [ ] Used `gt commit` (not `git commit`)\n- [ ] Branch pushed to origin\n- [ ] PR created via `gh pr create`\n\n---\n\n## Anti-Patterns\n\n| ❌ Don't | ✅ Do instead |\n|----------|--------------|\n| `git push origin main` | Push feature branch, create PR |\n| `git commit` directly | `gt commit` (sets agent identity) |\n| `git add .` blindly | Stage specific files, verify with `git status` |\n| Include `shared/` or `config/` without intent | Check `git submodule status` first |\n| Force-push without understanding why | Resolve the root cause |\n| Commit secrets or .env files | Always check `git diff` before staging |\n\n---\n\n## If You Get Stuck\n\n- **Rebase conflicts**: resolve carefully, then `git rebase --continue`\n- **Pushed wrong branch**: ask before force-pushing; usually `git push origin <branch>` is fine\n- **Need to undo last commit**: `git reset HEAD~1` (keeps changes staged)\n- **Committed to main by mistake**: stop immediately, ask for help\n",".claude/skills/ghi-list/SKILL.md":"---\nname: ghi-list\ndescription: >\n  List GitHub issues in a formatted ASCII table. Supports filters like --state,\n  --assignee, --label. Use for issue triage and tracking workflows.\nallowed-tools: \"Bash(gh issue list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# GHI List - Formatted GitHub Issues Table\n\nDisplay GitHub issues in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/ghi-list [options]\n```\n\n## Options (passed to gh issue list)\n\n- `--state open|closed|all` - Filter by state (default: open)\n- `--assignee <user>` - Filter by assignee\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--author <user>` - Filter by author\n- `--milestone <name>` - Filter by milestone\n\n## Execution Steps\n\n1. Run `gh issue list` with any provided options plus `--json number,assignees,labels,title,state`\n2. Format output as an ASCII table using box-drawing characters\n3. Truncate titles to fit reasonable terminal width (~45 chars)\n4. Show first assignee only, or \"-\" if none\n5. Show first 2-3 labels abbreviated, or \"-\" if none\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌───────┬────────────┬─────────────────┬───────────────────────────────────────────────┬────────┐\n│ Issue │ Assignee   │ Labels          │ Title                                         │ State  │\n├───────┼────────────┼─────────────────┼───────────────────────────────────────────────┼────────┤\n│   372 │ max        │ enhancement     │ Create /pr-list and /ghi-list skills          │ OPEN   │\n│   371 │ -          │ bug, priority   │ Fix null pointer in auth module               │ OPEN   │\n│   370 │ joe        │ -               │ Update documentation for new API              │ CLOSED │\n└───────┴────────────┴─────────────────┴───────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align issue numbers\n- Left-align text columns\n- Pad columns consistently\n- For assignees: show login of first assignee, \"-\" if none\n- For labels: show comma-separated names (truncate if >17 chars)\n- Show count summary below table: \"**N issues** (M open, K closed)\"\n\n## Example Commands\n\n```bash\n# Default - open issues\ngh issue list --json number,assignees,labels,title,state\n\n# With filters\ngh issue list --state all --label bug --json number,assignees,labels,title,state\n```\n",".claude/skills/pr-list/SKILL.md":"---\nname: pr-list\ndescription: >\n  List GitHub PRs in a formatted ASCII table. Supports filters like --state,\n  --author, --label. Use for PR review workflows and sheriff duties.\nallowed-tools: \"Bash(gh pr list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR List - Formatted Pull Request Table\n\nDisplay GitHub pull requests in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/pr-list [options]\n```\n\n## Options (passed to gh pr list)\n\n- `--state open|closed|merged|all` - Filter by state (default: open)\n- `--author <user>` - Filter by author\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--assignee <user>` - Filter by assignee\n- `--draft` - Show only drafts\n- `--all-reviews` - Include PRs with CHANGES_REQUESTED (excluded by default)\n\n## Execution Steps\n\n1. Run `gh pr list` with any provided options plus `--json number,author,title,state,isDraft,reviewDecision`\n2. **Filter out PRs with reviewDecision=\"CHANGES_REQUESTED\"** (unless `--all-reviews` specified)\n3. Format output as an ASCII table using box-drawing characters\n4. Truncate titles to fit reasonable terminal width (~50 chars)\n5. Truncate author names if needed (~18 chars)\n6. Show state as OPEN/CLOSED/MERGED/DRAFT, append \"(changes requested)\" if filtered with --all-reviews\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌─────┬────────────────────┬───────────────────────────────────────────────────┬────────┐\n│  PR │ Author             │ Title                                             │ State  │\n├─────┼────────────────────┼───────────────────────────────────────────────────┼────────┤\n│ 123 │ username           │ feat: add new feature for something               │ OPEN   │\n│ 122 │ another-user       │ fix: resolve bug in component                     │ DRAFT  │\n└─────┴────────────────────┴───────────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align PR numbers\n- Left-align text columns\n- Pad columns consistently\n- Show count summary below table: \"**N open PRs** (M drafts)\"\n\n## Example Commands\n\n```bash\n# Default - open PRs (excludes CHANGES_REQUESTED)\ngh pr list --json number,author,title,state,isDraft,reviewDecision\n\n# With filters\ngh pr list --state all --author boshu2 --json number,author,title,state,isDraft,reviewDecision\n```\n",".claude/skills/pr-sheriff/skill.md":"---\nname: pr-sheriff\ndescription: >\n  PR Sheriff workflow: triage PRs into easy-wins and crew assignments.\n  Prints recommendations inline - does NOT post to GitHub.\nallowed-tools: \"Bash(gh pr *), Bash(git *), Bash(gt *), Bash(bd *), Bash(cat *)\"\nversion: \"2.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR Sheriff - Triage and Review Workflow\n\nThis skill delegates to the `mol-pr-sheriff-patrol` formula, which lives at\n`$GT_ROOT/.beads/formulas/mol-pr-sheriff-patrol.formula.toml` and is shared\nacross all Gas Town rigs (gastown, beads, etc.).\n\n## Repo Scope\n\nThis rig (gastown/crew/max) is responsible for **steveyegge/gastown only**.\nThe beads repo (steveyegge/beads) is handled by beads/crew/emma.\nDo NOT discover or triage PRs from repos outside your scope.\n\nWhen loading the shared config, filter the repo list to only `steveyegge/gastown`.\n\n## Usage\n\n```\n/pr-sheriff [repo]\n```\n\n- `repo` - Optional. If provided, overrides the default scope.\n  If omitted, scan only `steveyegge/gastown` (this rig's scope).\n\n## How to Execute\n\n**1. Load the config:**\n```bash\ncat $GT_ROOT/.beads/pr-sheriff-config.json\n```\n\nThis contains crew mappings per repo and contributor policies\n(trust tiers, firewalled contributors, bot auto-merge rules).\n**Only scan repos within your scope** (see Repo Scope above).\n\n**2. Follow the formula steps in order:**\n```bash\ngt formula show mol-pr-sheriff-patrol\n```\n\nThe formula defines a 7-step workflow:\n\n| Step | What it does |\n|------|-------------|\n| load-config | Load pr-sheriff-config.json, establish repo list |\n| discover-prs | Find open PRs needing review across all repos |\n| triage-batch | Categorize all PRs in one pass (preserves cross-PR context) |\n| merge-easy-wins | Merge approved easy-wins via `gh pr merge` |\n| dispatch-crew-reviews | Nudge crew for NEEDS-CREW PRs |\n| dispatch-deep-reviews | Nudge crew for NEEDS-HUMAN PRs (full evaluation framework) |\n| collect-results | Gather crew review nudge-backs |\n| interactive-review | Walk through remaining NEEDS-HUMAN PRs with overseer |\n| summarize | Print patrol summary |\n\n**3. For each step, read the full description:**\n```bash\ngt formula show mol-pr-sheriff-patrol  # Shows all steps with descriptions\n```\n\n## Key References\n\n- **Patrol formula:** `mol-pr-sheriff-patrol` (town-level)\n- **Crew review formula:** `mol-pr-crew-review` (dispatched to crew)\n- **Deep review formula:** `mol-pr-deep-review` (dispatched for NEEDS-HUMAN)\n- **Config:** `$GT_ROOT/.beads/pr-sheriff-config.json`\n\n## Contributor Policy Tiers\n\nLoaded from config. Current tiers:\n\n| Tier | Handling |\n|------|----------|\n| bot-trusted | Auto-merge if CI passes (e.g., dependabot) |\n| community | Normal triage — easy-win / crew / deep review |\n| firewalled | Always NEEDS-HUMAN, never auto-merge, deep review required |\n\n## Category Decision Tree\n\n```\nDraft? → SKIP\nContributor firewalled? → NEEDS-HUMAN (deep review)\nDependabot patch bump + CI green? → EASY-WIN\n<50 lines, obvious bug/doc/test fix? → EASY-WIN\nSecurity/architecture/API change? → NEEDS-HUMAN\nMulti-concern PR? → NEEDS-HUMAN\n100+ lines new feature? → NEEDS-CREW or NEEDS-HUMAN\nEverything else → NEEDS-CREW\n```\n\n## Deep Review Evaluation Framework (NEEDS-HUMAN)\n\nThe deep review formula (mol-pr-deep-review) applies six lenses:\n\n1. **Plugin/integration fit** — core vs plugin/formula/integration?\n2. **Tech-debt weight** — complexity justified by user breadth?\n3. **Contributor track record** — first-time, repeat, or firewalled?\n4. **ZFC compliance** — structural checks, not string heuristics?\n5. **Problem validity + solution fit** — real problem, right solution?\n6. **Splitability** — can good parts be cherry-picked from bad?\n\nFinal verdicts: MERGE | CHERRY-PICK | REWORK | REIMPLEMENT | CLOSE\n\n## Output Format\n\nFor each PR, print a recommendation block:\n\n```\n### PR #<num>: <title>\nAuthor: <login> | +<additions>/-<deletions> | <changedFiles> files\n\n**Category**: EASY-WIN | NEEDS-CREW | NEEDS-HUMAN | SKIP\n\n**Analysis**:\n<1-3 sentences explaining the change and why it fits this category>\n\n**Recommendation**:\n<specific action>\n```\n\n## Summary Output\n\n```\n## PR Sheriff Patrol Summary — <date>\n\n**Easy-wins merged**: N\n**Crew-reviewed and merged**: N\n**Sent back for rework**: N\n**Closed**: N\n**Still pending**: N\n```\n\n## Dispatching Work: Use Ephemeral Beads\n\nWhen creating beads to track fix-merge work for polecats or crew, **use\nephemeral beads (wisps)** rather than persistent beads. PR review/fix-merge\ntasks are orchestration scaffolding — they exist to give a polecat something\nto hook and track, not to create a permanent record.\n\nEphemeral beads are the right trade-off: they give polecats and crew trackable\nwork items without polluting Dolt's permanent ledger with one-off orchestration\nnoise. If/when beads are exported to permanent ledgers, review-task wisps won't\nclutter the history.\n\n```bash\n# Ephemeral bead for fix-merge dispatch\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review \\\n  --wisp-type patrol\n\n# vs persistent (avoid for orchestration work)\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review\n```\n\nThe `--wisp-type patrol` flag marks it as ephemeral orchestration work that\nthe reaper will eventually clean up. The polecat/crew member can still hook it,\nwork it, and close it normally.\n\n## CRITICAL Rules\n\n- All output is printed inline. Do NOT post comments to GitHub.\n- The overseer decides what gets posted externally.\n- Contributor-friendly: help contributors get to the finish line.\n- Use `Co-authored-by` trailer when fixing up contributor work.\n",".cursor/skills/gas-town-cursor/SKILL.md":"---\nname: gas-town-cursor\ndescription: >\n  Develop and operate Gas Town with the Cursor agent preset (cursor-agent CLI):\n  gt flags, hooks at .cursor/hooks.json, session resume, and how this repo differs from README marketing copy.\n---\n\n# Gas Town + Cursor Agent CLI\n\nUse this skill when working **in this repository** with the **`cursor`** agent preset (CLI binary **`cursor-agent`**, sometimes symlinked as **`agent`**).\n\n## Concepts\n\n| Name | Meaning |\n|------|---------|\n| **Preset `cursor`** | Gas Town agent id (`GT_AGENT=cursor`). Config lives in `internal/config/agents.go` (`AgentCursor`). |\n| **Binary `cursor-agent`** | The Cursor Agent CLI process name for pane/detection; install docs may also symlink `agent` → same binary. |\n| **Hooks** | Cursor lifecycle hooks are configured at **`.cursor/hooks.json`** (see preset `HooksSettingsFile`). |\n\n## Essential commands\n\n- Build / run `gt` from repo root: `make build` or `go run ./cmd/gt …`.\n- Point a session at the Cursor preset: spawn or config so the runtime uses **`--agent cursor`** (or set **`GT_AGENT=cursor`** where applicable).\n- After changing hooks or settings: **`gt up --restore`** (or role-specific restart) so agents reload config.\n\n## Resume semantics\n\nThe Cursor preset uses **`--resume <chatId>`** style resume (`ResumeStyle: flag`). Session identity is not carried in a dedicated env var in the same way as Claude’s `CLAUDE_SESSION_ID`; follow the preset fields in `internal/config/agents.go` (`ResumeFlag`, `ResumeStyle`).\n\n## Read more\n\n- Beads / plan handoff: [`docs/cursor-runtime-beads-tasks.md`](../../../docs/cursor-runtime-beads-tasks.md)\n- Agent instructions for automation: [`AGENTS.md`](../../../AGENTS.md) and [`CLAUDE.md`](../../../CLAUDE.md) (project-wide, not Cursor-only)\n\n## Boundary\n\nProject **README** is user-facing product overview; **`.cursor/README.md`** is Cursor-specific onboarding for this repo. Prefer linking to those files instead of duplicating long install steps inside skills.\n","AGENTS.md":"# Agent Instructions\n\nSee **CLAUDE.md** for complete agent context and instructions.\n\nThis file exists for compatibility with tools that look for AGENTS.md.\n\n> **Recovery**: Run `gt prime` after compaction, clear, or new session\n\nFull context is injected by `gt prime` at session start.\n\n<!-- beads-agent-instructions-v2 -->\n\n---\n\n## Beads Workflow Integration\n\nThis project uses [beads](https://github.com/steveyegge/beads) for issue tracking. Issues live in `.beads/` and are tracked in git.\n\nTwo CLIs: **bd** (issue CRUD) and **bv** (graph-aware triage, read-only).\n\n### bd: Issue Management\n\n```bash\nbd ready              # Unblocked issues ready to work\nbd list --status=open # All open issues\nbd show <id>          # Full details with dependencies\nbd create --title=\"...\" --type=task --priority=2\nbd update <id> --status=in_progress\nbd close <id>         # Mark complete\nbd close <id1> <id2>  # Close multiple\nbd dep add <a> <b>    # a depends on b\nbd sync               # Sync with git\n```\n\n### bv: Graph Analysis (read-only)\n\n**NEVER run bare `bv`** — it launches interactive TUI. Always use `--robot-*` flags:\n\n```bash\nbv --robot-triage     # Ranked picks, quick wins, blockers, health\nbv --robot-next       # Single top pick + claim command\nbv --robot-plan       # Parallel execution tracks\nbv --robot-alerts     # Stale issues, cascades, mismatches\nbv --robot-insights   # Full graph metrics: PageRank, betweenness, cycles\n```\n\n### Workflow\n\n1. **Start**: `bd ready` (or `bv --robot-triage` for graph analysis)\n2. **Claim**: `bd update <id> --status=in_progress`\n3. **Work**: Implement the task\n4. **Complete**: `bd close <id>`\n5. **Sync**: `bd sync` at session end\n\n### Session Close Protocol\n\n```bash\ngit status            # Check what changed\ngit add <files>       # Stage code changes\nbd sync               # Commit beads changes\ngit commit -m \"...\"   # Commit code\nbd sync               # Commit any new beads changes\ngit push              # Push to remote\n```\n\n### Key Concepts\n\n- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (numbers only)\n- **Types**: task, bug, feature, epic, question, docs\n- **Dependencies**: `bd ready` shows only unblocked work\n\n<!-- end-beads-agent-instructions -->\n\n<!-- gastown-agent-instructions-v1 -->\n\n---\n\n## Gas Town Multi-Agent Communication\n\nThis workspace is part of a **Gas Town** multi-agent environment. You communicate\nwith other agents using `gt` commands — never by printing text or using raw tmux.\n\n### Nudging Agents (Immediate Delivery)\n\n`gt nudge` sends a message directly to another agent's active session:\n\n```bash\ngt nudge mayor \"Status update: PR review complete\"\ngt nudge laneassist/crew/dom \"Check your mail — PR ready for review\"\ngt nudge witness \"Polecat health check needed\"\ngt nudge refinery \"Merge queue has items\"\n```\n\n**Target formats:**\n- Role shortcuts: `mayor`, `deacon`, `witness`, `refinery`\n- Full path: `<rig>/crew/<name>`, `<rig>/polecats/<name>`\n\n**Important:** `gt nudge` is the ONLY way to send text to another agent's session.\nNever print \"Hey @name\" — the other agent cannot see your terminal output.\n\n### Sending Mail (Persistent Messages)\n\n`gt mail` sends messages that persist across session restarts:\n\n```bash\n# Reading\ngt mail inbox                    # List messages\ngt mail read <id>                # Read a specific message\n\n# Sending (use --stdin for multi-line content)\ngt mail send mayor/ -s \"Subject\" -m \"Short message\"\ngt mail send laneassist/crew/dom -s \"PR Review\" --stdin <<'BODY'\nMulti-line message content here.\nDetails about the PR and what to look for.\nBODY\ngt mail send --human -s \"Subject\" -m \"Message to overseer\"\n```\n\n### When to Use Which\n\n| Want to... | Command | Why |\n|------------|---------|-----|\n| Wake a sleeping agent | `gt nudge <target> \"msg\"` | Immediate delivery |\n| Send detailed task/info | `gt mail send <target> -s \"...\" --stdin` | Persists across restarts |\n| Both: send + wake | `gt mail send` then `gt nudge` | Mail carries payload, nudge wakes |\n\n### Context Recovery\n\nAfter compaction or new session, run `gt prime` to reload your full role context,\nidentity, and any pending work.\n\n```bash\ngt prime              # Full context reload\ngt hook               # Check for assigned work\ngt mail inbox         # Check for messages\n```\n\n<!-- end-gastown-agent-instructions -->\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `gt prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `gt prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n   ```bash\n   git pull --rebase\n   bd dolt push\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n","docs/skills/convoy/SKILL.md":"---\nname: convoy\ndescription: The definitive guide for working with gastown's convoy system -- batch work tracking, event-driven feeding, stage-launch workflow, and dispatch safety guards. Use when writing convoy code, debugging convoy behavior, adding convoy features, testing convoy changes, or answering questions about how convoys work. Triggers on convoy, convoy manager, convoy feeding, dispatch, stranded convoy, feedFirstReady, feedNextReadyIssue, IsSlingableType, isIssueBlocked, CheckConvoysForIssue, gt convoy, gt sling, stage, launch, staged, wave.\n---\n\n# Gastown Convoy System\n\nThe convoy system tracks batches of work across rigs. A convoy is a bead that `tracks` other beads via dependencies. The daemon monitors close events and feeds the next ready issue when one completes.\n\n## Architecture\n\n```\n+================================ CREATION =================================+\n|                                                                            |\n|   gt sling <beads>      gt convoy create ...     gt convoy stage <epic>    |\n|        |  (auto-convoy)       |  (explicit)            |  (validated)     |\n|        v                      v                        v                  |\n|   +-----------+          +-----------+         +----------------+         |\n|   |  status:  |          |  status:  |         |    status:     |         |\n|   |   open    |          |   open    |         | staged:ready   |         |\n|   +-----------+          +-----------+         | staged:warnings|         |\n|                                                +----------------+         |\n|                                                        |                  |\n|                                              gt convoy launch             |\n|                                                        |                  |\n|                                                        v                  |\n|                                                +----------------+         |\n|                                                |    status:     |         |\n|                                                |     open       |         |\n|                                                | (Wave 1 slung) |         |\n|                                                +----------------+         |\n|                                                                            |\n|   All paths produce: CONVOY (hq-cv-*)                                      |\n|                      tracks: issue1, issue2, ...                           |\n+============================================================================+\n              |                              |\n              v                              v\n+= EVENT-DRIVEN FEEDER (5s) =+   +=== STRANDED SCAN (30s) ===+\n|                              |   |                            |\n|   GetAllEventsSince (SDK)    |   |   findStranded             |\n|     |                        |   |     |                      |\n|     v                        |   |     v                      |\n|   close event detected       |   |   convoy has ready issues  |\n|     |                        |   |   but no active workers    |\n|     v                        |   |     |                      |\n|   CheckConvoysForIssue       |   |     v                      |\n|     |                        |   |   feedFirstReady           |\n|     v                        |   |   (iterates all ready)     |\n|   feedNextReadyIssue         |   |     |                      |\n|   (iterates all ready)       |   |     v                      |\n|     |                        |   |   gt sling <next-bead>     |\n|     v                        |   |   or closeEmptyConvoy     |\n|   gt sling <next-bead>       |   |                            |\n|                              |   +============================+\n+==============================+\n```\n\nThree creation paths (sling, create, stage), two feed paths, same safety guards:\n- **Event-driven** (`operations.go`): Polls beads stores every ~5s for close events. Calls `feedNextReadyIssue` which checks `IsSlingableType` + `isIssueBlocked` before dispatch. **Skips staged convoys** (`isConvoyStaged` check).\n- **Stranded scan** (`convoy_manager.go`): Runs every 30s. `feedFirstReady` iterates all ready issues. The ready list is pre-filtered by `IsSlingableType` in `findStrandedConvoys` (cmd/convoy.go). **Only sees open convoys** — staged convoys never appear.\n\n## Safety guards (the three rules)\n\nThese prevent the event-driven feeder from dispatching work it shouldn't:\n\n### 1. Type filtering (`IsSlingableType`)\n\nOnly leaf work items dispatch. Defined in `operations.go`:\n\n```go\nvar slingableTypes = map[string]bool{\n    \"task\": true, \"bug\": true, \"feature\": true, \"chore\": true,\n    \"\": true, // empty defaults to task\n}\n```\n\nEpics, sub-epics, convoys, decisions -- all skip. Applied in both `feedNextReadyIssue` (event path) and `findStrandedConvoys` (stranded path).\n\n### 2. Blocks dep checking (`isIssueBlocked`)\n\nIssues with unclosed `blocks`, `conditional-blocks`, or `waits-for` dependencies skip. `parent-child` is **not** blocking -- a child task dispatches even if its parent epic is open. This is consistent with `bd ready` and molecule step behavior.\n\nFail-open on store errors (assumes not blocked) to avoid stalling convoys on transient Dolt issues.\n\n### 3. Dispatch failure iteration\n\nBoth feed paths iterate past failures instead of giving up:\n- `feedNextReadyIssue`: `continue` on dispatch failure, try next ready issue\n- `feedFirstReady`: `for range ReadyIssues` with `continue` on skip/failure, `return` on first success\n\n## CLI commands\n\n### Stage and launch (validated creation)\n\n```bash\ngt convoy stage <epic-id>            # analyze deps, build DAG, compute waves, create staged convoy\ngt convoy stage gt-task1 gt-task2    # stage from explicit task list\ngt convoy stage hq-cv-abc            # re-stage existing staged convoy\ngt convoy stage <epic-id> --json     # machine-readable output\ngt convoy stage <epic-id> --launch   # stage + immediately launch if no errors\ngt convoy launch hq-cv-abc           # transition staged → open, dispatch Wave 1\ngt convoy launch <epic-id>           # stage + launch in one step (delegates to stage --launch)\n```\n\n### Create and manage\n\n```bash\ngt convoy create \"Auth overhaul\" gt-task1 gt-task2 gt-task3\ngt convoy add hq-cv-abc gt-task4\n```\n\n### Check and monitor\n\n```bash\ngt convoy check hq-cv-abc       # auto-closes if all tracked issues done\ngt convoy check                  # check all open convoys\ngt convoy status hq-cv-abc       # single convoy detail\ngt convoy list                   # all convoys\ngt convoy list --all             # include closed\n```\n\n### Find stranded work\n\n```bash\ngt convoy stranded               # ready work with no active workers\ngt convoy stranded --json        # machine-readable\n```\n\n### Close and land\n\n```bash\ngt convoy close hq-cv-abc --reason \"done\"\ngt convoy land hq-cv-abc         # cleanup worktrees + close\n```\n\n### Interactive TUI\n\n```bash\ngt convoy -i                     # opens interactive convoy browser\ngt convoy --interactive          # long form\n```\n\n## Batch sling behavior\n\n`gt sling <bead1> <bead2> <bead3>` creates **one convoy** tracking all beads. The rig is auto-resolved from the beads' prefixes (via `routes.jsonl`). The convoy title is `\"Batch: N beads to <rig>\"`. Each bead gets its own polecat, but they share a single convoy for tracking.\n\nThe convoy ID and merge strategy are stored on each bead, so `gt done` can find the convoy via the fast path (`getConvoyInfoFromIssue`).\n\n### Rig resolution\n\n- **Auto-resolve (preferred):** `gt sling gt-task1 gt-task2 gt-task3` -- resolves rig from the `gt-` prefix. All beads must resolve to the same rig.\n- **Explicit rig (deprecated):** `gt sling gt-task1 gt-task2 gt-task3 myrig` -- still works, prints a deprecation warning. If any bead's prefix doesn't match the explicit rig, errors with suggested actions.\n- **Mixed prefixes:** If beads resolve to different rigs, errors listing each bead's resolved rig and suggested actions (sling separately, or `--force`).\n- **Unmapped prefix:** If a prefix has no route, errors with diagnostic info (`cat .beads/routes.jsonl | grep <prefix>`).\n\n### Conflict handling\n\nIf any bead is already tracked by another convoy, batch sling **errors** with detailed conflict info (which convoy, all beads in it with statuses, and 4 recommended actions). This prevents accidental double-tracking.\n\n```bash\n# Auto-resolve: one convoy, three polecats (preferred)\ngt sling gt-task1 gt-task2 gt-task3\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n\n# Explicit rig still works but prints deprecation warning\ngt sling gt-task1 gt-task2 gt-task3 gastown\n# -> Deprecation: gt sling now auto-resolves the rig from bead prefixes.\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n```\n\n## Stage-launch workflow\n\n> Implemented in [PR #1820](https://github.com/steveyegge/gastown/pull/1820). Depends on the feeder safety guards from [PR #1759](https://github.com/steveyegge/gastown/pull/1759). Design docs: `docs/design/convoy/stage-launch/prd.md`, `docs/design/convoy/stage-launch/testing.md`.\n\nThe stage-launch workflow is a two-phase convoy creation path that validates dependencies and computes wave dispatch order **before** any work is dispatched. This is the preferred path for epic delivery.\n\n### Input types\n\n`gt convoy stage` accepts three mutually exclusive input types:\n\n| Input | Example | Behavior |\n|-------|---------|----------|\n| Epic ID | `gt convoy stage bcc-nxk2o` | BFS walks entire parent-child tree, collects all descendants |\n| Task list | `gt convoy stage gt-t1 gt-t2 gt-t3` | Analyzes exactly those tasks |\n| Convoy ID | `gt convoy stage hq-cv-abc` | Re-reads tracked beads from existing staged convoy (re-stage) |\n\nMixed types (e.g., epic + task together) error. Multiple epics or multiple convoys error.\n\n### Processing pipeline\n\n```\n1. validateStageArgs     — reject empty/flag-like args\n2. bdShow each arg       — resolve bead types\n3. resolveInputKind      — classify Epic / Tasks / Convoy\n4. collectBeads          — gather BeadInfo + DepInfo (BFS for epic, direct for tasks)\n5. buildConvoyDAG        — construct in-memory DAG (nodes + edges)\n6. detectErrors          — cycle detection + missing rig checks\n7. detectWarnings        — orphans, parked rigs, cross-rig, capacity, missing branches\n8. categorizeFindings    — split into errors / warnings\n9. chooseStatus          — staged:ready, staged:warnings, or abort on errors\n10. computeWaves         — Kahn's algorithm (only when no errors)\n11. renderDAGTree        — print ASCII dependency tree\n12. renderWaveTable      — print wave dispatch plan\n13. createStagedConvoy   — bd create --type=convoy --status=<staged-status>\n```\n\n### Wave computation (Kahn's algorithm)\n\nOnly slingable types participate in waves: `task`, `bug`, `feature`, `chore`. Epics are excluded.\n\nExecution edges (create wave ordering):\n- `blocks`\n- `conditional-blocks`\n- `waits-for`\n\nNon-execution edges (ignored for wave ordering):\n- `parent-child` — hierarchy only\n- `related`, `tracks`, `discovered-from`\n\n**Algorithm:**\n1. Filter to slingable nodes only\n2. Calculate in-degree for each node (count BlockedBy edges to other slingable nodes)\n3. Peel loop: collect all nodes with in-degree 0 → Wave N; remove them; decrement neighbors; repeat\n4. Sort within each wave alphabetically for determinism\n\nOutput example:\n```\n  Wave   ID              Title                     Rig       Blocked By\n  ──────────────────────────────────────────────────────────────────────\n  1      bcc-nxk2o.1.1   Init scaffolding          bcc       —\n  2      bcc-nxk2o.1.2   Shared types              bcc       bcc-nxk2o.1.1\n  3      bcc-nxk2o.1.3   CLI wrapper               bcc       bcc-nxk2o.1.2\n\n  3 tasks across 3 waves (max parallelism: 1 in wave 1)\n```\n\n### Convoy status model\n\nFour statuses with defined transitions:\n\n| Status | Meaning |\n|--------|---------|\n| `staged:ready` | Validated, no errors or warnings, ready to launch |\n| `staged:warnings` | Validated, no errors but has warnings. Fix and re-stage, or launch anyway. |\n| `open` | Active — daemon feeds work as beads close |\n| `closed` | Complete or cancelled |\n\nValid transitions:\n\n| From → To | Allowed? |\n|-----------|----------|\n| `staged:ready` → `open` | Yes (launch) |\n| `staged:warnings` → `open` | Yes (launch) |\n| `staged:*` → `closed` | Yes (cancel) |\n| `staged:ready` ↔ `staged:warnings` | Yes (re-stage) |\n| `open` → `closed` | Yes |\n| `closed` → `open` | Yes (reopen) |\n| `open` → `staged:*` | **No** |\n| `closed` → `staged:*` | **No** |\n\n### Error vs warning classification\n\n**Errors** (fatal — prevent convoy creation):\n\n| Category | Trigger | Fix |\n|----------|---------|-----|\n| `cycle` | Cycle detected in execution edges | Remove one blocking dep in the cycle |\n| `no-rig` | Slingable bead has no rig (prefix not in routes.jsonl) | Add routes.jsonl entry |\n\n**Warnings** (non-fatal — convoy created as `staged:warnings`):\n\n| Category | Trigger |\n|----------|---------|\n| `orphan` | Slingable task with no blocking deps in either direction (epic input only) |\n| `blocked-rig` | Bead targets a parked or docked rig |\n| `cross-rig` | Bead on a different rig than the majority |\n| `capacity` | A wave has more than 5 tasks |\n| `missing-branch` | Sub-epic with children but no integration branch |\n\n### Launch behavior\n\n`gt convoy launch <convoy-id>` transitions a staged convoy to open and dispatches Wave 1:\n\n1. Validate convoy exists and is staged\n2. Transition status to `open`\n3. Re-read tracked beads, rebuild DAG, recompute waves\n5. Dispatch every task in Wave 1 via `gt sling <beadID> <rig>`\n6. Individual sling failures do NOT abort remaining dispatches\n7. Print dispatch results (checkmark/X per task)\n8. Subsequent waves handled automatically by the daemon\n\nIf `gt convoy launch` receives an epic or task list (not a staged convoy), it delegates to `gt convoy stage --launch` to stage-then-launch in one step.\n\n### Staged convoy daemon safety\n\n**Staged convoys are completely inert to the daemon.** Neither feed path processes them:\n\n- **Event-driven feeder:** `isConvoyStaged` check in `CheckConvoysForIssue` skips any convoy with `staged:*` status. Fail-open on read errors (assumes not staged → processes, which is safe since a read error on a non-existent convoy does nothing).\n- **Stranded scan:** `gt convoy stranded` only returns open convoys. Staged convoys never appear.\n\nThis means you can stage a convoy, review the wave plan, and launch when ready — no risk of premature dispatch.\n\n### Re-staging\n\nRunning `gt convoy stage <convoy-id>` on an existing staged convoy re-analyzes and updates:\n- Re-reads tracked beads from the convoy's `tracks` deps\n- Rebuilds DAG, re-detects errors/warnings, recomputes waves\n- Updates status via `bd update` (e.g., `staged:warnings` → `staged:ready` if warnings resolved)\n- Does NOT create a new convoy or re-add track dependencies\n\n## Testing convoy changes\n\n### Running tests\n\n```bash\n# Full convoy suite (all packages)\ngo test ./internal/convoy/... ./internal/daemon/... ./internal/cmd/... -count=1\n\n# By area:\ngo test ./internal/convoy/... -v -count=1                       # feeding logic\ngo test ./internal/daemon/... -v -count=1 -run TestConvoy       # ConvoyManager\ngo test ./internal/daemon/... -v -count=1 -run TestFeedFirstReady\ngo test ./internal/cmd/... -v -count=1 -run TestCreateBatchConvoy  # batch sling\ngo test ./internal/cmd/... -v -count=1 -run TestBatchSling\ngo test ./internal/cmd/... -v -count=1 -run TestResolveRig      # rig resolution\ngo test ./internal/daemon/... -v -count=1 -run Integration      # real beads stores\n\n# Stage-launch:\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyStage     # staging logic\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyLaunch    # launch + Wave 1 dispatch\ngo test ./internal/cmd/... -v -count=1 -run TestDetectCycles    # cycle detection\ngo test ./internal/cmd/... -v -count=1 -run TestComputeWaves    # wave computation\ngo test ./internal/cmd/... -v -count=1 -run TestBuildConvoyDAG  # DAG construction\n```\n\n### Key test invariants\n\n- `feedFirstReady` dispatches exactly 1 issue per call (first success wins)\n- `feedFirstReady` iterates past failures (sling exit 1 -> try next)\n- Parked rigs are skipped in both event poll and feedFirstReady\n- hq store is never skipped even if `isRigParked` returns true for everything\n- High-water marks prevent event reprocessing across poll cycles\n- First poll cycle is warm-up only (seeds marks, no processing)\n- `IsSlingableType(\"epic\") == false`, `IsSlingableType(\"task\") == true`, `IsSlingableType(\"\") == true`\n- `isIssueBlocked` is fail-open (store error -> not blocked)\n- `parent-child` deps are NOT blocking\n- Batch sling creates exactly 1 convoy for N beads (not N convoys)\n- `resolveRigFromBeadIDs` errors on mixed prefixes, unmapped prefixes, town-level prefixes\n- Cycles in blocking deps prevent staged convoy creation (exit non-zero, no side effects)\n- Wave 1 contains ONLY tasks with zero unsatisfied blocking deps among slingable nodes\n- Epics and non-slingable types are NEVER placed in waves\n- Daemon does NOT feed issues from `staged:*` convoys (both feed paths skip)\n- `staged:warnings` convoys can still be launched (warnings are informational)\n- Re-staging a convoy does NOT create duplicates (updates in place)\n- Launch dispatches ONLY Wave 1, not subsequent waves\n- Wave computation is deterministic (same input → same output, alphabetical sort within waves)\n\n### Deeper test engineering\n\nSee `docs/design/convoy/stage-launch/testing.md` for the full stage-launch test plan (105 tests across unit, integration, snapshot, and property tiers).\n\nSee `docs/design/convoy/testing.md` for the general convoy test plan covering failure modes, coverage gaps, harness scorecard, test matrix, and recommended test strategy.\n\n## Common pitfalls\n\n- **`parent-child` is never blocking.** This is a deliberate design choice, not a bug. Consistent with `bd ready`, beads SDK, and molecule step behavior.\n- **Batch sling errors on already-tracked beads.** If any bead is already in a convoy, the entire batch sling fails with conflict details. The user must resolve the conflict before proceeding.\n- **The stranded scan has its own blocked check.** `isReadyIssue` in cmd/convoy.go reads `t.Blocked` from issue details. `isIssueBlocked` in operations.go covers the event-driven path. Don't consolidate them without understanding both paths.\n- **Empty IssueType is slingable.** Beads default to type \"task\" when IssueType is unset. Treating empty as non-slingable would break all legacy beads.\n- **`isIssueBlocked` is fail-open.** Store errors assume not blocked. A transient Dolt error should not permanently stall a convoy -- the next feed cycle retries with fresh state.\n- **Explicit rig in batch sling is deprecated.** `gt sling beads... rig` still works but prints a warning. Prefer `gt sling beads...` with auto-resolution.\n- **Staged convoys are inert.** The daemon ignores them completely. Don't expect auto-feeding until you `gt convoy launch`.\n- **Review `staged:warnings` before launching.** Warnings are informational — fix and re-stage if possible, or launch anyway if they're acceptable.\n- **`gt convoy launch` on a non-staged input delegates to stage.** If you pass an epic or task list to `launch`, it runs `stage --launch` internally. Only an already-staged convoy gets the fast path.\n- **Wave computation is informational.** Waves are computed at stage time for display. Runtime dispatch uses the daemon's per-cycle `isIssueBlocked` checks, which are more dynamic.\n- **You cannot un-stage an open convoy.** Once launched, a convoy cannot return to staged status. The `open → staged:*` transition is rejected.\n\n## Key source files\n\n| File | What it does |\n|------|-------------|\n| `internal/convoy/operations.go` | Core feeding: `CheckConvoysForIssue`, `feedNextReadyIssue`, `IsSlingableType`, `isIssueBlocked` |\n| `internal/daemon/convoy_manager.go` | `ConvoyManager` goroutines: `runEventPoll` (5s), `runStrandedScan` (30s), `feedFirstReady` |\n| `internal/cmd/convoy.go` | All `gt convoy` subcommands + `findStrandedConvoys` type filter |\n| `internal/cmd/sling.go` | Batch detection at ~242, auto-rig-resolution, deprecation warning |\n| `internal/cmd/sling_batch.go` | `runBatchSling`, `resolveRigFromBeadIDs`, `allBeadIDs`, cross-rig guard |\n| `internal/cmd/sling_convoy.go` | `createAutoConvoy`, `createBatchConvoy`, `printConvoyConflict` |\n| `internal/cmd/convoy_stage.go` | `gt convoy stage`: DAG walking, wave computation, error/warning detection, staged convoy creation |\n| `internal/cmd/convoy_launch.go` | `gt convoy launch`: status transition, Wave 1 dispatch via `dispatchWave1` |\n| `internal/daemon/daemon.go` | Daemon startup -- creates `ConvoyManager` at ~237 |\n","internal/hooks/templates/copilot/copilot-instructions.md":"# Gas Town Agent Context\n\nYou are running inside Gas Town, a multi-agent workspace manager.\n\n## Startup Protocol\n\nOn session start or after compaction, run:\n```\ngt prime\n```\nThis loads your full role context, mail, and pending work.\n\n## Key Commands\n\n- `gt prime` - Load role context (run after compaction or new session)\n- `gt mol status` - Check your hooked work\n- `gt mail inbox` - Check for messages\n- `bd ready` - Find available work\n- `gt handoff` - Cycle to fresh session\n\n## Work Protocol\n\n1. Check hook: `gt mol status`\n2. If work is hooked, execute immediately (no waiting for confirmation)\n3. If hook empty, check mail: `gt mail inbox`\n4. Complete work, commit, and push before ending session\n"},"files":{".claude/commands/backup.md":"---\ndescription: Run Dolt database backup — sync production DBs to backup remotes and iCloud\nallowed-tools: Bash(gt dolt status:*), Bash(dolt backup:*), Bash(dolt log:*), Bash(rsync:*), Bash(du:*), Bash(cat:*), Bash(mkdir:*), Bash(timeout:*), Bash(gt escalate:*), Bash(ls:*)\nargument-hint: [--skip-offsite]\n---\n\n# Dolt Backup\n\nSync production Dolt databases to filesystem backups with smart change detection.\nRuns the same cycle as `mol-dog-backup` / the `dolt-backup` plugin.\n\nArguments: $ARGUMENTS\nIf `--skip-offsite` is passed, skip the iCloud rsync step.\n\n## Configuration\n\n```\nDOLT_DATA_DIR=~/gt/.dolt-data\nBACKUP_DIR=~/gt/.dolt-backup\nICLOUD_DIR=~/Library/Mobile Documents/com~apple~CloudDocs/gt-dolt-backup\nPROD_DBS: auto-discovered (databases with <name>-backup remotes)\nBACKUP_TIMEOUT=120s per database\nHANG_THRESHOLD=30s for server ping\nDOLT_PORT=3307\n```\n\n## Execution Steps\n\n### Step 1: Verify Dolt server is responsive\n\n```bash\ngt dolt status\n```\n\nAlso ping directly to detect hangs:\n\n```bash\ntimeout 30 dolt sql --host 127.0.0.1 --port 3307 --user root --password \"\" \\\n  --no-tls -q \"SELECT 1\" --result-format csv\n```\n\nIf the ping hangs (takes > 30s) or fails:\n```bash\ngt escalate \"dolt-backup: Dolt server hung or unreachable\" -s CRITICAL\n```\nSTOP — do not attempt backups against a hung server.\n\n### Step 2: Discover databases with backup remotes\n\nList directories in `~/gt/.dolt-data/` and check each for a `<name>-backup` remote:\n\n```bash\nls ~/gt/.dolt-data/\n```\n\nFor each directory (skip dotfiles):\n```bash\ncd ~/gt/.dolt-data/<name> && dolt backup\n```\n\nIf the output contains `<name>-backup`, include it in the backup list.\nExpected databases: `hq`, `beads`, `gastown`.\n\n### Step 3: Check each DB for changes and sync\n\nFor each database with a backup remote:\n\n**3a. Get current HEAD hash:**\n```bash\ncd ~/gt/.dolt-data/<name> && dolt log -n 1 --oneline | head -1 | cut -d' ' -f1\n```\n\n**3b. Compare against last backed-up hash:**\n```bash\ncat ~/gt/.dolt-backup/<name>/.last-backup-hash 2>/dev/null\n```\n\nIf hashes match and current hash is not \"unknown\", skip (unchanged).\n\n**3c. Sync if changed:**\n```bash\ncd ~/gt/.dolt-data/<name> && timeout 120 dolt backup sync <name>-backup\n```\n\n**3d. Record successful hash:**\n```bash\nmkdir -p ~/gt/.dolt-backup/<name>\necho \"<current_hash>\" > ~/gt/.dolt-backup/<name>/.last-backup-hash\n```\n\n**3e. Get backup size:**\n```bash\ndu -sh ~/gt/.dolt-backup/<name> 2>/dev/null | cut -f1\n```\n\n### Step 4: Offsite sync to iCloud Drive\n\nUnless `--skip-offsite` was specified:\n\n```bash\nmkdir -p ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup\nrsync -a --delete ~/gt/.dolt-backup/ ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup/\n```\n\nIf iCloud is unavailable, log and continue — not fatal.\n\n### Step 5: Report\n\nPrint a summary in this format:\n\n```\n## Backup Report\n\n**Databases synced**: N/M\n**Databases skipped** (unchanged): N\n**Databases failed**: N\n**Offsite sync**: ok | failed | skipped\n\n### Per Database\n- <name>: synced in Ns (<size>) | unchanged (<hash>) | FAILED: <error>\n\n### Failures\n<list or \"None\">\n```\n\nIf any database failed or server was hung:\n```bash\ngt escalate \"dolt-backup FAILED: <summary>\" -s HIGH\n```\n\nIf server was hung, use `-s CRITICAL` instead.\n",".claude/commands/patrol.md":"---\ndescription: Run a patrol cycle for the current agent role (witness, deacon, or refinery)\nallowed-tools: Bash(gt patrol:*), Bash(gt hook:*), Bash(gt mail:*), Bash(gt nudge:*), Bash(gt peek:*), Bash(gt escalate:*), Bash(gt dolt status:*), Bash(bd :*), Bash(gt mol:*)\nargument-hint: [witness|deacon|refinery]\n---\n\n# Patrol\n\nRun one patrol cycle for the specified role. Patrol is a continuous monitoring\nloop — each invocation executes one cycle of the patrol formula.\n\nArguments: $ARGUMENTS\nIf no role specified, detect from current GT_ROLE environment variable.\n\n## Role Detection\n\n```bash\necho $GT_ROLE\n```\n\nMap to patrol type:\n- `*/witness` → witness patrol (`mol-witness-patrol`)\n- `*/deacon` or `*/deacon/*` → deacon patrol (`mol-deacon-patrol`)\n- `*/refinery` → refinery patrol (`mol-refinery-patrol`)\n- Explicit argument overrides detection\n\n## Patrol Entry Point\n\n```bash\ngt patrol new --role <role>\n```\n\nThis creates a hooked wisp with steps from the patrol formula.\nIf a patrol is already running (wisp exists on hook), resume it instead.\n\n## Witness Patrol Steps\n\nThe witness is the per-rig polecat supervisor. Execute in order:\n\n### 1. inbox-check\n```bash\ngt mail inbox\n```\nProcess any pending messages: POLECAT_DONE, MERGED, HELP, escalations.\nRead each with `gt mail read <id>` and take appropriate action.\n\n### 2. process-cleanups\nCheck for cleanup wisps (dirty state from dead polecats):\n```bash\nbd list --status=open --label=cleanup --json\n```\nProcess each: verify git state, clean worktrees, close cleanup wisps.\n\n### 3. check-refinery\n```bash\ngt peek gastown/refinery\n```\nVerify refinery is alive and processing the merge queue.\nIf stuck, nudge: `gt nudge gastown/refinery \"Health check — are you processing?\"`\n\n### 4. survey-workers\nCheck all active polecats in the rig:\n```bash\ngt peek gastown/polecats\n```\nFor each active polecat:\n- Check if session is alive (has recent activity)\n- Check if work is progressing (commits, bead updates)\n- Detect zombies: session dead but agent_state says working\n- Detect stale spawns: spawning > 10 minutes\n\nNudge idle polecats:\n```bash\ngt nudge gastown/polecats/<name> \"Progress check — what's your status?\"\n```\n\n### 5. check-timer-gates\n```bash\nbd list --label=gate:timer --status=open --json\n```\nEvaluate any timer-based gates that may have elapsed.\n\n### 6. check-swarm\nCheck for convoy/swarm completion across coordinated work:\n```bash\nbd list --label=convoy --status=open --json\n```\n\n### 7. patrol-cleanup\nClose completed patrol wisps, update metrics.\n\n### 8. context-check\nCheck remaining context budget. If approaching limit:\n```bash\ngt handoff -s \"Patrol cycling\" -m \"Patrol cycle N complete, cycling for fresh context\"\n```\n\n### 9. loop-or-exit\nReport cycle results and spawn next cycle:\n```bash\ngt patrol report --summary \"<cycle summary>\" --steps \"inbox:OK,cleanup:OK,...\"\n```\n\n## Deacon Patrol Steps\n\nThe deacon is the town-wide daemon monitor. Key steps:\n\n1. **inbox-check** — Process callbacks from witnesses, refineries, polecats\n2. **trigger-pending-spawns** — Launch queued polecat spawns\n3. **gate-evaluation** — Check async gates (timer, dependency)\n4. **dispatch-gated-molecules** — Release molecules whose gates cleared\n5. **check-convoy-completion** — Track multi-rig coordinated work\n6. **health-scan** — Check Dolt health (`gt dolt status`), agent health\n7. **zombie-scan** — Find dead sessions, orphaned wisps\n8. **plugin-run** — Execute enabled plugins (backup, reaper, etc.)\n9. **dog-pool-maintenance** — Manage utility worker pool\n10. **orphan-check** — Find orphaned test databases (`gt dolt cleanup`)\n11. **session-gc** — Clean up dead session artifacts\n12. **patrol-cleanup** — Close completed wisps, update metrics\n13. **context-check** — Check context budget, handoff if needed\n14. **loop-or-exit** — Report and spawn next cycle\n\n## Refinery Patrol Steps\n\nThe refinery processes the merge queue sequentially:\n\n1. **inbox-check** — Look for MERGE_READY messages from witness\n2. **queue-scan** — List pending MRs in merge queue\n3. **process-branch** — Fetch and rebase next MR branch onto target\n4. **run-tests** — Execute configured gate suite on rebased branch\n5. **handle-failures** — On test failure: bisect, isolate culprit, notify\n6. **merge-push** — Fast-forward push to main: `git push origin temp:main`\n7. **notify** — Send MERGED mail to witness immediately after push\n8. **cleanup** — Close MR bead, delete remote branch, archive mail\n9. **context-check** — Check context budget\n10. **loop-or-exit** — Report and spawn next cycle\n\n## Cycle Completion\n\nEach cycle ends with:\n```bash\ngt patrol report --summary \"<what happened>\" --steps \"<step1:OK,step2:SKIP,...>\"\n```\n\nThis closes the current patrol wisp and spawns the next cycle automatically.\n",".claude/commands/reaper.md":"---\ndescription: Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases\nallowed-tools: Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*)\nargument-hint: [--dry-run]\n---\n\n# Wisp Reaper\n\nReap stale wisps and close stale issues across all production Dolt databases.\nRuns the same cycle as `mol-dog-reaper` but directly, without Dog dispatch.\n\nArguments: $ARGUMENTS\nIf `--dry-run` is passed, report counts without making changes.\n\n## Configuration Defaults\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| max_age | 24h | Wisps older than this are reaped (closed) |\n| purge_age | 72h | Closed wisps older than this are purged (deleted) |\n| stale_issue_age | 168h | Issues stale longer than this are auto-closed |\n| mail_delete_age | 72h | Closed mail older than this is purged |\n| alert_threshold | 3000 | Open wisp count that triggers escalation |\n| dolt_port | 3307 | Dolt server port |\n\n## Execution Steps\n\n### Step 1: Verify Dolt server health\n\n```bash\ngt dolt status\n```\n\nIf the server is unhealthy or unreachable, STOP and escalate:\n```bash\ngt escalate \"Reaper blocked: Dolt server unhealthy\" -s HIGH\n```\n\n### Step 2: Discover databases\n\n```bash\ngt reaper databases --json\n```\n\nThis lists all production databases on the Dolt server.\nExpected databases: `hq`, `beads`, `gastown` (and any rig-specific DBs).\n\n### Step 3: Scan each database for candidates\n\nFor each database returned in Step 2:\n\n```bash\ngt reaper scan --db=<name> --port=3307 \\\n  --max-age=24h --purge-age=72h \\\n  --mail-age=72h --stale-age=168h \\\n  --json\n```\n\nInspect the JSON output:\n- `reap_candidates`: wisps eligible for closing\n- `purge_candidates`: closed wisps eligible for deletion\n- `open_wisps`: total open wisp count\n- `anomalies`: array of detected problems\n\nIf `open_wisps` exceeds 3000 across all databases, note for escalation.\nIf no candidates found across all databases, report \"nothing to reap\" and stop.\n\n### Step 4: Reap stale wisps\n\nFor each database with reap candidates:\n\n```bash\ngt reaper reap --db=<name> --port=3307 --max-age=24h [--dry-run] --json\n```\n\n**IMPORTANT**: Scan/reap count mismatch is NORMAL (witness closes wisps concurrently).\nDo NOT escalate scan > reap mismatches. Only escalate actual errors.\n\n### Step 5: Purge old closed wisps and mail\n\nFor each database with purge candidates:\n\n```bash\ngt reaper purge --db=<name> --port=3307 \\\n  --purge-age=72h --mail-age=72h [--dry-run] --json\n```\n\nWatch for `dolt_commit_failed` anomalies — purged data may not persist.\n\n### Step 6: Auto-close stale issues\n\nFor each database with stale candidates:\n\n```bash\ngt reaper auto-close --db=<name> --port=3307 \\\n  --stale-age=168h [--dry-run] --json\n```\n\nAuto-close NEVER touches: P0/P1 issues, epics, or issues with active dependencies.\n\n### Step 7: Report\n\nPrint a summary in this format:\n\n```\n## Reaper Report\n\n**Databases scanned**: N\n**Wisps reaped**: N (stale open wisps closed)\n**Wisps purged**: N (old closed wisps deleted)\n**Mail purged**: N (old closed mail deleted)\n**Issues auto-closed**: N (stale issues past 168h)\n**Open wisps remaining**: N\n**Anomalies**: <list or \"none\">\n```\n\nIf anomalies were found:\n```bash\ngt escalate \"Reaper anomalies detected\" -s MEDIUM -m \"<anomaly details>\"\n```\n",".claude/skills/crew-commit/SKILL.md":"---\nname: crew-commit\ndescription: >\n  Canonical commit workflow for Gas Town crew members: pre-flight checks,\n  branch creation, gt commit with agent identity, push, and PR creation.\n  Use when ready to commit and submit work for review.\nallowed-tools: \"Bash(git *), Bash(gt *), Bash(gh *)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# Crew Commit — Canonical Git Workflow\n\nThis skill guides crew members through the standard Gas Town commit workflow:\npre-flight → branch → stage → commit → push → PR.\n\n> **⚠️ NEVER commit directly to `main`.** All crew work goes through branches\n> and pull requests. The Refinery handles merges to main.\n\n## Usage\n\n```\n/crew-commit\n```\n\nRun this when you have changes ready to commit. The skill walks you through\neach step in order.\n\n---\n\n## Step 1: Pre-flight Checks\n\nBefore touching anything, sync with origin and verify your state.\n\n```bash\n# Fetch latest from origin\ngit fetch origin\n\n# Check current branch and status\ngit status\ngit branch --show-current\n\n# If you're on main, STOP — create a branch first (Step 2)\n```\n\n**If you're behind origin/main**, rebase now:\n\n```bash\ngit rebase origin/main\n```\n\nIf there are conflicts, resolve them carefully before proceeding.\nIf stuck on a rebase conflict, stop and get help rather than force-pushing.\n\n---\n\n## Step 2: Create a Feature Branch\n\n**If you're already on a feature branch**, skip to Step 3.\n\nBranch naming convention: `<type>/<short-description>`\n\nTypes:\n- `feat/` — new feature\n- `fix/` — bug fix\n- `refactor/` — code restructuring\n- `docs/` — documentation only\n- `chore/` — maintenance, deps, config\n- `test/` — tests only\n\n```bash\n# Create and switch to feature branch\ngit checkout -b feat/my-feature-description\n\n# Or use the crew/<name> prefix for crew-specific branches\ngit checkout -b crew/<your-name>/description\n```\n\n---\n\n## Step 3: Submodule Warning\n\n**Check for submodules before staging.** Accidentally committing a submodule\npointer change causes cascading failures for other crew members.\n\n```bash\n# Check if repo has submodules\ncat .gitmodules 2>/dev/null || echo \"(no submodules)\"\n\n# Check for dirty submodule state\ngit submodule status 2>/dev/null\n```\n\n**Common submodule paths to watch:** `shared/`, `config/`, `vendor/`\n\nIf you see changes in submodule directories:\n- Do NOT `git add shared/` or `git add config/` unless you intentionally\n  bumped the submodule pointer\n- Submodule pointer changes should be explicit and deliberate\n- When in doubt, ask before including submodule changes\n\n---\n\n## Step 4: Stage Your Changes\n\nPrefer staging specific files over `git add .` or `git add -A`.\n\n```bash\n# Review what changed\ngit diff\ngit status\n\n# Stage specific files (preferred)\ngit add src/myfile.go tests/myfile_test.go\n\n# If you need to stage all intentional changes and have verified no secrets:\ngit add -p    # Interactive staging — review each hunk\n```\n\n**Before staging, verify:**\n- [ ] No `.env` files, API keys, or credentials\n- [ ] No debug prints or temporary test code\n- [ ] No unrelated changes mixed in\n- [ ] Submodule directories NOT accidentally staged (unless intentional)\n\n---\n\n## Step 5: Commit with gt commit\n\nUse `gt commit` instead of `git commit`. It automatically sets the correct\nagent identity (name + email) based on your `GT_ROLE`.\n\n```bash\ngt commit -m \"$(cat <<'EOF'\n<type>: <concise description of what and why>\n\n<optional body: context, motivation, or notable details>\nEOF\n)\"\n```\n\n**Commit message format:**\n- First line: `<type>: <subject>` (50 chars or less)\n- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`\n- Use imperative mood: \"add feature\" not \"added feature\"\n- Body is optional but valuable for non-obvious changes\n\n**Good examples:**\n```\nfeat: add retry logic to webhook delivery\nfix: prevent nil pointer when session token expires\ndocs: clarify crew commit workflow in CONTRIBUTING.md\n```\n\n---\n\n## Step 6: Push Branch to Origin\n\n```bash\ngit push origin <your-branch-name>\n\n# Or, if branch doesn't exist on remote yet:\ngit push -u origin <your-branch-name>\n```\n\n---\n\n## Step 7: Create Pull Request\n\n```bash\ngh pr create --title \"<type>: <concise description>\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- <what changed and why>\n\n## Test plan\n\n- [ ] <how to verify this works>\n\n## Notes\n\n<any context reviewers need>\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\nEOF\n)\"\n```\n\nAfter creating the PR, note the PR number from the output.\n\n---\n\n## Step 8: Notify (Optional)\n\nIf your work affects others or is high priority:\n\n```bash\nnotify \"PR ready: <brief description> — #<PR number>\"\n```\n\n---\n\n## Completion Checklist\n\n- [ ] Synced with origin/main (git fetch + rebase)\n- [ ] On a feature branch (NOT main)\n- [ ] Submodules NOT accidentally staged\n- [ ] Specific files staged (no secrets, no debug code)\n- [ ] Used `gt commit` (not `git commit`)\n- [ ] Branch pushed to origin\n- [ ] PR created via `gh pr create`\n\n---\n\n## Anti-Patterns\n\n| ❌ Don't | ✅ Do instead |\n|----------|--------------|\n| `git push origin main` | Push feature branch, create PR |\n| `git commit` directly | `gt commit` (sets agent identity) |\n| `git add .` blindly | Stage specific files, verify with `git status` |\n| Include `shared/` or `config/` without intent | Check `git submodule status` first |\n| Force-push without understanding why | Resolve the root cause |\n| Commit secrets or .env files | Always check `git diff` before staging |\n\n---\n\n## If You Get Stuck\n\n- **Rebase conflicts**: resolve carefully, then `git rebase --continue`\n- **Pushed wrong branch**: ask before force-pushing; usually `git push origin <branch>` is fine\n- **Need to undo last commit**: `git reset HEAD~1` (keeps changes staged)\n- **Committed to main by mistake**: stop immediately, ask for help\n",".claude/skills/ghi-list/SKILL.md":"---\nname: ghi-list\ndescription: >\n  List GitHub issues in a formatted ASCII table. Supports filters like --state,\n  --assignee, --label. Use for issue triage and tracking workflows.\nallowed-tools: \"Bash(gh issue list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# GHI List - Formatted GitHub Issues Table\n\nDisplay GitHub issues in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/ghi-list [options]\n```\n\n## Options (passed to gh issue list)\n\n- `--state open|closed|all` - Filter by state (default: open)\n- `--assignee <user>` - Filter by assignee\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--author <user>` - Filter by author\n- `--milestone <name>` - Filter by milestone\n\n## Execution Steps\n\n1. Run `gh issue list` with any provided options plus `--json number,assignees,labels,title,state`\n2. Format output as an ASCII table using box-drawing characters\n3. Truncate titles to fit reasonable terminal width (~45 chars)\n4. Show first assignee only, or \"-\" if none\n5. Show first 2-3 labels abbreviated, or \"-\" if none\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌───────┬────────────┬─────────────────┬───────────────────────────────────────────────┬────────┐\n│ Issue │ Assignee   │ Labels          │ Title                                         │ State  │\n├───────┼────────────┼─────────────────┼───────────────────────────────────────────────┼────────┤\n│   372 │ max        │ enhancement     │ Create /pr-list and /ghi-list skills          │ OPEN   │\n│   371 │ -          │ bug, priority   │ Fix null pointer in auth module               │ OPEN   │\n│   370 │ joe        │ -               │ Update documentation for new API              │ CLOSED │\n└───────┴────────────┴─────────────────┴───────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align issue numbers\n- Left-align text columns\n- Pad columns consistently\n- For assignees: show login of first assignee, \"-\" if none\n- For labels: show comma-separated names (truncate if >17 chars)\n- Show count summary below table: \"**N issues** (M open, K closed)\"\n\n## Example Commands\n\n```bash\n# Default - open issues\ngh issue list --json number,assignees,labels,title,state\n\n# With filters\ngh issue list --state all --label bug --json number,assignees,labels,title,state\n```\n",".claude/skills/pr-list/SKILL.md":"---\nname: pr-list\ndescription: >\n  List GitHub PRs in a formatted ASCII table. Supports filters like --state,\n  --author, --label. Use for PR review workflows and sheriff duties.\nallowed-tools: \"Bash(gh pr list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR List - Formatted Pull Request Table\n\nDisplay GitHub pull requests in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/pr-list [options]\n```\n\n## Options (passed to gh pr list)\n\n- `--state open|closed|merged|all` - Filter by state (default: open)\n- `--author <user>` - Filter by author\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--assignee <user>` - Filter by assignee\n- `--draft` - Show only drafts\n- `--all-reviews` - Include PRs with CHANGES_REQUESTED (excluded by default)\n\n## Execution Steps\n\n1. Run `gh pr list` with any provided options plus `--json number,author,title,state,isDraft,reviewDecision`\n2. **Filter out PRs with reviewDecision=\"CHANGES_REQUESTED\"** (unless `--all-reviews` specified)\n3. Format output as an ASCII table using box-drawing characters\n4. Truncate titles to fit reasonable terminal width (~50 chars)\n5. Truncate author names if needed (~18 chars)\n6. Show state as OPEN/CLOSED/MERGED/DRAFT, append \"(changes requested)\" if filtered with --all-reviews\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌─────┬────────────────────┬───────────────────────────────────────────────────┬────────┐\n│  PR │ Author             │ Title                                             │ State  │\n├─────┼────────────────────┼───────────────────────────────────────────────────┼────────┤\n│ 123 │ username           │ feat: add new feature for something               │ OPEN   │\n│ 122 │ another-user       │ fix: resolve bug in component                     │ DRAFT  │\n└─────┴────────────────────┴───────────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align PR numbers\n- Left-align text columns\n- Pad columns consistently\n- Show count summary below table: \"**N open PRs** (M drafts)\"\n\n## Example Commands\n\n```bash\n# Default - open PRs (excludes CHANGES_REQUESTED)\ngh pr list --json number,author,title,state,isDraft,reviewDecision\n\n# With filters\ngh pr list --state all --author boshu2 --json number,author,title,state,isDraft,reviewDecision\n```\n",".claude/skills/pr-sheriff/skill.md":"---\nname: pr-sheriff\ndescription: >\n  PR Sheriff workflow: triage PRs into easy-wins and crew assignments.\n  Prints recommendations inline - does NOT post to GitHub.\nallowed-tools: \"Bash(gh pr *), Bash(git *), Bash(gt *), Bash(bd *), Bash(cat *)\"\nversion: \"2.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR Sheriff - Triage and Review Workflow\n\nThis skill delegates to the `mol-pr-sheriff-patrol` formula, which lives at\n`$GT_ROOT/.beads/formulas/mol-pr-sheriff-patrol.formula.toml` and is shared\nacross all Gas Town rigs (gastown, beads, etc.).\n\n## Repo Scope\n\nThis rig (gastown/crew/max) is responsible for **steveyegge/gastown only**.\nThe beads repo (steveyegge/beads) is handled by beads/crew/emma.\nDo NOT discover or triage PRs from repos outside your scope.\n\nWhen loading the shared config, filter the repo list to only `steveyegge/gastown`.\n\n## Usage\n\n```\n/pr-sheriff [repo]\n```\n\n- `repo` - Optional. If provided, overrides the default scope.\n  If omitted, scan only `steveyegge/gastown` (this rig's scope).\n\n## How to Execute\n\n**1. Load the config:**\n```bash\ncat $GT_ROOT/.beads/pr-sheriff-config.json\n```\n\nThis contains crew mappings per repo and contributor policies\n(trust tiers, firewalled contributors, bot auto-merge rules).\n**Only scan repos within your scope** (see Repo Scope above).\n\n**2. Follow the formula steps in order:**\n```bash\ngt formula show mol-pr-sheriff-patrol\n```\n\nThe formula defines a 7-step workflow:\n\n| Step | What it does |\n|------|-------------|\n| load-config | Load pr-sheriff-config.json, establish repo list |\n| discover-prs | Find open PRs needing review across all repos |\n| triage-batch | Categorize all PRs in one pass (preserves cross-PR context) |\n| merge-easy-wins | Merge approved easy-wins via `gh pr merge` |\n| dispatch-crew-reviews | Nudge crew for NEEDS-CREW PRs |\n| dispatch-deep-reviews | Nudge crew for NEEDS-HUMAN PRs (full evaluation framework) |\n| collect-results | Gather crew review nudge-backs |\n| interactive-review | Walk through remaining NEEDS-HUMAN PRs with overseer |\n| summarize | Print patrol summary |\n\n**3. For each step, read the full description:**\n```bash\ngt formula show mol-pr-sheriff-patrol  # Shows all steps with descriptions\n```\n\n## Key References\n\n- **Patrol formula:** `mol-pr-sheriff-patrol` (town-level)\n- **Crew review formula:** `mol-pr-crew-review` (dispatched to crew)\n- **Deep review formula:** `mol-pr-deep-review` (dispatched for NEEDS-HUMAN)\n- **Config:** `$GT_ROOT/.beads/pr-sheriff-config.json`\n\n## Contributor Policy Tiers\n\nLoaded from config. Current tiers:\n\n| Tier | Handling |\n|------|----------|\n| bot-trusted | Auto-merge if CI passes (e.g., dependabot) |\n| community | Normal triage — easy-win / crew / deep review |\n| firewalled | Always NEEDS-HUMAN, never auto-merge, deep review required |\n\n## Category Decision Tree\n\n```\nDraft? → SKIP\nContributor firewalled? → NEEDS-HUMAN (deep review)\nDependabot patch bump + CI green? → EASY-WIN\n<50 lines, obvious bug/doc/test fix? → EASY-WIN\nSecurity/architecture/API change? → NEEDS-HUMAN\nMulti-concern PR? → NEEDS-HUMAN\n100+ lines new feature? → NEEDS-CREW or NEEDS-HUMAN\nEverything else → NEEDS-CREW\n```\n\n## Deep Review Evaluation Framework (NEEDS-HUMAN)\n\nThe deep review formula (mol-pr-deep-review) applies six lenses:\n\n1. **Plugin/integration fit** — core vs plugin/formula/integration?\n2. **Tech-debt weight** — complexity justified by user breadth?\n3. **Contributor track record** — first-time, repeat, or firewalled?\n4. **ZFC compliance** — structural checks, not string heuristics?\n5. **Problem validity + solution fit** — real problem, right solution?\n6. **Splitability** — can good parts be cherry-picked from bad?\n\nFinal verdicts: MERGE | CHERRY-PICK | REWORK | REIMPLEMENT | CLOSE\n\n## Output Format\n\nFor each PR, print a recommendation block:\n\n```\n### PR #<num>: <title>\nAuthor: <login> | +<additions>/-<deletions> | <changedFiles> files\n\n**Category**: EASY-WIN | NEEDS-CREW | NEEDS-HUMAN | SKIP\n\n**Analysis**:\n<1-3 sentences explaining the change and why it fits this category>\n\n**Recommendation**:\n<specific action>\n```\n\n## Summary Output\n\n```\n## PR Sheriff Patrol Summary — <date>\n\n**Easy-wins merged**: N\n**Crew-reviewed and merged**: N\n**Sent back for rework**: N\n**Closed**: N\n**Still pending**: N\n```\n\n## Dispatching Work: Use Ephemeral Beads\n\nWhen creating beads to track fix-merge work for polecats or crew, **use\nephemeral beads (wisps)** rather than persistent beads. PR review/fix-merge\ntasks are orchestration scaffolding — they exist to give a polecat something\nto hook and track, not to create a permanent record.\n\nEphemeral beads are the right trade-off: they give polecats and crew trackable\nwork items without polluting Dolt's permanent ledger with one-off orchestration\nnoise. If/when beads are exported to permanent ledgers, review-task wisps won't\nclutter the history.\n\n```bash\n# Ephemeral bead for fix-merge dispatch\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review \\\n  --wisp-type patrol\n\n# vs persistent (avoid for orchestration work)\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review\n```\n\nThe `--wisp-type patrol` flag marks it as ephemeral orchestration work that\nthe reaper will eventually clean up. The polecat/crew member can still hook it,\nwork it, and close it normally.\n\n## CRITICAL Rules\n\n- All output is printed inline. Do NOT post comments to GitHub.\n- The overseer decides what gets posted externally.\n- Contributor-friendly: help contributors get to the finish line.\n- Use `Co-authored-by` trailer when fixing up contributor work.\n",".cursor/skills/gas-town-cursor/SKILL.md":"---\nname: gas-town-cursor\ndescription: >\n  Develop and operate Gas Town with the Cursor agent preset (cursor-agent CLI):\n  gt flags, hooks at .cursor/hooks.json, session resume, and how this repo differs from README marketing copy.\n---\n\n# Gas Town + Cursor Agent CLI\n\nUse this skill when working **in this repository** with the **`cursor`** agent preset (CLI binary **`cursor-agent`**, sometimes symlinked as **`agent`**).\n\n## Concepts\n\n| Name | Meaning |\n|------|---------|\n| **Preset `cursor`** | Gas Town agent id (`GT_AGENT=cursor`). Config lives in `internal/config/agents.go` (`AgentCursor`). |\n| **Binary `cursor-agent`** | The Cursor Agent CLI process name for pane/detection; install docs may also symlink `agent` → same binary. |\n| **Hooks** | Cursor lifecycle hooks are configured at **`.cursor/hooks.json`** (see preset `HooksSettingsFile`). |\n\n## Essential commands\n\n- Build / run `gt` from repo root: `make build` or `go run ./cmd/gt …`.\n- Point a session at the Cursor preset: spawn or config so the runtime uses **`--agent cursor`** (or set **`GT_AGENT=cursor`** where applicable).\n- After changing hooks or settings: **`gt up --restore`** (or role-specific restart) so agents reload config.\n\n## Resume semantics\n\nThe Cursor preset uses **`--resume <chatId>`** style resume (`ResumeStyle: flag`). Session identity is not carried in a dedicated env var in the same way as Claude’s `CLAUDE_SESSION_ID`; follow the preset fields in `internal/config/agents.go` (`ResumeFlag`, `ResumeStyle`).\n\n## Read more\n\n- Beads / plan handoff: [`docs/cursor-runtime-beads-tasks.md`](../../../docs/cursor-runtime-beads-tasks.md)\n- Agent instructions for automation: [`AGENTS.md`](../../../AGENTS.md) and [`CLAUDE.md`](../../../CLAUDE.md) (project-wide, not Cursor-only)\n\n## Boundary\n\nProject **README** is user-facing product overview; **`.cursor/README.md`** is Cursor-specific onboarding for this repo. Prefer linking to those files instead of duplicating long install steps inside skills.\n","AGENTS.md":"# Agent Instructions\n\nSee **CLAUDE.md** for complete agent context and instructions.\n\nThis file exists for compatibility with tools that look for AGENTS.md.\n\n> **Recovery**: Run `gt prime` after compaction, clear, or new session\n\nFull context is injected by `gt prime` at session start.\n\n<!-- beads-agent-instructions-v2 -->\n\n---\n\n## Beads Workflow Integration\n\nThis project uses [beads](https://github.com/steveyegge/beads) for issue tracking. Issues live in `.beads/` and are tracked in git.\n\nTwo CLIs: **bd** (issue CRUD) and **bv** (graph-aware triage, read-only).\n\n### bd: Issue Management\n\n```bash\nbd ready              # Unblocked issues ready to work\nbd list --status=open # All open issues\nbd show <id>          # Full details with dependencies\nbd create --title=\"...\" --type=task --priority=2\nbd update <id> --status=in_progress\nbd close <id>         # Mark complete\nbd close <id1> <id2>  # Close multiple\nbd dep add <a> <b>    # a depends on b\nbd sync               # Sync with git\n```\n\n### bv: Graph Analysis (read-only)\n\n**NEVER run bare `bv`** — it launches interactive TUI. Always use `--robot-*` flags:\n\n```bash\nbv --robot-triage     # Ranked picks, quick wins, blockers, health\nbv --robot-next       # Single top pick + claim command\nbv --robot-plan       # Parallel execution tracks\nbv --robot-alerts     # Stale issues, cascades, mismatches\nbv --robot-insights   # Full graph metrics: PageRank, betweenness, cycles\n```\n\n### Workflow\n\n1. **Start**: `bd ready` (or `bv --robot-triage` for graph analysis)\n2. **Claim**: `bd update <id> --status=in_progress`\n3. **Work**: Implement the task\n4. **Complete**: `bd close <id>`\n5. **Sync**: `bd sync` at session end\n\n### Session Close Protocol\n\n```bash\ngit status            # Check what changed\ngit add <files>       # Stage code changes\nbd sync               # Commit beads changes\ngit commit -m \"...\"   # Commit code\nbd sync               # Commit any new beads changes\ngit push              # Push to remote\n```\n\n### Key Concepts\n\n- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (numbers only)\n- **Types**: task, bug, feature, epic, question, docs\n- **Dependencies**: `bd ready` shows only unblocked work\n\n<!-- end-beads-agent-instructions -->\n\n<!-- gastown-agent-instructions-v1 -->\n\n---\n\n## Gas Town Multi-Agent Communication\n\nThis workspace is part of a **Gas Town** multi-agent environment. You communicate\nwith other agents using `gt` commands — never by printing text or using raw tmux.\n\n### Nudging Agents (Immediate Delivery)\n\n`gt nudge` sends a message directly to another agent's active session:\n\n```bash\ngt nudge mayor \"Status update: PR review complete\"\ngt nudge laneassist/crew/dom \"Check your mail — PR ready for review\"\ngt nudge witness \"Polecat health check needed\"\ngt nudge refinery \"Merge queue has items\"\n```\n\n**Target formats:**\n- Role shortcuts: `mayor`, `deacon`, `witness`, `refinery`\n- Full path: `<rig>/crew/<name>`, `<rig>/polecats/<name>`\n\n**Important:** `gt nudge` is the ONLY way to send text to another agent's session.\nNever print \"Hey @name\" — the other agent cannot see your terminal output.\n\n### Sending Mail (Persistent Messages)\n\n`gt mail` sends messages that persist across session restarts:\n\n```bash\n# Reading\ngt mail inbox                    # List messages\ngt mail read <id>                # Read a specific message\n\n# Sending (use --stdin for multi-line content)\ngt mail send mayor/ -s \"Subject\" -m \"Short message\"\ngt mail send laneassist/crew/dom -s \"PR Review\" --stdin <<'BODY'\nMulti-line message content here.\nDetails about the PR and what to look for.\nBODY\ngt mail send --human -s \"Subject\" -m \"Message to overseer\"\n```\n\n### When to Use Which\n\n| Want to... | Command | Why |\n|------------|---------|-----|\n| Wake a sleeping agent | `gt nudge <target> \"msg\"` | Immediate delivery |\n| Send detailed task/info | `gt mail send <target> -s \"...\" --stdin` | Persists across restarts |\n| Both: send + wake | `gt mail send` then `gt nudge` | Mail carries payload, nudge wakes |\n\n### Context Recovery\n\nAfter compaction or new session, run `gt prime` to reload your full role context,\nidentity, and any pending work.\n\n```bash\ngt prime              # Full context reload\ngt hook               # Check for assigned work\ngt mail inbox         # Check for messages\n```\n\n<!-- end-gastown-agent-instructions -->\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `gt prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `gt prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n   ```bash\n   git pull --rebase\n   bd dolt push\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n","docs/skills/convoy/SKILL.md":"---\nname: convoy\ndescription: The definitive guide for working with gastown's convoy system -- batch work tracking, event-driven feeding, stage-launch workflow, and dispatch safety guards. Use when writing convoy code, debugging convoy behavior, adding convoy features, testing convoy changes, or answering questions about how convoys work. Triggers on convoy, convoy manager, convoy feeding, dispatch, stranded convoy, feedFirstReady, feedNextReadyIssue, IsSlingableType, isIssueBlocked, CheckConvoysForIssue, gt convoy, gt sling, stage, launch, staged, wave.\n---\n\n# Gastown Convoy System\n\nThe convoy system tracks batches of work across rigs. A convoy is a bead that `tracks` other beads via dependencies. The daemon monitors close events and feeds the next ready issue when one completes.\n\n## Architecture\n\n```\n+================================ CREATION =================================+\n|                                                                            |\n|   gt sling <beads>      gt convoy create ...     gt convoy stage <epic>    |\n|        |  (auto-convoy)       |  (explicit)            |  (validated)     |\n|        v                      v                        v                  |\n|   +-----------+          +-----------+         +----------------+         |\n|   |  status:  |          |  status:  |         |    status:     |         |\n|   |   open    |          |   open    |         | staged:ready   |         |\n|   +-----------+          +-----------+         | staged:warnings|         |\n|                                                +----------------+         |\n|                                                        |                  |\n|                                              gt convoy launch             |\n|                                                        |                  |\n|                                                        v                  |\n|                                                +----------------+         |\n|                                                |    status:     |         |\n|                                                |     open       |         |\n|                                                | (Wave 1 slung) |         |\n|                                                +----------------+         |\n|                                                                            |\n|   All paths produce: CONVOY (hq-cv-*)                                      |\n|                      tracks: issue1, issue2, ...                           |\n+============================================================================+\n              |                              |\n              v                              v\n+= EVENT-DRIVEN FEEDER (5s) =+   +=== STRANDED SCAN (30s) ===+\n|                              |   |                            |\n|   GetAllEventsSince (SDK)    |   |   findStranded             |\n|     |                        |   |     |                      |\n|     v                        |   |     v                      |\n|   close event detected       |   |   convoy has ready issues  |\n|     |                        |   |   but no active workers    |\n|     v                        |   |     |                      |\n|   CheckConvoysForIssue       |   |     v                      |\n|     |                        |   |   feedFirstReady           |\n|     v                        |   |   (iterates all ready)     |\n|   feedNextReadyIssue         |   |     |                      |\n|   (iterates all ready)       |   |     v                      |\n|     |                        |   |   gt sling <next-bead>     |\n|     v                        |   |   or closeEmptyConvoy     |\n|   gt sling <next-bead>       |   |                            |\n|                              |   +============================+\n+==============================+\n```\n\nThree creation paths (sling, create, stage), two feed paths, same safety guards:\n- **Event-driven** (`operations.go`): Polls beads stores every ~5s for close events. Calls `feedNextReadyIssue` which checks `IsSlingableType` + `isIssueBlocked` before dispatch. **Skips staged convoys** (`isConvoyStaged` check).\n- **Stranded scan** (`convoy_manager.go`): Runs every 30s. `feedFirstReady` iterates all ready issues. The ready list is pre-filtered by `IsSlingableType` in `findStrandedConvoys` (cmd/convoy.go). **Only sees open convoys** — staged convoys never appear.\n\n## Safety guards (the three rules)\n\nThese prevent the event-driven feeder from dispatching work it shouldn't:\n\n### 1. Type filtering (`IsSlingableType`)\n\nOnly leaf work items dispatch. Defined in `operations.go`:\n\n```go\nvar slingableTypes = map[string]bool{\n    \"task\": true, \"bug\": true, \"feature\": true, \"chore\": true,\n    \"\": true, // empty defaults to task\n}\n```\n\nEpics, sub-epics, convoys, decisions -- all skip. Applied in both `feedNextReadyIssue` (event path) and `findStrandedConvoys` (stranded path).\n\n### 2. Blocks dep checking (`isIssueBlocked`)\n\nIssues with unclosed `blocks`, `conditional-blocks`, or `waits-for` dependencies skip. `parent-child` is **not** blocking -- a child task dispatches even if its parent epic is open. This is consistent with `bd ready` and molecule step behavior.\n\nFail-open on store errors (assumes not blocked) to avoid stalling convoys on transient Dolt issues.\n\n### 3. Dispatch failure iteration\n\nBoth feed paths iterate past failures instead of giving up:\n- `feedNextReadyIssue`: `continue` on dispatch failure, try next ready issue\n- `feedFirstReady`: `for range ReadyIssues` with `continue` on skip/failure, `return` on first success\n\n## CLI commands\n\n### Stage and launch (validated creation)\n\n```bash\ngt convoy stage <epic-id>            # analyze deps, build DAG, compute waves, create staged convoy\ngt convoy stage gt-task1 gt-task2    # stage from explicit task list\ngt convoy stage hq-cv-abc            # re-stage existing staged convoy\ngt convoy stage <epic-id> --json     # machine-readable output\ngt convoy stage <epic-id> --launch   # stage + immediately launch if no errors\ngt convoy launch hq-cv-abc           # transition staged → open, dispatch Wave 1\ngt convoy launch <epic-id>           # stage + launch in one step (delegates to stage --launch)\n```\n\n### Create and manage\n\n```bash\ngt convoy create \"Auth overhaul\" gt-task1 gt-task2 gt-task3\ngt convoy add hq-cv-abc gt-task4\n```\n\n### Check and monitor\n\n```bash\ngt convoy check hq-cv-abc       # auto-closes if all tracked issues done\ngt convoy check                  # check all open convoys\ngt convoy status hq-cv-abc       # single convoy detail\ngt convoy list                   # all convoys\ngt convoy list --all             # include closed\n```\n\n### Find stranded work\n\n```bash\ngt convoy stranded               # ready work with no active workers\ngt convoy stranded --json        # machine-readable\n```\n\n### Close and land\n\n```bash\ngt convoy close hq-cv-abc --reason \"done\"\ngt convoy land hq-cv-abc         # cleanup worktrees + close\n```\n\n### Interactive TUI\n\n```bash\ngt convoy -i                     # opens interactive convoy browser\ngt convoy --interactive          # long form\n```\n\n## Batch sling behavior\n\n`gt sling <bead1> <bead2> <bead3>` creates **one convoy** tracking all beads. The rig is auto-resolved from the beads' prefixes (via `routes.jsonl`). The convoy title is `\"Batch: N beads to <rig>\"`. Each bead gets its own polecat, but they share a single convoy for tracking.\n\nThe convoy ID and merge strategy are stored on each bead, so `gt done` can find the convoy via the fast path (`getConvoyInfoFromIssue`).\n\n### Rig resolution\n\n- **Auto-resolve (preferred):** `gt sling gt-task1 gt-task2 gt-task3` -- resolves rig from the `gt-` prefix. All beads must resolve to the same rig.\n- **Explicit rig (deprecated):** `gt sling gt-task1 gt-task2 gt-task3 myrig` -- still works, prints a deprecation warning. If any bead's prefix doesn't match the explicit rig, errors with suggested actions.\n- **Mixed prefixes:** If beads resolve to different rigs, errors listing each bead's resolved rig and suggested actions (sling separately, or `--force`).\n- **Unmapped prefix:** If a prefix has no route, errors with diagnostic info (`cat .beads/routes.jsonl | grep <prefix>`).\n\n### Conflict handling\n\nIf any bead is already tracked by another convoy, batch sling **errors** with detailed conflict info (which convoy, all beads in it with statuses, and 4 recommended actions). This prevents accidental double-tracking.\n\n```bash\n# Auto-resolve: one convoy, three polecats (preferred)\ngt sling gt-task1 gt-task2 gt-task3\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n\n# Explicit rig still works but prints deprecation warning\ngt sling gt-task1 gt-task2 gt-task3 gastown\n# -> Deprecation: gt sling now auto-resolves the rig from bead prefixes.\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n```\n\n## Stage-launch workflow\n\n> Implemented in [PR #1820](https://github.com/steveyegge/gastown/pull/1820). Depends on the feeder safety guards from [PR #1759](https://github.com/steveyegge/gastown/pull/1759). Design docs: `docs/design/convoy/stage-launch/prd.md`, `docs/design/convoy/stage-launch/testing.md`.\n\nThe stage-launch workflow is a two-phase convoy creation path that validates dependencies and computes wave dispatch order **before** any work is dispatched. This is the preferred path for epic delivery.\n\n### Input types\n\n`gt convoy stage` accepts three mutually exclusive input types:\n\n| Input | Example | Behavior |\n|-------|---------|----------|\n| Epic ID | `gt convoy stage bcc-nxk2o` | BFS walks entire parent-child tree, collects all descendants |\n| Task list | `gt convoy stage gt-t1 gt-t2 gt-t3` | Analyzes exactly those tasks |\n| Convoy ID | `gt convoy stage hq-cv-abc` | Re-reads tracked beads from existing staged convoy (re-stage) |\n\nMixed types (e.g., epic + task together) error. Multiple epics or multiple convoys error.\n\n### Processing pipeline\n\n```\n1. validateStageArgs     — reject empty/flag-like args\n2. bdShow each arg       — resolve bead types\n3. resolveInputKind      — classify Epic / Tasks / Convoy\n4. collectBeads          — gather BeadInfo + DepInfo (BFS for epic, direct for tasks)\n5. buildConvoyDAG        — construct in-memory DAG (nodes + edges)\n6. detectErrors          — cycle detection + missing rig checks\n7. detectWarnings        — orphans, parked rigs, cross-rig, capacity, missing branches\n8. categorizeFindings    — split into errors / warnings\n9. chooseStatus          — staged:ready, staged:warnings, or abort on errors\n10. computeWaves         — Kahn's algorithm (only when no errors)\n11. renderDAGTree        — print ASCII dependency tree\n12. renderWaveTable      — print wave dispatch plan\n13. createStagedConvoy   — bd create --type=convoy --status=<staged-status>\n```\n\n### Wave computation (Kahn's algorithm)\n\nOnly slingable types participate in waves: `task`, `bug`, `feature`, `chore`. Epics are excluded.\n\nExecution edges (create wave ordering):\n- `blocks`\n- `conditional-blocks`\n- `waits-for`\n\nNon-execution edges (ignored for wave ordering):\n- `parent-child` — hierarchy only\n- `related`, `tracks`, `discovered-from`\n\n**Algorithm:**\n1. Filter to slingable nodes only\n2. Calculate in-degree for each node (count BlockedBy edges to other slingable nodes)\n3. Peel loop: collect all nodes with in-degree 0 → Wave N; remove them; decrement neighbors; repeat\n4. Sort within each wave alphabetically for determinism\n\nOutput example:\n```\n  Wave   ID              Title                     Rig       Blocked By\n  ──────────────────────────────────────────────────────────────────────\n  1      bcc-nxk2o.1.1   Init scaffolding          bcc       —\n  2      bcc-nxk2o.1.2   Shared types              bcc       bcc-nxk2o.1.1\n  3      bcc-nxk2o.1.3   CLI wrapper               bcc       bcc-nxk2o.1.2\n\n  3 tasks across 3 waves (max parallelism: 1 in wave 1)\n```\n\n### Convoy status model\n\nFour statuses with defined transitions:\n\n| Status | Meaning |\n|--------|---------|\n| `staged:ready` | Validated, no errors or warnings, ready to launch |\n| `staged:warnings` | Validated, no errors but has warnings. Fix and re-stage, or launch anyway. |\n| `open` | Active — daemon feeds work as beads close |\n| `closed` | Complete or cancelled |\n\nValid transitions:\n\n| From → To | Allowed? |\n|-----------|----------|\n| `staged:ready` → `open` | Yes (launch) |\n| `staged:warnings` → `open` | Yes (launch) |\n| `staged:*` → `closed` | Yes (cancel) |\n| `staged:ready` ↔ `staged:warnings` | Yes (re-stage) |\n| `open` → `closed` | Yes |\n| `closed` → `open` | Yes (reopen) |\n| `open` → `staged:*` | **No** |\n| `closed` → `staged:*` | **No** |\n\n### Error vs warning classification\n\n**Errors** (fatal — prevent convoy creation):\n\n| Category | Trigger | Fix |\n|----------|---------|-----|\n| `cycle` | Cycle detected in execution edges | Remove one blocking dep in the cycle |\n| `no-rig` | Slingable bead has no rig (prefix not in routes.jsonl) | Add routes.jsonl entry |\n\n**Warnings** (non-fatal — convoy created as `staged:warnings`):\n\n| Category | Trigger |\n|----------|---------|\n| `orphan` | Slingable task with no blocking deps in either direction (epic input only) |\n| `blocked-rig` | Bead targets a parked or docked rig |\n| `cross-rig` | Bead on a different rig than the majority |\n| `capacity` | A wave has more than 5 tasks |\n| `missing-branch` | Sub-epic with children but no integration branch |\n\n### Launch behavior\n\n`gt convoy launch <convoy-id>` transitions a staged convoy to open and dispatches Wave 1:\n\n1. Validate convoy exists and is staged\n2. Transition status to `open`\n3. Re-read tracked beads, rebuild DAG, recompute waves\n5. Dispatch every task in Wave 1 via `gt sling <beadID> <rig>`\n6. Individual sling failures do NOT abort remaining dispatches\n7. Print dispatch results (checkmark/X per task)\n8. Subsequent waves handled automatically by the daemon\n\nIf `gt convoy launch` receives an epic or task list (not a staged convoy), it delegates to `gt convoy stage --launch` to stage-then-launch in one step.\n\n### Staged convoy daemon safety\n\n**Staged convoys are completely inert to the daemon.** Neither feed path processes them:\n\n- **Event-driven feeder:** `isConvoyStaged` check in `CheckConvoysForIssue` skips any convoy with `staged:*` status. Fail-open on read errors (assumes not staged → processes, which is safe since a read error on a non-existent convoy does nothing).\n- **Stranded scan:** `gt convoy stranded` only returns open convoys. Staged convoys never appear.\n\nThis means you can stage a convoy, review the wave plan, and launch when ready — no risk of premature dispatch.\n\n### Re-staging\n\nRunning `gt convoy stage <convoy-id>` on an existing staged convoy re-analyzes and updates:\n- Re-reads tracked beads from the convoy's `tracks` deps\n- Rebuilds DAG, re-detects errors/warnings, recomputes waves\n- Updates status via `bd update` (e.g., `staged:warnings` → `staged:ready` if warnings resolved)\n- Does NOT create a new convoy or re-add track dependencies\n\n## Testing convoy changes\n\n### Running tests\n\n```bash\n# Full convoy suite (all packages)\ngo test ./internal/convoy/... ./internal/daemon/... ./internal/cmd/... -count=1\n\n# By area:\ngo test ./internal/convoy/... -v -count=1                       # feeding logic\ngo test ./internal/daemon/... -v -count=1 -run TestConvoy       # ConvoyManager\ngo test ./internal/daemon/... -v -count=1 -run TestFeedFirstReady\ngo test ./internal/cmd/... -v -count=1 -run TestCreateBatchConvoy  # batch sling\ngo test ./internal/cmd/... -v -count=1 -run TestBatchSling\ngo test ./internal/cmd/... -v -count=1 -run TestResolveRig      # rig resolution\ngo test ./internal/daemon/... -v -count=1 -run Integration      # real beads stores\n\n# Stage-launch:\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyStage     # staging logic\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyLaunch    # launch + Wave 1 dispatch\ngo test ./internal/cmd/... -v -count=1 -run TestDetectCycles    # cycle detection\ngo test ./internal/cmd/... -v -count=1 -run TestComputeWaves    # wave computation\ngo test ./internal/cmd/... -v -count=1 -run TestBuildConvoyDAG  # DAG construction\n```\n\n### Key test invariants\n\n- `feedFirstReady` dispatches exactly 1 issue per call (first success wins)\n- `feedFirstReady` iterates past failures (sling exit 1 -> try next)\n- Parked rigs are skipped in both event poll and feedFirstReady\n- hq store is never skipped even if `isRigParked` returns true for everything\n- High-water marks prevent event reprocessing across poll cycles\n- First poll cycle is warm-up only (seeds marks, no processing)\n- `IsSlingableType(\"epic\") == false`, `IsSlingableType(\"task\") == true`, `IsSlingableType(\"\") == true`\n- `isIssueBlocked` is fail-open (store error -> not blocked)\n- `parent-child` deps are NOT blocking\n- Batch sling creates exactly 1 convoy for N beads (not N convoys)\n- `resolveRigFromBeadIDs` errors on mixed prefixes, unmapped prefixes, town-level prefixes\n- Cycles in blocking deps prevent staged convoy creation (exit non-zero, no side effects)\n- Wave 1 contains ONLY tasks with zero unsatisfied blocking deps among slingable nodes\n- Epics and non-slingable types are NEVER placed in waves\n- Daemon does NOT feed issues from `staged:*` convoys (both feed paths skip)\n- `staged:warnings` convoys can still be launched (warnings are informational)\n- Re-staging a convoy does NOT create duplicates (updates in place)\n- Launch dispatches ONLY Wave 1, not subsequent waves\n- Wave computation is deterministic (same input → same output, alphabetical sort within waves)\n\n### Deeper test engineering\n\nSee `docs/design/convoy/stage-launch/testing.md` for the full stage-launch test plan (105 tests across unit, integration, snapshot, and property tiers).\n\nSee `docs/design/convoy/testing.md` for the general convoy test plan covering failure modes, coverage gaps, harness scorecard, test matrix, and recommended test strategy.\n\n## Common pitfalls\n\n- **`parent-child` is never blocking.** This is a deliberate design choice, not a bug. Consistent with `bd ready`, beads SDK, and molecule step behavior.\n- **Batch sling errors on already-tracked beads.** If any bead is already in a convoy, the entire batch sling fails with conflict details. The user must resolve the conflict before proceeding.\n- **The stranded scan has its own blocked check.** `isReadyIssue` in cmd/convoy.go reads `t.Blocked` from issue details. `isIssueBlocked` in operations.go covers the event-driven path. Don't consolidate them without understanding both paths.\n- **Empty IssueType is slingable.** Beads default to type \"task\" when IssueType is unset. Treating empty as non-slingable would break all legacy beads.\n- **`isIssueBlocked` is fail-open.** Store errors assume not blocked. A transient Dolt error should not permanently stall a convoy -- the next feed cycle retries with fresh state.\n- **Explicit rig in batch sling is deprecated.** `gt sling beads... rig` still works but prints a warning. Prefer `gt sling beads...` with auto-resolution.\n- **Staged convoys are inert.** The daemon ignores them completely. Don't expect auto-feeding until you `gt convoy launch`.\n- **Review `staged:warnings` before launching.** Warnings are informational — fix and re-stage if possible, or launch anyway if they're acceptable.\n- **`gt convoy launch` on a non-staged input delegates to stage.** If you pass an epic or task list to `launch`, it runs `stage --launch` internally. Only an already-staged convoy gets the fast path.\n- **Wave computation is informational.** Waves are computed at stage time for display. Runtime dispatch uses the daemon's per-cycle `isIssueBlocked` checks, which are more dynamic.\n- **You cannot un-stage an open convoy.** Once launched, a convoy cannot return to staged status. The `open → staged:*` transition is rejected.\n\n## Key source files\n\n| File | What it does |\n|------|-------------|\n| `internal/convoy/operations.go` | Core feeding: `CheckConvoysForIssue`, `feedNextReadyIssue`, `IsSlingableType`, `isIssueBlocked` |\n| `internal/daemon/convoy_manager.go` | `ConvoyManager` goroutines: `runEventPoll` (5s), `runStrandedScan` (30s), `feedFirstReady` |\n| `internal/cmd/convoy.go` | All `gt convoy` subcommands + `findStrandedConvoys` type filter |\n| `internal/cmd/sling.go` | Batch detection at ~242, auto-rig-resolution, deprecation warning |\n| `internal/cmd/sling_batch.go` | `runBatchSling`, `resolveRigFromBeadIDs`, `allBeadIDs`, cross-rig guard |\n| `internal/cmd/sling_convoy.go` | `createAutoConvoy`, `createBatchConvoy`, `printConvoyConflict` |\n| `internal/cmd/convoy_stage.go` | `gt convoy stage`: DAG walking, wave computation, error/warning detection, staged convoy creation |\n| `internal/cmd/convoy_launch.go` | `gt convoy launch`: status transition, Wave 1 dispatch via `dispatchWave1` |\n| `internal/daemon/daemon.go` | Daemon startup -- creates `ConvoyManager` at ~237 |\n","internal/hooks/templates/copilot/copilot-instructions.md":"# Gas Town Agent Context\n\nYou are running inside Gas Town, a multi-agent workspace manager.\n\n## Startup Protocol\n\nOn session start or after compaction, run:\n```\ngt prime\n```\nThis loads your full role context, mail, and pending work.\n\n## Key Commands\n\n- `gt prime` - Load role context (run after compaction or new session)\n- `gt mol status` - Check your hooked work\n- `gt mail inbox` - Check for messages\n- `bd ready` - Find available work\n- `gt handoff` - Cycle to fresh session\n\n## Work Protocol\n\n1. Check hook: `gt mol status`\n2. If work is hooked, execute immediately (no waiting for confirmation)\n3. If hook empty, check mail: `gt mail inbox`\n4. Complete work, commit, and push before ending session\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Agent Instructions\n\nSee **CLAUDE.md** for complete agent context and instructions.\n\nThis file exists for compatibility with tools that look for AGENTS.md.\n\n> **Recovery**: Run `gt prime` after compaction, clear, or new session\n\nFull context is injected by `gt prime` at session start.\n\n<!-- beads-agent-instructions-v2 -->\n\n---\n\n## Beads Workflow Integration\n\nThis project uses [beads](https://github.com/steveyegge/beads) for issue tracking. Issues live in `.beads/` and are tracked in git.\n\nTwo CLIs: **bd** (issue CRUD) and **bv** (graph-aware triage, read-only).\n\n### bd: Issue Management\n\n```bash\nbd ready              # Unblocked issues ready to work\nbd list --status=open # All open issues\nbd show <id>          # Full details with dependencies\nbd create --title=\"...\" --type=task --priority=2\nbd update <id> --status=in_progress\nbd close <id>         # Mark complete\nbd close <id1> <id2>  # Close multiple\nbd dep add <a> <b>    # a depends on b\nbd sync               # Sync with git\n```\n\n### bv: Graph Analysis (read-only)\n\n**NEVER run bare `bv`** — it launches interactive TUI. Always use `--robot-*` flags:\n\n```bash\nbv --robot-triage     # Ranked picks, quick wins, blockers, health\nbv --robot-next       # Single top pick + claim command\nbv --robot-plan       # Parallel execution tracks\nbv --robot-alerts     # Stale issues, cascades, mismatches\nbv --robot-insights   # Full graph metrics: PageRank, betweenness, cycles\n```\n\n### Workflow\n\n1. **Start**: `bd ready` (or `bv --robot-triage` for graph analysis)\n2. **Claim**: `bd update <id> --status=in_progress`\n3. **Work**: Implement the task\n4. **Complete**: `bd close <id>`\n5. **Sync**: `bd sync` at session end\n\n### Session Close Protocol\n\n```bash\ngit status            # Check what changed\ngit add <files>       # Stage code changes\nbd sync               # Commit beads changes\ngit commit -m \"...\"   # Commit code\nbd sync               # Commit any new beads changes\ngit push              # Push to remote\n```\n\n### Key Concepts\n\n- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (numbers only)\n- **Types**: task, bug, feature, epic, question, docs\n- **Dependencies**: `bd ready` shows only unblocked work\n\n<!-- end-beads-agent-instructions -->\n\n<!-- gastown-agent-instructions-v1 -->\n\n---\n\n## Gas Town Multi-Agent Communication\n\nThis workspace is part of a **Gas Town** multi-agent environment. You communicate\nwith other agents using `gt` commands — never by printing text or using raw tmux.\n\n### Nudging Agents (Immediate Delivery)\n\n`gt nudge` sends a message directly to another agent's active session:\n\n```bash\ngt nudge mayor \"Status update: PR review complete\"\ngt nudge laneassist/crew/dom \"Check your mail — PR ready for review\"\ngt nudge witness \"Polecat health check needed\"\ngt nudge refinery \"Merge queue has items\"\n```\n\n**Target formats:**\n- Role shortcuts: `mayor`, `deacon`, `witness`, `refinery`\n- Full path: `<rig>/crew/<name>`, `<rig>/polecats/<name>`\n\n**Important:** `gt nudge` is the ONLY way to send text to another agent's session.\nNever print \"Hey @name\" — the other agent cannot see your terminal output.\n\n### Sending Mail (Persistent Messages)\n\n`gt mail` sends messages that persist across session restarts:\n\n```bash\n# Reading\ngt mail inbox                    # List messages\ngt mail read <id>                # Read a specific message\n\n# Sending (use --stdin for multi-line content)\ngt mail send mayor/ -s \"Subject\" -m \"Short message\"\ngt mail send laneassist/crew/dom -s \"PR Review\" --stdin <<'BODY'\nMulti-line message content here.\nDetails about the PR and what to look for.\nBODY\ngt mail send --human -s \"Subject\" -m \"Message to overseer\"\n```\n\n### When to Use Which\n\n| Want to... | Command | Why |\n|------------|---------|-----|\n| Wake a sleeping agent | `gt nudge <target> \"msg\"` | Immediate delivery |\n| Send detailed task/info | `gt mail send <target> -s \"...\" --stdin` | Persists across restarts |\n| Both: send + wake | `gt mail send` then `gt nudge` | Mail carries payload, nudge wakes |\n\n### Context Recovery\n\nAfter compaction or new session, run `gt prime` to reload your full role context,\nidentity, and any pending work.\n\n```bash\ngt prime              # Full context reload\ngt hook               # Check for assigned work\ngt mail inbox         # Check for messages\n```\n\n<!-- end-gastown-agent-instructions -->\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `gt prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `gt prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n   ```bash\n   git pull --rebase\n   bd dolt push\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n","isInternal":false,"tokens":1519,"sizeBytes":5978},{"name":"copilot-instructions.md","path":"internal/hooks/templates/copilot/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/internal/hooks/templates/copilot/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"# Gas Town Agent Context\n\nYou are running inside Gas Town, a multi-agent workspace manager.\n\n## Startup Protocol\n\nOn session start or after compaction, run:\n```\ngt prime\n```\nThis loads your full role context, mail, and pending work.\n\n## Key Commands\n\n- `gt prime` - Load role context (run after compaction or new session)\n- `gt mol status` - Check your hooked work\n- `gt mail inbox` - Check for messages\n- `bd ready` - Find available work\n- `gt handoff` - Cycle to fresh session\n\n## Work Protocol\n\n1. Check hook: `gt mol status`\n2. If work is hooked, execute immediately (no waiting for confirmation)\n3. If hook empty, check mail: `gt mail inbox`\n4. Complete work, commit, and push before ending session\n","isInternal":false,"tokens":176,"sizeBytes":704},{"name":"SKILL.md","path":".claude/skills/crew-commit/SKILL.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/skills/crew-commit/SKILL.md","title":"crew-commit","category":"anthropic-skill","format":"markdown","content":"---\nname: crew-commit\ndescription: >\n  Canonical commit workflow for Gas Town crew members: pre-flight checks,\n  branch creation, gt commit with agent identity, push, and PR creation.\n  Use when ready to commit and submit work for review.\nallowed-tools: \"Bash(git *), Bash(gt *), Bash(gh *)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# Crew Commit — Canonical Git Workflow\n\nThis skill guides crew members through the standard Gas Town commit workflow:\npre-flight → branch → stage → commit → push → PR.\n\n> **⚠️ NEVER commit directly to `main`.** All crew work goes through branches\n> and pull requests. The Refinery handles merges to main.\n\n## Usage\n\n```\n/crew-commit\n```\n\nRun this when you have changes ready to commit. The skill walks you through\neach step in order.\n\n---\n\n## Step 1: Pre-flight Checks\n\nBefore touching anything, sync with origin and verify your state.\n\n```bash\n# Fetch latest from origin\ngit fetch origin\n\n# Check current branch and status\ngit status\ngit branch --show-current\n\n# If you're on main, STOP — create a branch first (Step 2)\n```\n\n**If you're behind origin/main**, rebase now:\n\n```bash\ngit rebase origin/main\n```\n\nIf there are conflicts, resolve them carefully before proceeding.\nIf stuck on a rebase conflict, stop and get help rather than force-pushing.\n\n---\n\n## Step 2: Create a Feature Branch\n\n**If you're already on a feature branch**, skip to Step 3.\n\nBranch naming convention: `<type>/<short-description>`\n\nTypes:\n- `feat/` — new feature\n- `fix/` — bug fix\n- `refactor/` — code restructuring\n- `docs/` — documentation only\n- `chore/` — maintenance, deps, config\n- `test/` — tests only\n\n```bash\n# Create and switch to feature branch\ngit checkout -b feat/my-feature-description\n\n# Or use the crew/<name> prefix for crew-specific branches\ngit checkout -b crew/<your-name>/description\n```\n\n---\n\n## Step 3: Submodule Warning\n\n**Check for submodules before staging.** Accidentally committing a submodule\npointer change causes cascading failures for other crew members.\n\n```bash\n# Check if repo has submodules\ncat .gitmodules 2>/dev/null || echo \"(no submodules)\"\n\n# Check for dirty submodule state\ngit submodule status 2>/dev/null\n```\n\n**Common submodule paths to watch:** `shared/`, `config/`, `vendor/`\n\nIf you see changes in submodule directories:\n- Do NOT `git add shared/` or `git add config/` unless you intentionally\n  bumped the submodule pointer\n- Submodule pointer changes should be explicit and deliberate\n- When in doubt, ask before including submodule changes\n\n---\n\n## Step 4: Stage Your Changes\n\nPrefer staging specific files over `git add .` or `git add -A`.\n\n```bash\n# Review what changed\ngit diff\ngit status\n\n# Stage specific files (preferred)\ngit add src/myfile.go tests/myfile_test.go\n\n# If you need to stage all intentional changes and have verified no secrets:\ngit add -p    # Interactive staging — review each hunk\n```\n\n**Before staging, verify:**\n- [ ] No `.env` files, API keys, or credentials\n- [ ] No debug prints or temporary test code\n- [ ] No unrelated changes mixed in\n- [ ] Submodule directories NOT accidentally staged (unless intentional)\n\n---\n\n## Step 5: Commit with gt commit\n\nUse `gt commit` instead of `git commit`. It automatically sets the correct\nagent identity (name + email) based on your `GT_ROLE`.\n\n```bash\ngt commit -m \"$(cat <<'EOF'\n<type>: <concise description of what and why>\n\n<optional body: context, motivation, or notable details>\nEOF\n)\"\n```\n\n**Commit message format:**\n- First line: `<type>: <subject>` (50 chars or less)\n- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`\n- Use imperative mood: \"add feature\" not \"added feature\"\n- Body is optional but valuable for non-obvious changes\n\n**Good examples:**\n```\nfeat: add retry logic to webhook delivery\nfix: prevent nil pointer when session token expires\ndocs: clarify crew commit workflow in CONTRIBUTING.md\n```\n\n---\n\n## Step 6: Push Branch to Origin\n\n```bash\ngit push origin <your-branch-name>\n\n# Or, if branch doesn't exist on remote yet:\ngit push -u origin <your-branch-name>\n```\n\n---\n\n## Step 7: Create Pull Request\n\n```bash\ngh pr create --title \"<type>: <concise description>\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- <what changed and why>\n\n## Test plan\n\n- [ ] <how to verify this works>\n\n## Notes\n\n<any context reviewers need>\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\nEOF\n)\"\n```\n\nAfter creating the PR, note the PR number from the output.\n\n---\n\n## Step 8: Notify (Optional)\n\nIf your work affects others or is high priority:\n\n```bash\nnotify \"PR ready: <brief description> — #<PR number>\"\n```\n\n---\n\n## Completion Checklist\n\n- [ ] Synced with origin/main (git fetch + rebase)\n- [ ] On a feature branch (NOT main)\n- [ ] Submodules NOT accidentally staged\n- [ ] Specific files staged (no secrets, no debug code)\n- [ ] Used `gt commit` (not `git commit`)\n- [ ] Branch pushed to origin\n- [ ] PR created via `gh pr create`\n\n---\n\n## Anti-Patterns\n\n| ❌ Don't | ✅ Do instead |\n|----------|--------------|\n| `git push origin main` | Push feature branch, create PR |\n| `git commit` directly | `gt commit` (sets agent identity) |\n| `git add .` blindly | Stage specific files, verify with `git status` |\n| Include `shared/` or `config/` without intent | Check `git submodule status` first |\n| Force-push without understanding why | Resolve the root cause |\n| Commit secrets or .env files | Always check `git diff` before staging |\n\n---\n\n## If You Get Stuck\n\n- **Rebase conflicts**: resolve carefully, then `git rebase --continue`\n- **Pushed wrong branch**: ask before force-pushing; usually `git push origin <branch>` is fine\n- **Need to undo last commit**: `git reset HEAD~1` (keeps changes staged)\n- **Committed to main by mistake**: stop immediately, ask for help\n","frontmatter":{"name":"crew-commit","description":"Canonical commit workflow for Gas Town crew members: pre-flight checks, branch creation, gt commit with agent identity, push, and PR creation. Use when ready to commit and submit work for review.\n","allowed-tools":"Bash(git *), Bash(gt *), Bash(gh *)","version":"1.0.0","author":"Gas Town","allowedTools":["Bash(git","*),","Bash(gt","*),","Bash(gh","*)"]},"allowedTools":["Bash(git","*),","Bash(gt","*),","Bash(gh","*)"],"isInternal":false,"tokens":1444,"sizeBytes":5763},{"name":"SKILL.md","path":".claude/skills/ghi-list/SKILL.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/skills/ghi-list/SKILL.md","title":"ghi-list","category":"anthropic-skill","format":"markdown","content":"---\nname: ghi-list\ndescription: >\n  List GitHub issues in a formatted ASCII table. Supports filters like --state,\n  --assignee, --label. Use for issue triage and tracking workflows.\nallowed-tools: \"Bash(gh issue list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# GHI List - Formatted GitHub Issues Table\n\nDisplay GitHub issues in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/ghi-list [options]\n```\n\n## Options (passed to gh issue list)\n\n- `--state open|closed|all` - Filter by state (default: open)\n- `--assignee <user>` - Filter by assignee\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--author <user>` - Filter by author\n- `--milestone <name>` - Filter by milestone\n\n## Execution Steps\n\n1. Run `gh issue list` with any provided options plus `--json number,assignees,labels,title,state`\n2. Format output as an ASCII table using box-drawing characters\n3. Truncate titles to fit reasonable terminal width (~45 chars)\n4. Show first assignee only, or \"-\" if none\n5. Show first 2-3 labels abbreviated, or \"-\" if none\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌───────┬────────────┬─────────────────┬───────────────────────────────────────────────┬────────┐\n│ Issue │ Assignee   │ Labels          │ Title                                         │ State  │\n├───────┼────────────┼─────────────────┼───────────────────────────────────────────────┼────────┤\n│   372 │ max        │ enhancement     │ Create /pr-list and /ghi-list skills          │ OPEN   │\n│   371 │ -          │ bug, priority   │ Fix null pointer in auth module               │ OPEN   │\n│   370 │ joe        │ -               │ Update documentation for new API              │ CLOSED │\n└───────┴────────────┴─────────────────┴───────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align issue numbers\n- Left-align text columns\n- Pad columns consistently\n- For assignees: show login of first assignee, \"-\" if none\n- For labels: show comma-separated names (truncate if >17 chars)\n- Show count summary below table: \"**N issues** (M open, K closed)\"\n\n## Example Commands\n\n```bash\n# Default - open issues\ngh issue list --json number,assignees,labels,title,state\n\n# With filters\ngh issue list --state all --label bug --json number,assignees,labels,title,state\n```\n","frontmatter":{"name":"ghi-list","description":"List GitHub issues in a formatted ASCII table. Supports filters like --state, --assignee, --label. Use for issue triage and tracking workflows.\n","allowed-tools":"Bash(gh issue list:*)","version":"1.0.0","author":"Gas Town","allowedTools":["Bash(gh","issue","list:*)"]},"allowedTools":["Bash(gh","issue","list:*)"],"isInternal":false,"tokens":642,"sizeBytes":3067},{"name":"SKILL.md","path":".claude/skills/pr-list/SKILL.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/skills/pr-list/SKILL.md","title":"pr-list","category":"anthropic-skill","format":"markdown","content":"---\nname: pr-list\ndescription: >\n  List GitHub PRs in a formatted ASCII table. Supports filters like --state,\n  --author, --label. Use for PR review workflows and sheriff duties.\nallowed-tools: \"Bash(gh pr list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR List - Formatted Pull Request Table\n\nDisplay GitHub pull requests in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/pr-list [options]\n```\n\n## Options (passed to gh pr list)\n\n- `--state open|closed|merged|all` - Filter by state (default: open)\n- `--author <user>` - Filter by author\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--assignee <user>` - Filter by assignee\n- `--draft` - Show only drafts\n- `--all-reviews` - Include PRs with CHANGES_REQUESTED (excluded by default)\n\n## Execution Steps\n\n1. Run `gh pr list` with any provided options plus `--json number,author,title,state,isDraft,reviewDecision`\n2. **Filter out PRs with reviewDecision=\"CHANGES_REQUESTED\"** (unless `--all-reviews` specified)\n3. Format output as an ASCII table using box-drawing characters\n4. Truncate titles to fit reasonable terminal width (~50 chars)\n5. Truncate author names if needed (~18 chars)\n6. Show state as OPEN/CLOSED/MERGED/DRAFT, append \"(changes requested)\" if filtered with --all-reviews\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌─────┬────────────────────┬───────────────────────────────────────────────────┬────────┐\n│  PR │ Author             │ Title                                             │ State  │\n├─────┼────────────────────┼───────────────────────────────────────────────────┼────────┤\n│ 123 │ username           │ feat: add new feature for something               │ OPEN   │\n│ 122 │ another-user       │ fix: resolve bug in component                     │ DRAFT  │\n└─────┴────────────────────┴───────────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align PR numbers\n- Left-align text columns\n- Pad columns consistently\n- Show count summary below table: \"**N open PRs** (M drafts)\"\n\n## Example Commands\n\n```bash\n# Default - open PRs (excludes CHANGES_REQUESTED)\ngh pr list --json number,author,title,state,isDraft,reviewDecision\n\n# With filters\ngh pr list --state all --author boshu2 --json number,author,title,state,isDraft,reviewDecision\n```\n","frontmatter":{"name":"pr-list","description":"List GitHub PRs in a formatted ASCII table. Supports filters like --state, --author, --label. Use for PR review workflows and sheriff duties.\n","allowed-tools":"Bash(gh pr list:*)","version":"1.0.0","author":"Gas Town","allowedTools":["Bash(gh","pr","list:*)"]},"allowedTools":["Bash(gh","pr","list:*)"],"isInternal":false,"tokens":638,"sizeBytes":2997},{"name":"skill.md","path":".claude/skills/pr-sheriff/skill.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/skills/pr-sheriff/skill.md","title":"pr-sheriff","category":"anthropic-skill","format":"markdown","content":"---\nname: pr-sheriff\ndescription: >\n  PR Sheriff workflow: triage PRs into easy-wins and crew assignments.\n  Prints recommendations inline - does NOT post to GitHub.\nallowed-tools: \"Bash(gh pr *), Bash(git *), Bash(gt *), Bash(bd *), Bash(cat *)\"\nversion: \"2.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR Sheriff - Triage and Review Workflow\n\nThis skill delegates to the `mol-pr-sheriff-patrol` formula, which lives at\n`$GT_ROOT/.beads/formulas/mol-pr-sheriff-patrol.formula.toml` and is shared\nacross all Gas Town rigs (gastown, beads, etc.).\n\n## Repo Scope\n\nThis rig (gastown/crew/max) is responsible for **steveyegge/gastown only**.\nThe beads repo (steveyegge/beads) is handled by beads/crew/emma.\nDo NOT discover or triage PRs from repos outside your scope.\n\nWhen loading the shared config, filter the repo list to only `steveyegge/gastown`.\n\n## Usage\n\n```\n/pr-sheriff [repo]\n```\n\n- `repo` - Optional. If provided, overrides the default scope.\n  If omitted, scan only `steveyegge/gastown` (this rig's scope).\n\n## How to Execute\n\n**1. Load the config:**\n```bash\ncat $GT_ROOT/.beads/pr-sheriff-config.json\n```\n\nThis contains crew mappings per repo and contributor policies\n(trust tiers, firewalled contributors, bot auto-merge rules).\n**Only scan repos within your scope** (see Repo Scope above).\n\n**2. Follow the formula steps in order:**\n```bash\ngt formula show mol-pr-sheriff-patrol\n```\n\nThe formula defines a 7-step workflow:\n\n| Step | What it does |\n|------|-------------|\n| load-config | Load pr-sheriff-config.json, establish repo list |\n| discover-prs | Find open PRs needing review across all repos |\n| triage-batch | Categorize all PRs in one pass (preserves cross-PR context) |\n| merge-easy-wins | Merge approved easy-wins via `gh pr merge` |\n| dispatch-crew-reviews | Nudge crew for NEEDS-CREW PRs |\n| dispatch-deep-reviews | Nudge crew for NEEDS-HUMAN PRs (full evaluation framework) |\n| collect-results | Gather crew review nudge-backs |\n| interactive-review | Walk through remaining NEEDS-HUMAN PRs with overseer |\n| summarize | Print patrol summary |\n\n**3. For each step, read the full description:**\n```bash\ngt formula show mol-pr-sheriff-patrol  # Shows all steps with descriptions\n```\n\n## Key References\n\n- **Patrol formula:** `mol-pr-sheriff-patrol` (town-level)\n- **Crew review formula:** `mol-pr-crew-review` (dispatched to crew)\n- **Deep review formula:** `mol-pr-deep-review` (dispatched for NEEDS-HUMAN)\n- **Config:** `$GT_ROOT/.beads/pr-sheriff-config.json`\n\n## Contributor Policy Tiers\n\nLoaded from config. Current tiers:\n\n| Tier | Handling |\n|------|----------|\n| bot-trusted | Auto-merge if CI passes (e.g., dependabot) |\n| community | Normal triage — easy-win / crew / deep review |\n| firewalled | Always NEEDS-HUMAN, never auto-merge, deep review required |\n\n## Category Decision Tree\n\n```\nDraft? → SKIP\nContributor firewalled? → NEEDS-HUMAN (deep review)\nDependabot patch bump + CI green? → EASY-WIN\n<50 lines, obvious bug/doc/test fix? → EASY-WIN\nSecurity/architecture/API change? → NEEDS-HUMAN\nMulti-concern PR? → NEEDS-HUMAN\n100+ lines new feature? → NEEDS-CREW or NEEDS-HUMAN\nEverything else → NEEDS-CREW\n```\n\n## Deep Review Evaluation Framework (NEEDS-HUMAN)\n\nThe deep review formula (mol-pr-deep-review) applies six lenses:\n\n1. **Plugin/integration fit** — core vs plugin/formula/integration?\n2. **Tech-debt weight** — complexity justified by user breadth?\n3. **Contributor track record** — first-time, repeat, or firewalled?\n4. **ZFC compliance** — structural checks, not string heuristics?\n5. **Problem validity + solution fit** — real problem, right solution?\n6. **Splitability** — can good parts be cherry-picked from bad?\n\nFinal verdicts: MERGE | CHERRY-PICK | REWORK | REIMPLEMENT | CLOSE\n\n## Output Format\n\nFor each PR, print a recommendation block:\n\n```\n### PR #<num>: <title>\nAuthor: <login> | +<additions>/-<deletions> | <changedFiles> files\n\n**Category**: EASY-WIN | NEEDS-CREW | NEEDS-HUMAN | SKIP\n\n**Analysis**:\n<1-3 sentences explaining the change and why it fits this category>\n\n**Recommendation**:\n<specific action>\n```\n\n## Summary Output\n\n```\n## PR Sheriff Patrol Summary — <date>\n\n**Easy-wins merged**: N\n**Crew-reviewed and merged**: N\n**Sent back for rework**: N\n**Closed**: N\n**Still pending**: N\n```\n\n## Dispatching Work: Use Ephemeral Beads\n\nWhen creating beads to track fix-merge work for polecats or crew, **use\nephemeral beads (wisps)** rather than persistent beads. PR review/fix-merge\ntasks are orchestration scaffolding — they exist to give a polecat something\nto hook and track, not to create a permanent record.\n\nEphemeral beads are the right trade-off: they give polecats and crew trackable\nwork items without polluting Dolt's permanent ledger with one-off orchestration\nnoise. If/when beads are exported to permanent ledgers, review-task wisps won't\nclutter the history.\n\n```bash\n# Ephemeral bead for fix-merge dispatch\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review \\\n  --wisp-type patrol\n\n# vs persistent (avoid for orchestration work)\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review\n```\n\nThe `--wisp-type patrol` flag marks it as ephemeral orchestration work that\nthe reaper will eventually clean up. The polecat/crew member can still hook it,\nwork it, and close it normally.\n\n## CRITICAL Rules\n\n- All output is printed inline. Do NOT post comments to GitHub.\n- The overseer decides what gets posted externally.\n- Contributor-friendly: help contributors get to the finish line.\n- Use `Co-authored-by` trailer when fixing up contributor work.\n","frontmatter":{"name":"pr-sheriff","description":"PR Sheriff workflow: triage PRs into easy-wins and crew assignments. Prints recommendations inline - does NOT post to GitHub.\n","allowed-tools":"Bash(gh pr *), Bash(git *), Bash(gt *), Bash(bd *), Bash(cat *)","version":"2.0.0","author":"Gas Town","allowedTools":["Bash(gh","pr","*),","Bash(git","*),","Bash(gt","*),","Bash(bd","*),","Bash(cat","*)"]},"allowedTools":["Bash(gh","pr","*),","Bash(git","*),","Bash(gt","*),","Bash(bd","*),","Bash(cat","*)"],"isInternal":false,"tokens":1491,"sizeBytes":5579},{"name":"SKILL.md","path":".cursor/skills/gas-town-cursor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.cursor/skills/gas-town-cursor/SKILL.md","title":"gas-town-cursor","category":"anthropic-skill","format":"markdown","content":"---\nname: gas-town-cursor\ndescription: >\n  Develop and operate Gas Town with the Cursor agent preset (cursor-agent CLI):\n  gt flags, hooks at .cursor/hooks.json, session resume, and how this repo differs from README marketing copy.\n---\n\n# Gas Town + Cursor Agent CLI\n\nUse this skill when working **in this repository** with the **`cursor`** agent preset (CLI binary **`cursor-agent`**, sometimes symlinked as **`agent`**).\n\n## Concepts\n\n| Name | Meaning |\n|------|---------|\n| **Preset `cursor`** | Gas Town agent id (`GT_AGENT=cursor`). Config lives in `internal/config/agents.go` (`AgentCursor`). |\n| **Binary `cursor-agent`** | The Cursor Agent CLI process name for pane/detection; install docs may also symlink `agent` → same binary. |\n| **Hooks** | Cursor lifecycle hooks are configured at **`.cursor/hooks.json`** (see preset `HooksSettingsFile`). |\n\n## Essential commands\n\n- Build / run `gt` from repo root: `make build` or `go run ./cmd/gt …`.\n- Point a session at the Cursor preset: spawn or config so the runtime uses **`--agent cursor`** (or set **`GT_AGENT=cursor`** where applicable).\n- After changing hooks or settings: **`gt up --restore`** (or role-specific restart) so agents reload config.\n\n## Resume semantics\n\nThe Cursor preset uses **`--resume <chatId>`** style resume (`ResumeStyle: flag`). Session identity is not carried in a dedicated env var in the same way as Claude’s `CLAUDE_SESSION_ID`; follow the preset fields in `internal/config/agents.go` (`ResumeFlag`, `ResumeStyle`).\n\n## Read more\n\n- Beads / plan handoff: [`docs/cursor-runtime-beads-tasks.md`](../../../docs/cursor-runtime-beads-tasks.md)\n- Agent instructions for automation: [`AGENTS.md`](../../../AGENTS.md) and [`CLAUDE.md`](../../../CLAUDE.md) (project-wide, not Cursor-only)\n\n## Boundary\n\nProject **README** is user-facing product overview; **`.cursor/README.md`** is Cursor-specific onboarding for this repo. Prefer linking to those files instead of duplicating long install steps inside skills.\n","frontmatter":{"name":"gas-town-cursor","description":"Develop and operate Gas Town with the Cursor agent preset (cursor-agent CLI): gt flags, hooks at .cursor/hooks.json, session resume, and how this repo differs from README marketing copy.\n"},"isInternal":false,"tokens":483,"sizeBytes":1996},{"name":"SKILL.md","path":"docs/skills/convoy/SKILL.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/docs/skills/convoy/SKILL.md","title":"convoy","category":"anthropic-skill","format":"markdown","content":"---\nname: convoy\ndescription: The definitive guide for working with gastown's convoy system -- batch work tracking, event-driven feeding, stage-launch workflow, and dispatch safety guards. Use when writing convoy code, debugging convoy behavior, adding convoy features, testing convoy changes, or answering questions about how convoys work. Triggers on convoy, convoy manager, convoy feeding, dispatch, stranded convoy, feedFirstReady, feedNextReadyIssue, IsSlingableType, isIssueBlocked, CheckConvoysForIssue, gt convoy, gt sling, stage, launch, staged, wave.\n---\n\n# Gastown Convoy System\n\nThe convoy system tracks batches of work across rigs. A convoy is a bead that `tracks` other beads via dependencies. The daemon monitors close events and feeds the next ready issue when one completes.\n\n## Architecture\n\n```\n+================================ CREATION =================================+\n|                                                                            |\n|   gt sling <beads>      gt convoy create ...     gt convoy stage <epic>    |\n|        |  (auto-convoy)       |  (explicit)            |  (validated)     |\n|        v                      v                        v                  |\n|   +-----------+          +-----------+         +----------------+         |\n|   |  status:  |          |  status:  |         |    status:     |         |\n|   |   open    |          |   open    |         | staged:ready   |         |\n|   +-----------+          +-----------+         | staged:warnings|         |\n|                                                +----------------+         |\n|                                                        |                  |\n|                                              gt convoy launch             |\n|                                                        |                  |\n|                                                        v                  |\n|                                                +----------------+         |\n|                                                |    status:     |         |\n|                                                |     open       |         |\n|                                                | (Wave 1 slung) |         |\n|                                                +----------------+         |\n|                                                                            |\n|   All paths produce: CONVOY (hq-cv-*)                                      |\n|                      tracks: issue1, issue2, ...                           |\n+============================================================================+\n              |                              |\n              v                              v\n+= EVENT-DRIVEN FEEDER (5s) =+   +=== STRANDED SCAN (30s) ===+\n|                              |   |                            |\n|   GetAllEventsSince (SDK)    |   |   findStranded             |\n|     |                        |   |     |                      |\n|     v                        |   |     v                      |\n|   close event detected       |   |   convoy has ready issues  |\n|     |                        |   |   but no active workers    |\n|     v                        |   |     |                      |\n|   CheckConvoysForIssue       |   |     v                      |\n|     |                        |   |   feedFirstReady           |\n|     v                        |   |   (iterates all ready)     |\n|   feedNextReadyIssue         |   |     |                      |\n|   (iterates all ready)       |   |     v                      |\n|     |                        |   |   gt sling <next-bead>     |\n|     v                        |   |   or closeEmptyConvoy     |\n|   gt sling <next-bead>       |   |                            |\n|                              |   +============================+\n+==============================+\n```\n\nThree creation paths (sling, create, stage), two feed paths, same safety guards:\n- **Event-driven** (`operations.go`): Polls beads stores every ~5s for close events. Calls `feedNextReadyIssue` which checks `IsSlingableType` + `isIssueBlocked` before dispatch. **Skips staged convoys** (`isConvoyStaged` check).\n- **Stranded scan** (`convoy_manager.go`): Runs every 30s. `feedFirstReady` iterates all ready issues. The ready list is pre-filtered by `IsSlingableType` in `findStrandedConvoys` (cmd/convoy.go). **Only sees open convoys** — staged convoys never appear.\n\n## Safety guards (the three rules)\n\nThese prevent the event-driven feeder from dispatching work it shouldn't:\n\n### 1. Type filtering (`IsSlingableType`)\n\nOnly leaf work items dispatch. Defined in `operations.go`:\n\n```go\nvar slingableTypes = map[string]bool{\n    \"task\": true, \"bug\": true, \"feature\": true, \"chore\": true,\n    \"\": true, // empty defaults to task\n}\n```\n\nEpics, sub-epics, convoys, decisions -- all skip. Applied in both `feedNextReadyIssue` (event path) and `findStrandedConvoys` (stranded path).\n\n### 2. Blocks dep checking (`isIssueBlocked`)\n\nIssues with unclosed `blocks`, `conditional-blocks`, or `waits-for` dependencies skip. `parent-child` is **not** blocking -- a child task dispatches even if its parent epic is open. This is consistent with `bd ready` and molecule step behavior.\n\nFail-open on store errors (assumes not blocked) to avoid stalling convoys on transient Dolt issues.\n\n### 3. Dispatch failure iteration\n\nBoth feed paths iterate past failures instead of giving up:\n- `feedNextReadyIssue`: `continue` on dispatch failure, try next ready issue\n- `feedFirstReady`: `for range ReadyIssues` with `continue` on skip/failure, `return` on first success\n\n## CLI commands\n\n### Stage and launch (validated creation)\n\n```bash\ngt convoy stage <epic-id>            # analyze deps, build DAG, compute waves, create staged convoy\ngt convoy stage gt-task1 gt-task2    # stage from explicit task list\ngt convoy stage hq-cv-abc            # re-stage existing staged convoy\ngt convoy stage <epic-id> --json     # machine-readable output\ngt convoy stage <epic-id> --launch   # stage + immediately launch if no errors\ngt convoy launch hq-cv-abc           # transition staged → open, dispatch Wave 1\ngt convoy launch <epic-id>           # stage + launch in one step (delegates to stage --launch)\n```\n\n### Create and manage\n\n```bash\ngt convoy create \"Auth overhaul\" gt-task1 gt-task2 gt-task3\ngt convoy add hq-cv-abc gt-task4\n```\n\n### Check and monitor\n\n```bash\ngt convoy check hq-cv-abc       # auto-closes if all tracked issues done\ngt convoy check                  # check all open convoys\ngt convoy status hq-cv-abc       # single convoy detail\ngt convoy list                   # all convoys\ngt convoy list --all             # include closed\n```\n\n### Find stranded work\n\n```bash\ngt convoy stranded               # ready work with no active workers\ngt convoy stranded --json        # machine-readable\n```\n\n### Close and land\n\n```bash\ngt convoy close hq-cv-abc --reason \"done\"\ngt convoy land hq-cv-abc         # cleanup worktrees + close\n```\n\n### Interactive TUI\n\n```bash\ngt convoy -i                     # opens interactive convoy browser\ngt convoy --interactive          # long form\n```\n\n## Batch sling behavior\n\n`gt sling <bead1> <bead2> <bead3>` creates **one convoy** tracking all beads. The rig is auto-resolved from the beads' prefixes (via `routes.jsonl`). The convoy title is `\"Batch: N beads to <rig>\"`. Each bead gets its own polecat, but they share a single convoy for tracking.\n\nThe convoy ID and merge strategy are stored on each bead, so `gt done` can find the convoy via the fast path (`getConvoyInfoFromIssue`).\n\n### Rig resolution\n\n- **Auto-resolve (preferred):** `gt sling gt-task1 gt-task2 gt-task3` -- resolves rig from the `gt-` prefix. All beads must resolve to the same rig.\n- **Explicit rig (deprecated):** `gt sling gt-task1 gt-task2 gt-task3 myrig` -- still works, prints a deprecation warning. If any bead's prefix doesn't match the explicit rig, errors with suggested actions.\n- **Mixed prefixes:** If beads resolve to different rigs, errors listing each bead's resolved rig and suggested actions (sling separately, or `--force`).\n- **Unmapped prefix:** If a prefix has no route, errors with diagnostic info (`cat .beads/routes.jsonl | grep <prefix>`).\n\n### Conflict handling\n\nIf any bead is already tracked by another convoy, batch sling **errors** with detailed conflict info (which convoy, all beads in it with statuses, and 4 recommended actions). This prevents accidental double-tracking.\n\n```bash\n# Auto-resolve: one convoy, three polecats (preferred)\ngt sling gt-task1 gt-task2 gt-task3\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n\n# Explicit rig still works but prints deprecation warning\ngt sling gt-task1 gt-task2 gt-task3 gastown\n# -> Deprecation: gt sling now auto-resolves the rig from bead prefixes.\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n```\n\n## Stage-launch workflow\n\n> Implemented in [PR #1820](https://github.com/steveyegge/gastown/pull/1820). Depends on the feeder safety guards from [PR #1759](https://github.com/steveyegge/gastown/pull/1759). Design docs: `docs/design/convoy/stage-launch/prd.md`, `docs/design/convoy/stage-launch/testing.md`.\n\nThe stage-launch workflow is a two-phase convoy creation path that validates dependencies and computes wave dispatch order **before** any work is dispatched. This is the preferred path for epic delivery.\n\n### Input types\n\n`gt convoy stage` accepts three mutually exclusive input types:\n\n| Input | Example | Behavior |\n|-------|---------|----------|\n| Epic ID | `gt convoy stage bcc-nxk2o` | BFS walks entire parent-child tree, collects all descendants |\n| Task list | `gt convoy stage gt-t1 gt-t2 gt-t3` | Analyzes exactly those tasks |\n| Convoy ID | `gt convoy stage hq-cv-abc` | Re-reads tracked beads from existing staged convoy (re-stage) |\n\nMixed types (e.g., epic + task together) error. Multiple epics or multiple convoys error.\n\n### Processing pipeline\n\n```\n1. validateStageArgs     — reject empty/flag-like args\n2. bdShow each arg       — resolve bead types\n3. resolveInputKind      — classify Epic / Tasks / Convoy\n4. collectBeads          — gather BeadInfo + DepInfo (BFS for epic, direct for tasks)\n5. buildConvoyDAG        — construct in-memory DAG (nodes + edges)\n6. detectErrors          — cycle detection + missing rig checks\n7. detectWarnings        — orphans, parked rigs, cross-rig, capacity, missing branches\n8. categorizeFindings    — split into errors / warnings\n9. chooseStatus          — staged:ready, staged:warnings, or abort on errors\n10. computeWaves         — Kahn's algorithm (only when no errors)\n11. renderDAGTree        — print ASCII dependency tree\n12. renderWaveTable      — print wave dispatch plan\n13. createStagedConvoy   — bd create --type=convoy --status=<staged-status>\n```\n\n### Wave computation (Kahn's algorithm)\n\nOnly slingable types participate in waves: `task`, `bug`, `feature`, `chore`. Epics are excluded.\n\nExecution edges (create wave ordering):\n- `blocks`\n- `conditional-blocks`\n- `waits-for`\n\nNon-execution edges (ignored for wave ordering):\n- `parent-child` — hierarchy only\n- `related`, `tracks`, `discovered-from`\n\n**Algorithm:**\n1. Filter to slingable nodes only\n2. Calculate in-degree for each node (count BlockedBy edges to other slingable nodes)\n3. Peel loop: collect all nodes with in-degree 0 → Wave N; remove them; decrement neighbors; repeat\n4. Sort within each wave alphabetically for determinism\n\nOutput example:\n```\n  Wave   ID              Title                     Rig       Blocked By\n  ──────────────────────────────────────────────────────────────────────\n  1      bcc-nxk2o.1.1   Init scaffolding          bcc       —\n  2      bcc-nxk2o.1.2   Shared types              bcc       bcc-nxk2o.1.1\n  3      bcc-nxk2o.1.3   CLI wrapper               bcc       bcc-nxk2o.1.2\n\n  3 tasks across 3 waves (max parallelism: 1 in wave 1)\n```\n\n### Convoy status model\n\nFour statuses with defined transitions:\n\n| Status | Meaning |\n|--------|---------|\n| `staged:ready` | Validated, no errors or warnings, ready to launch |\n| `staged:warnings` | Validated, no errors but has warnings. Fix and re-stage, or launch anyway. |\n| `open` | Active — daemon feeds work as beads close |\n| `closed` | Complete or cancelled |\n\nValid transitions:\n\n| From → To | Allowed? |\n|-----------|----------|\n| `staged:ready` → `open` | Yes (launch) |\n| `staged:warnings` → `open` | Yes (launch) |\n| `staged:*` → `closed` | Yes (cancel) |\n| `staged:ready` ↔ `staged:warnings` | Yes (re-stage) |\n| `open` → `closed` | Yes |\n| `closed` → `open` | Yes (reopen) |\n| `open` → `staged:*` | **No** |\n| `closed` → `staged:*` | **No** |\n\n### Error vs warning classification\n\n**Errors** (fatal — prevent convoy creation):\n\n| Category | Trigger | Fix |\n|----------|---------|-----|\n| `cycle` | Cycle detected in execution edges | Remove one blocking dep in the cycle |\n| `no-rig` | Slingable bead has no rig (prefix not in routes.jsonl) | Add routes.jsonl entry |\n\n**Warnings** (non-fatal — convoy created as `staged:warnings`):\n\n| Category | Trigger |\n|----------|---------|\n| `orphan` | Slingable task with no blocking deps in either direction (epic input only) |\n| `blocked-rig` | Bead targets a parked or docked rig |\n| `cross-rig` | Bead on a different rig than the majority |\n| `capacity` | A wave has more than 5 tasks |\n| `missing-branch` | Sub-epic with children but no integration branch |\n\n### Launch behavior\n\n`gt convoy launch <convoy-id>` transitions a staged convoy to open and dispatches Wave 1:\n\n1. Validate convoy exists and is staged\n2. Transition status to `open`\n3. Re-read tracked beads, rebuild DAG, recompute waves\n5. Dispatch every task in Wave 1 via `gt sling <beadID> <rig>`\n6. Individual sling failures do NOT abort remaining dispatches\n7. Print dispatch results (checkmark/X per task)\n8. Subsequent waves handled automatically by the daemon\n\nIf `gt convoy launch` receives an epic or task list (not a staged convoy), it delegates to `gt convoy stage --launch` to stage-then-launch in one step.\n\n### Staged convoy daemon safety\n\n**Staged convoys are completely inert to the daemon.** Neither feed path processes them:\n\n- **Event-driven feeder:** `isConvoyStaged` check in `CheckConvoysForIssue` skips any convoy with `staged:*` status. Fail-open on read errors (assumes not staged → processes, which is safe since a read error on a non-existent convoy does nothing).\n- **Stranded scan:** `gt convoy stranded` only returns open convoys. Staged convoys never appear.\n\nThis means you can stage a convoy, review the wave plan, and launch when ready — no risk of premature dispatch.\n\n### Re-staging\n\nRunning `gt convoy stage <convoy-id>` on an existing staged convoy re-analyzes and updates:\n- Re-reads tracked beads from the convoy's `tracks` deps\n- Rebuilds DAG, re-detects errors/warnings, recomputes waves\n- Updates status via `bd update` (e.g., `staged:warnings` → `staged:ready` if warnings resolved)\n- Does NOT create a new convoy or re-add track dependencies\n\n## Testing convoy changes\n\n### Running tests\n\n```bash\n# Full convoy suite (all packages)\ngo test ./internal/convoy/... ./internal/daemon/... ./internal/cmd/... -count=1\n\n# By area:\ngo test ./internal/convoy/... -v -count=1                       # feeding logic\ngo test ./internal/daemon/... -v -count=1 -run TestConvoy       # ConvoyManager\ngo test ./internal/daemon/... -v -count=1 -run TestFeedFirstReady\ngo test ./internal/cmd/... -v -count=1 -run TestCreateBatchConvoy  # batch sling\ngo test ./internal/cmd/... -v -count=1 -run TestBatchSling\ngo test ./internal/cmd/... -v -count=1 -run TestResolveRig      # rig resolution\ngo test ./internal/daemon/... -v -count=1 -run Integration      # real beads stores\n\n# Stage-launch:\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyStage     # staging logic\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyLaunch    # launch + Wave 1 dispatch\ngo test ./internal/cmd/... -v -count=1 -run TestDetectCycles    # cycle detection\ngo test ./internal/cmd/... -v -count=1 -run TestComputeWaves    # wave computation\ngo test ./internal/cmd/... -v -count=1 -run TestBuildConvoyDAG  # DAG construction\n```\n\n### Key test invariants\n\n- `feedFirstReady` dispatches exactly 1 issue per call (first success wins)\n- `feedFirstReady` iterates past failures (sling exit 1 -> try next)\n- Parked rigs are skipped in both event poll and feedFirstReady\n- hq store is never skipped even if `isRigParked` returns true for everything\n- High-water marks prevent event reprocessing across poll cycles\n- First poll cycle is warm-up only (seeds marks, no processing)\n- `IsSlingableType(\"epic\") == false`, `IsSlingableType(\"task\") == true`, `IsSlingableType(\"\") == true`\n- `isIssueBlocked` is fail-open (store error -> not blocked)\n- `parent-child` deps are NOT blocking\n- Batch sling creates exactly 1 convoy for N beads (not N convoys)\n- `resolveRigFromBeadIDs` errors on mixed prefixes, unmapped prefixes, town-level prefixes\n- Cycles in blocking deps prevent staged convoy creation (exit non-zero, no side effects)\n- Wave 1 contains ONLY tasks with zero unsatisfied blocking deps among slingable nodes\n- Epics and non-slingable types are NEVER placed in waves\n- Daemon does NOT feed issues from `staged:*` convoys (both feed paths skip)\n- `staged:warnings` convoys can still be launched (warnings are informational)\n- Re-staging a convoy does NOT create duplicates (updates in place)\n- Launch dispatches ONLY Wave 1, not subsequent waves\n- Wave computation is deterministic (same input → same output, alphabetical sort within waves)\n\n### Deeper test engineering\n\nSee `docs/design/convoy/stage-launch/testing.md` for the full stage-launch test plan (105 tests across unit, integration, snapshot, and property tiers).\n\nSee `docs/design/convoy/testing.md` for the general convoy test plan covering failure modes, coverage gaps, harness scorecard, test matrix, and recommended test strategy.\n\n## Common pitfalls\n\n- **`parent-child` is never blocking.** This is a deliberate design choice, not a bug. Consistent with `bd ready`, beads SDK, and molecule step behavior.\n- **Batch sling errors on already-tracked beads.** If any bead is already in a convoy, the entire batch sling fails with conflict details. The user must resolve the conflict before proceeding.\n- **The stranded scan has its own blocked check.** `isReadyIssue` in cmd/convoy.go reads `t.Blocked` from issue details. `isIssueBlocked` in operations.go covers the event-driven path. Don't consolidate them without understanding both paths.\n- **Empty IssueType is slingable.** Beads default to type \"task\" when IssueType is unset. Treating empty as non-slingable would break all legacy beads.\n- **`isIssueBlocked` is fail-open.** Store errors assume not blocked. A transient Dolt error should not permanently stall a convoy -- the next feed cycle retries with fresh state.\n- **Explicit rig in batch sling is deprecated.** `gt sling beads... rig` still works but prints a warning. Prefer `gt sling beads...` with auto-resolution.\n- **Staged convoys are inert.** The daemon ignores them completely. Don't expect auto-feeding until you `gt convoy launch`.\n- **Review `staged:warnings` before launching.** Warnings are informational — fix and re-stage if possible, or launch anyway if they're acceptable.\n- **`gt convoy launch` on a non-staged input delegates to stage.** If you pass an epic or task list to `launch`, it runs `stage --launch` internally. Only an already-staged convoy gets the fast path.\n- **Wave computation is informational.** Waves are computed at stage time for display. Runtime dispatch uses the daemon's per-cycle `isIssueBlocked` checks, which are more dynamic.\n- **You cannot un-stage an open convoy.** Once launched, a convoy cannot return to staged status. The `open → staged:*` transition is rejected.\n\n## Key source files\n\n| File | What it does |\n|------|-------------|\n| `internal/convoy/operations.go` | Core feeding: `CheckConvoysForIssue`, `feedNextReadyIssue`, `IsSlingableType`, `isIssueBlocked` |\n| `internal/daemon/convoy_manager.go` | `ConvoyManager` goroutines: `runEventPoll` (5s), `runStrandedScan` (30s), `feedFirstReady` |\n| `internal/cmd/convoy.go` | All `gt convoy` subcommands + `findStrandedConvoys` type filter |\n| `internal/cmd/sling.go` | Batch detection at ~242, auto-rig-resolution, deprecation warning |\n| `internal/cmd/sling_batch.go` | `runBatchSling`, `resolveRigFromBeadIDs`, `allBeadIDs`, cross-rig guard |\n| `internal/cmd/sling_convoy.go` | `createAutoConvoy`, `createBatchConvoy`, `printConvoyConflict` |\n| `internal/cmd/convoy_stage.go` | `gt convoy stage`: DAG walking, wave computation, error/warning detection, staged convoy creation |\n| `internal/cmd/convoy_launch.go` | `gt convoy launch`: status transition, Wave 1 dispatch via `dispatchWave1` |\n| `internal/daemon/daemon.go` | Daemon startup -- creates `ConvoyManager` at ~237 |\n","frontmatter":{"name":"convoy","description":"The definitive guide for working with gastown's convoy system -- batch work tracking, event-driven feeding, stage-launch workflow, and dispatch safety guards. Use when writing convoy code, debugging convoy behavior, adding convoy features, testing convoy changes, or answering questions about how convoys work. Triggers on convoy, convoy manager, convoy feeding, dispatch, stranded convoy, feedFirstReady, feedNextReadyIssue, IsSlingableType, isIssueBlocked, CheckConvoysForIssue, gt convoy, gt sling, stage, launch, staged, wave."},"isInternal":false,"tokens":5049,"sizeBytes":21061},{"name":"backup.md","path":".claude/commands/backup.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/commands/backup.md","title":"Command: /backup","category":"command-prompt","format":"markdown","content":"---\ndescription: Run Dolt database backup — sync production DBs to backup remotes and iCloud\nallowed-tools: Bash(gt dolt status:*), Bash(dolt backup:*), Bash(dolt log:*), Bash(rsync:*), Bash(du:*), Bash(cat:*), Bash(mkdir:*), Bash(timeout:*), Bash(gt escalate:*), Bash(ls:*)\nargument-hint: [--skip-offsite]\n---\n\n# Dolt Backup\n\nSync production Dolt databases to filesystem backups with smart change detection.\nRuns the same cycle as `mol-dog-backup` / the `dolt-backup` plugin.\n\nArguments: $ARGUMENTS\nIf `--skip-offsite` is passed, skip the iCloud rsync step.\n\n## Configuration\n\n```\nDOLT_DATA_DIR=~/gt/.dolt-data\nBACKUP_DIR=~/gt/.dolt-backup\nICLOUD_DIR=~/Library/Mobile Documents/com~apple~CloudDocs/gt-dolt-backup\nPROD_DBS: auto-discovered (databases with <name>-backup remotes)\nBACKUP_TIMEOUT=120s per database\nHANG_THRESHOLD=30s for server ping\nDOLT_PORT=3307\n```\n\n## Execution Steps\n\n### Step 1: Verify Dolt server is responsive\n\n```bash\ngt dolt status\n```\n\nAlso ping directly to detect hangs:\n\n```bash\ntimeout 30 dolt sql --host 127.0.0.1 --port 3307 --user root --password \"\" \\\n  --no-tls -q \"SELECT 1\" --result-format csv\n```\n\nIf the ping hangs (takes > 30s) or fails:\n```bash\ngt escalate \"dolt-backup: Dolt server hung or unreachable\" -s CRITICAL\n```\nSTOP — do not attempt backups against a hung server.\n\n### Step 2: Discover databases with backup remotes\n\nList directories in `~/gt/.dolt-data/` and check each for a `<name>-backup` remote:\n\n```bash\nls ~/gt/.dolt-data/\n```\n\nFor each directory (skip dotfiles):\n```bash\ncd ~/gt/.dolt-data/<name> && dolt backup\n```\n\nIf the output contains `<name>-backup`, include it in the backup list.\nExpected databases: `hq`, `beads`, `gastown`.\n\n### Step 3: Check each DB for changes and sync\n\nFor each database with a backup remote:\n\n**3a. Get current HEAD hash:**\n```bash\ncd ~/gt/.dolt-data/<name> && dolt log -n 1 --oneline | head -1 | cut -d' ' -f1\n```\n\n**3b. Compare against last backed-up hash:**\n```bash\ncat ~/gt/.dolt-backup/<name>/.last-backup-hash 2>/dev/null\n```\n\nIf hashes match and current hash is not \"unknown\", skip (unchanged).\n\n**3c. Sync if changed:**\n```bash\ncd ~/gt/.dolt-data/<name> && timeout 120 dolt backup sync <name>-backup\n```\n\n**3d. Record successful hash:**\n```bash\nmkdir -p ~/gt/.dolt-backup/<name>\necho \"<current_hash>\" > ~/gt/.dolt-backup/<name>/.last-backup-hash\n```\n\n**3e. Get backup size:**\n```bash\ndu -sh ~/gt/.dolt-backup/<name> 2>/dev/null | cut -f1\n```\n\n### Step 4: Offsite sync to iCloud Drive\n\nUnless `--skip-offsite` was specified:\n\n```bash\nmkdir -p ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup\nrsync -a --delete ~/gt/.dolt-backup/ ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup/\n```\n\nIf iCloud is unavailable, log and continue — not fatal.\n\n### Step 5: Report\n\nPrint a summary in this format:\n\n```\n## Backup Report\n\n**Databases synced**: N/M\n**Databases skipped** (unchanged): N\n**Databases failed**: N\n**Offsite sync**: ok | failed | skipped\n\n### Per Database\n- <name>: synced in Ns (<size>) | unchanged (<hash>) | FAILED: <error>\n\n### Failures\n<list or \"None\">\n```\n\nIf any database failed or server was hung:\n```bash\ngt escalate \"dolt-backup FAILED: <summary>\" -s HIGH\n```\n\nIf server was hung, use `-s CRITICAL` instead.\n","frontmatter":{"description":"Run Dolt database backup — sync production DBs to backup remotes and iCloud","allowed-tools":"Bash(gt dolt status:*), Bash(dolt backup:*), Bash(dolt log:*), Bash(rsync:*), Bash(du:*), Bash(cat:*), Bash(mkdir:*), Bash(timeout:*), Bash(gt escalate:*), Bash(ls:*)","argument-hint":["--skip-offsite"],"allowedTools":["Bash(gt","dolt","status:*),","Bash(dolt","backup:*),","Bash(dolt","log:*),","Bash(rsync:*),","Bash(du:*),","Bash(cat:*),","Bash(mkdir:*),","Bash(timeout:*),","Bash(gt","escalate:*),","Bash(ls:*)"]},"allowedTools":["Bash(gt","dolt","status:*),","Bash(dolt","backup:*),","Bash(dolt","log:*),","Bash(rsync:*),","Bash(du:*),","Bash(cat:*),","Bash(mkdir:*),","Bash(timeout:*),","Bash(gt","escalate:*),","Bash(ls:*)"],"isInternal":false,"tokens":969,"sizeBytes":3250},{"name":"patrol.md","path":".claude/commands/patrol.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/commands/patrol.md","title":"Command: /patrol","category":"command-prompt","format":"markdown","content":"---\ndescription: Run a patrol cycle for the current agent role (witness, deacon, or refinery)\nallowed-tools: Bash(gt patrol:*), Bash(gt hook:*), Bash(gt mail:*), Bash(gt nudge:*), Bash(gt peek:*), Bash(gt escalate:*), Bash(gt dolt status:*), Bash(bd :*), Bash(gt mol:*)\nargument-hint: [witness|deacon|refinery]\n---\n\n# Patrol\n\nRun one patrol cycle for the specified role. Patrol is a continuous monitoring\nloop — each invocation executes one cycle of the patrol formula.\n\nArguments: $ARGUMENTS\nIf no role specified, detect from current GT_ROLE environment variable.\n\n## Role Detection\n\n```bash\necho $GT_ROLE\n```\n\nMap to patrol type:\n- `*/witness` → witness patrol (`mol-witness-patrol`)\n- `*/deacon` or `*/deacon/*` → deacon patrol (`mol-deacon-patrol`)\n- `*/refinery` → refinery patrol (`mol-refinery-patrol`)\n- Explicit argument overrides detection\n\n## Patrol Entry Point\n\n```bash\ngt patrol new --role <role>\n```\n\nThis creates a hooked wisp with steps from the patrol formula.\nIf a patrol is already running (wisp exists on hook), resume it instead.\n\n## Witness Patrol Steps\n\nThe witness is the per-rig polecat supervisor. Execute in order:\n\n### 1. inbox-check\n```bash\ngt mail inbox\n```\nProcess any pending messages: POLECAT_DONE, MERGED, HELP, escalations.\nRead each with `gt mail read <id>` and take appropriate action.\n\n### 2. process-cleanups\nCheck for cleanup wisps (dirty state from dead polecats):\n```bash\nbd list --status=open --label=cleanup --json\n```\nProcess each: verify git state, clean worktrees, close cleanup wisps.\n\n### 3. check-refinery\n```bash\ngt peek gastown/refinery\n```\nVerify refinery is alive and processing the merge queue.\nIf stuck, nudge: `gt nudge gastown/refinery \"Health check — are you processing?\"`\n\n### 4. survey-workers\nCheck all active polecats in the rig:\n```bash\ngt peek gastown/polecats\n```\nFor each active polecat:\n- Check if session is alive (has recent activity)\n- Check if work is progressing (commits, bead updates)\n- Detect zombies: session dead but agent_state says working\n- Detect stale spawns: spawning > 10 minutes\n\nNudge idle polecats:\n```bash\ngt nudge gastown/polecats/<name> \"Progress check — what's your status?\"\n```\n\n### 5. check-timer-gates\n```bash\nbd list --label=gate:timer --status=open --json\n```\nEvaluate any timer-based gates that may have elapsed.\n\n### 6. check-swarm\nCheck for convoy/swarm completion across coordinated work:\n```bash\nbd list --label=convoy --status=open --json\n```\n\n### 7. patrol-cleanup\nClose completed patrol wisps, update metrics.\n\n### 8. context-check\nCheck remaining context budget. If approaching limit:\n```bash\ngt handoff -s \"Patrol cycling\" -m \"Patrol cycle N complete, cycling for fresh context\"\n```\n\n### 9. loop-or-exit\nReport cycle results and spawn next cycle:\n```bash\ngt patrol report --summary \"<cycle summary>\" --steps \"inbox:OK,cleanup:OK,...\"\n```\n\n## Deacon Patrol Steps\n\nThe deacon is the town-wide daemon monitor. Key steps:\n\n1. **inbox-check** — Process callbacks from witnesses, refineries, polecats\n2. **trigger-pending-spawns** — Launch queued polecat spawns\n3. **gate-evaluation** — Check async gates (timer, dependency)\n4. **dispatch-gated-molecules** — Release molecules whose gates cleared\n5. **check-convoy-completion** — Track multi-rig coordinated work\n6. **health-scan** — Check Dolt health (`gt dolt status`), agent health\n7. **zombie-scan** — Find dead sessions, orphaned wisps\n8. **plugin-run** — Execute enabled plugins (backup, reaper, etc.)\n9. **dog-pool-maintenance** — Manage utility worker pool\n10. **orphan-check** — Find orphaned test databases (`gt dolt cleanup`)\n11. **session-gc** — Clean up dead session artifacts\n12. **patrol-cleanup** — Close completed wisps, update metrics\n13. **context-check** — Check context budget, handoff if needed\n14. **loop-or-exit** — Report and spawn next cycle\n\n## Refinery Patrol Steps\n\nThe refinery processes the merge queue sequentially:\n\n1. **inbox-check** — Look for MERGE_READY messages from witness\n2. **queue-scan** — List pending MRs in merge queue\n3. **process-branch** — Fetch and rebase next MR branch onto target\n4. **run-tests** — Execute configured gate suite on rebased branch\n5. **handle-failures** — On test failure: bisect, isolate culprit, notify\n6. **merge-push** — Fast-forward push to main: `git push origin temp:main`\n7. **notify** — Send MERGED mail to witness immediately after push\n8. **cleanup** — Close MR bead, delete remote branch, archive mail\n9. **context-check** — Check context budget\n10. **loop-or-exit** — Report and spawn next cycle\n\n## Cycle Completion\n\nEach cycle ends with:\n```bash\ngt patrol report --summary \"<what happened>\" --steps \"<step1:OK,step2:SKIP,...>\"\n```\n\nThis closes the current patrol wisp and spawns the next cycle automatically.\n","frontmatter":{"description":"Run a patrol cycle for the current agent role (witness, deacon, or refinery)","allowed-tools":"Bash(gt patrol:*), Bash(gt hook:*), Bash(gt mail:*), Bash(gt nudge:*), Bash(gt peek:*), Bash(gt escalate:*), Bash(gt dolt status:*), Bash(bd :*), Bash(gt mol:*)","argument-hint":["witness|deacon|refinery"],"allowedTools":["Bash(gt","patrol:*),","Bash(gt","hook:*),","Bash(gt","mail:*),","Bash(gt","nudge:*),","Bash(gt","peek:*),","Bash(gt","escalate:*),","Bash(gt","dolt","status:*),","Bash(bd",":*),","Bash(gt","mol:*)"]},"allowedTools":["Bash(gt","patrol:*),","Bash(gt","hook:*),","Bash(gt","mail:*),","Bash(gt","nudge:*),","Bash(gt","peek:*),","Bash(gt","escalate:*),","Bash(gt","dolt","status:*),","Bash(bd",":*),","Bash(gt","mol:*)"],"isInternal":false,"tokens":1233,"sizeBytes":4804},{"name":"reaper.md","path":".claude/commands/reaper.md","rawUrl":"https://raw.githubusercontent.com/gastownhall/gastown/HEAD/.claude/commands/reaper.md","title":"Command: /reaper","category":"command-prompt","format":"markdown","content":"---\ndescription: Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases\nallowed-tools: Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*)\nargument-hint: [--dry-run]\n---\n\n# Wisp Reaper\n\nReap stale wisps and close stale issues across all production Dolt databases.\nRuns the same cycle as `mol-dog-reaper` but directly, without Dog dispatch.\n\nArguments: $ARGUMENTS\nIf `--dry-run` is passed, report counts without making changes.\n\n## Configuration Defaults\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| max_age | 24h | Wisps older than this are reaped (closed) |\n| purge_age | 72h | Closed wisps older than this are purged (deleted) |\n| stale_issue_age | 168h | Issues stale longer than this are auto-closed |\n| mail_delete_age | 72h | Closed mail older than this is purged |\n| alert_threshold | 3000 | Open wisp count that triggers escalation |\n| dolt_port | 3307 | Dolt server port |\n\n## Execution Steps\n\n### Step 1: Verify Dolt server health\n\n```bash\ngt dolt status\n```\n\nIf the server is unhealthy or unreachable, STOP and escalate:\n```bash\ngt escalate \"Reaper blocked: Dolt server unhealthy\" -s HIGH\n```\n\n### Step 2: Discover databases\n\n```bash\ngt reaper databases --json\n```\n\nThis lists all production databases on the Dolt server.\nExpected databases: `hq`, `beads`, `gastown` (and any rig-specific DBs).\n\n### Step 3: Scan each database for candidates\n\nFor each database returned in Step 2:\n\n```bash\ngt reaper scan --db=<name> --port=3307 \\\n  --max-age=24h --purge-age=72h \\\n  --mail-age=72h --stale-age=168h \\\n  --json\n```\n\nInspect the JSON output:\n- `reap_candidates`: wisps eligible for closing\n- `purge_candidates`: closed wisps eligible for deletion\n- `open_wisps`: total open wisp count\n- `anomalies`: array of detected problems\n\nIf `open_wisps` exceeds 3000 across all databases, note for escalation.\nIf no candidates found across all databases, report \"nothing to reap\" and stop.\n\n### Step 4: Reap stale wisps\n\nFor each database with reap candidates:\n\n```bash\ngt reaper reap --db=<name> --port=3307 --max-age=24h [--dry-run] --json\n```\n\n**IMPORTANT**: Scan/reap count mismatch is NORMAL (witness closes wisps concurrently).\nDo NOT escalate scan > reap mismatches. Only escalate actual errors.\n\n### Step 5: Purge old closed wisps and mail\n\nFor each database with purge candidates:\n\n```bash\ngt reaper purge --db=<name> --port=3307 \\\n  --purge-age=72h --mail-age=72h [--dry-run] --json\n```\n\nWatch for `dolt_commit_failed` anomalies — purged data may not persist.\n\n### Step 6: Auto-close stale issues\n\nFor each database with stale candidates:\n\n```bash\ngt reaper auto-close --db=<name> --port=3307 \\\n  --stale-age=168h [--dry-run] --json\n```\n\nAuto-close NEVER touches: P0/P1 issues, epics, or issues with active dependencies.\n\n### Step 7: Report\n\nPrint a summary in this format:\n\n```\n## Reaper Report\n\n**Databases scanned**: N\n**Wisps reaped**: N (stale open wisps closed)\n**Wisps purged**: N (old closed wisps deleted)\n**Mail purged**: N (old closed mail deleted)\n**Issues auto-closed**: N (stale issues past 168h)\n**Open wisps remaining**: N\n**Anomalies**: <list or \"none\">\n```\n\nIf anomalies were found:\n```bash\ngt escalate \"Reaper anomalies detected\" -s MEDIUM -m \"<anomaly details>\"\n```\n","frontmatter":{"description":"Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases","allowed-tools":"Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*)","argument-hint":["--dry-run"],"allowedTools":["Bash(gt","reaper:*),","Bash(gt","escalate:*),","Bash(gt","dolt","status:*)"]},"allowedTools":["Bash(gt","reaper:*),","Bash(gt","escalate:*),","Bash(gt","dolt","status:*)"],"isInternal":false,"tokens":889,"sizeBytes":3283}],"systemPromptSnippet":"<yakaai_skills repo=\"gastownhall/gastown\">\n<!-- File: AGENTS.md (Tokens: ~1519 | Category: root-instruction) -->\n# Agent Instructions\n\nSee **CLAUDE.md** for complete agent context and instructions.\n\nThis file exists for compatibility with tools that look for AGENTS.md.\n\n> **Recovery**: Run `gt prime` after compaction, clear, or new session\n\nFull context is injected by `gt prime` at session start.\n\n<!-- beads-agent-instructions-v2 -->\n\n---\n\n## Beads Workflow Integration\n\nThis project uses [beads](https://github.com/steveyegge/beads) for issue tracking. Issues live in `.beads/` and are tracked in git.\n\nTwo CLIs: **bd** (issue CRUD) and **bv** (graph-aware triage, read-only).\n\n### bd: Issue Management\n\n```bash\nbd ready              # Unblocked issues ready to work\nbd list --status=open # All open issues\nbd show <id>          # Full details with dependencies\nbd create --title=\"...\" --type=task --priority=2\nbd update <id> --status=in_progress\nbd close <id>         # Mark complete\nbd close <id1> <id2>  # Close multiple\nbd dep add <a> <b>    # a depends on b\nbd sync               # Sync with git\n```\n\n### bv: Graph Analysis (read-only)\n\n**NEVER run bare `bv`** — it launches interactive TUI. Always use `--robot-*` flags:\n\n```bash\nbv --robot-triage     # Ranked picks, quick wins, blockers, health\nbv --robot-next       # Single top pick + claim command\nbv --robot-plan       # Parallel execution tracks\nbv --robot-alerts     # Stale issues, cascades, mismatches\nbv --robot-insights   # Full graph metrics: PageRank, betweenness, cycles\n```\n\n### Workflow\n\n1. **Start**: `bd ready` (or `bv --robot-triage` for graph analysis)\n2. **Claim**: `bd update <id> --status=in_progress`\n3. **Work**: Implement the task\n4. **Complete**: `bd close <id>`\n5. **Sync**: `bd sync` at session end\n\n### Session Close Protocol\n\n```bash\ngit status            # Check what changed\ngit add <files>       # Stage code changes\nbd sync               # Commit beads changes\ngit commit -m \"...\"   # Commit code\nbd sync               # Commit any new beads changes\ngit push              # Push to remote\n```\n\n### Key Concepts\n\n- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (numbers only)\n- **Types**: task, bug, feature, epic, question, docs\n- **Dependencies**: `bd ready` shows only unblocked work\n\n<!-- end-beads-agent-instructions -->\n\n<!-- gastown-agent-instructions-v1 -->\n\n---\n\n## Gas Town Multi-Agent Communication\n\nThis workspace is part of a **Gas Town** multi-agent environment. You communicate\nwith other agents using `gt` commands — never by printing text or using raw tmux.\n\n### Nudging Agents (Immediate Delivery)\n\n`gt nudge` sends a message directly to another agent's active session:\n\n```bash\ngt nudge mayor \"Status update: PR review complete\"\ngt nudge laneassist/crew/dom \"Check your mail — PR ready for review\"\ngt nudge witness \"Polecat health check needed\"\ngt nudge refinery \"Merge queue has items\"\n```\n\n**Target formats:**\n- Role shortcuts: `mayor`, `deacon`, `witness`, `refinery`\n- Full path: `<rig>/crew/<name>`, `<rig>/polecats/<name>`\n\n**Important:** `gt nudge` is the ONLY way to send text to another agent's session.\nNever print \"Hey @name\" — the other agent cannot see your terminal output.\n\n### Sending Mail (Persistent Messages)\n\n`gt mail` sends messages that persist across session restarts:\n\n```bash\n# Reading\ngt mail inbox                    # List messages\ngt mail read <id>                # Read a specific message\n\n# Sending (use --stdin for multi-line content)\ngt mail send mayor/ -s \"Subject\" -m \"Short message\"\ngt mail send laneassist/crew/dom -s \"PR Review\" --stdin <<'BODY'\nMulti-line message content here.\nDetails about the PR and what to look for.\nBODY\ngt mail send --human -s \"Subject\" -m \"Message to overseer\"\n```\n\n### When to Use Which\n\n| Want to... | Command | Why |\n|------------|---------|-----|\n| Wake a sleeping agent | `gt nudge <target> \"msg\"` | Immediate delivery |\n| Send detailed task/info | `gt mail send <target> -s \"...\" --stdin` | Persists across restarts |\n| Both: send + wake | `gt mail send` then `gt nudge` | Mail carries payload, nudge wakes |\n\n### Context Recovery\n\nAfter compaction or new session, run `gt prime` to reload your full role context,\nidentity, and any pending work.\n\n```bash\ngt prime              # Full context reload\ngt hook               # Check for assigned work\ngt mail inbox         # Check for messages\n```\n\n<!-- end-gastown-agent-instructions -->\n\n<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->\n## Beads Issue Tracker\n\nThis project uses **bd (beads)** for issue tracking. Run `gt prime` to see full workflow context and commands.\n\n### Quick Reference\n\n```bash\nbd ready              # Find available work\nbd show <id>          # View issue details\nbd update <id> --claim  # Claim work\nbd close <id>         # Complete work\n```\n\n### Rules\n\n- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists\n- Run `gt prime` for detailed command reference and session close protocol\n- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files\n\n## Session Completion\n\n**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.\n\n**MANDATORY WORKFLOW:**\n\n1. **File issues for remaining work** - Create issues for anything that needs follow-up\n2. **Run quality gates** (if code changed) - Tests, linters, builds\n3. **Update issue status** - Close finished work, update in-progress items\n4. **PUSH TO REMOTE** - This is MANDATORY:\n   ```bash\n   git pull --rebase\n   bd dolt push\n   git push\n   git status  # MUST show \"up to date with origin\"\n   ```\n5. **Clean up** - Clear stashes, prune remote branches\n6. **Verify** - All changes committed AND pushed\n7. **Hand off** - Provide context for next session\n\n**CRITICAL RULES:**\n- Work is NOT complete until `git push` succeeds\n- NEVER stop before pushing - that leaves work stranded locally\n- NEVER say \"ready to push when you are\" - YOU must push\n- If push fails, resolve and retry until it succeeds\n<!-- END BEADS INTEGRATION -->\n\n<!-- File: internal/hooks/templates/copilot/copilot-instructions.md (Tokens: ~176 | Category: copilot-instructions) -->\n# Gas Town Agent Context\n\nYou are running inside Gas Town, a multi-agent workspace manager.\n\n## Startup Protocol\n\nOn session start or after compaction, run:\n```\ngt prime\n```\nThis loads your full role context, mail, and pending work.\n\n## Key Commands\n\n- `gt prime` - Load role context (run after compaction or new session)\n- `gt mol status` - Check your hooked work\n- `gt mail inbox` - Check for messages\n- `bd ready` - Find available work\n- `gt handoff` - Cycle to fresh session\n\n## Work Protocol\n\n1. Check hook: `gt mol status`\n2. If work is hooked, execute immediately (no waiting for confirmation)\n3. If hook empty, check mail: `gt mail inbox`\n4. Complete work, commit, and push before ending session\n\n<!-- File: .claude/skills/crew-commit/SKILL.md (Tokens: ~1444 | Category: anthropic-skill) -->\n---\nname: crew-commit\ndescription: >\n  Canonical commit workflow for Gas Town crew members: pre-flight checks,\n  branch creation, gt commit with agent identity, push, and PR creation.\n  Use when ready to commit and submit work for review.\nallowed-tools: \"Bash(git *), Bash(gt *), Bash(gh *)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# Crew Commit — Canonical Git Workflow\n\nThis skill guides crew members through the standard Gas Town commit workflow:\npre-flight → branch → stage → commit → push → PR.\n\n> **⚠️ NEVER commit directly to `main`.** All crew work goes through branches\n> and pull requests. The Refinery handles merges to main.\n\n## Usage\n\n```\n/crew-commit\n```\n\nRun this when you have changes ready to commit. The skill walks you through\neach step in order.\n\n---\n\n## Step 1: Pre-flight Checks\n\nBefore touching anything, sync with origin and verify your state.\n\n```bash\n# Fetch latest from origin\ngit fetch origin\n\n# Check current branch and status\ngit status\ngit branch --show-current\n\n# If you're on main, STOP — create a branch first (Step 2)\n```\n\n**If you're behind origin/main**, rebase now:\n\n```bash\ngit rebase origin/main\n```\n\nIf there are conflicts, resolve them carefully before proceeding.\nIf stuck on a rebase conflict, stop and get help rather than force-pushing.\n\n---\n\n## Step 2: Create a Feature Branch\n\n**If you're already on a feature branch**, skip to Step 3.\n\nBranch naming convention: `<type>/<short-description>`\n\nTypes:\n- `feat/` — new feature\n- `fix/` — bug fix\n- `refactor/` — code restructuring\n- `docs/` — documentation only\n- `chore/` — maintenance, deps, config\n- `test/` — tests only\n\n```bash\n# Create and switch to feature branch\ngit checkout -b feat/my-feature-description\n\n# Or use the crew/<name> prefix for crew-specific branches\ngit checkout -b crew/<your-name>/description\n```\n\n---\n\n## Step 3: Submodule Warning\n\n**Check for submodules before staging.** Accidentally committing a submodule\npointer change causes cascading failures for other crew members.\n\n```bash\n# Check if repo has submodules\ncat .gitmodules 2>/dev/null || echo \"(no submodules)\"\n\n# Check for dirty submodule state\ngit submodule status 2>/dev/null\n```\n\n**Common submodule paths to watch:** `shared/`, `config/`, `vendor/`\n\nIf you see changes in submodule directories:\n- Do NOT `git add shared/` or `git add config/` unless you intentionally\n  bumped the submodule pointer\n- Submodule pointer changes should be explicit and deliberate\n- When in doubt, ask before including submodule changes\n\n---\n\n## Step 4: Stage Your Changes\n\nPrefer staging specific files over `git add .` or `git add -A`.\n\n```bash\n# Review what changed\ngit diff\ngit status\n\n# Stage specific files (preferred)\ngit add src/myfile.go tests/myfile_test.go\n\n# If you need to stage all intentional changes and have verified no secrets:\ngit add -p    # Interactive staging — review each hunk\n```\n\n**Before staging, verify:**\n- [ ] No `.env` files, API keys, or credentials\n- [ ] No debug prints or temporary test code\n- [ ] No unrelated changes mixed in\n- [ ] Submodule directories NOT accidentally staged (unless intentional)\n\n---\n\n## Step 5: Commit with gt commit\n\nUse `gt commit` instead of `git commit`. It automatically sets the correct\nagent identity (name + email) based on your `GT_ROLE`.\n\n```bash\ngt commit -m \"$(cat <<'EOF'\n<type>: <concise description of what and why>\n\n<optional body: context, motivation, or notable details>\nEOF\n)\"\n```\n\n**Commit message format:**\n- First line: `<type>: <subject>` (50 chars or less)\n- Types: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`\n- Use imperative mood: \"add feature\" not \"added feature\"\n- Body is optional but valuable for non-obvious changes\n\n**Good examples:**\n```\nfeat: add retry logic to webhook delivery\nfix: prevent nil pointer when session token expires\ndocs: clarify crew commit workflow in CONTRIBUTING.md\n```\n\n---\n\n## Step 6: Push Branch to Origin\n\n```bash\ngit push origin <your-branch-name>\n\n# Or, if branch doesn't exist on remote yet:\ngit push -u origin <your-branch-name>\n```\n\n---\n\n## Step 7: Create Pull Request\n\n```bash\ngh pr create --title \"<type>: <concise description>\" \\\n  --body \"$(cat <<'EOF'\n## Summary\n\n- <what changed and why>\n\n## Test plan\n\n- [ ] <how to verify this works>\n\n## Notes\n\n<any context reviewers need>\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\nEOF\n)\"\n```\n\nAfter creating the PR, note the PR number from the output.\n\n---\n\n## Step 8: Notify (Optional)\n\nIf your work affects others or is high priority:\n\n```bash\nnotify \"PR ready: <brief description> — #<PR number>\"\n```\n\n---\n\n## Completion Checklist\n\n- [ ] Synced with origin/main (git fetch + rebase)\n- [ ] On a feature branch (NOT main)\n- [ ] Submodules NOT accidentally staged\n- [ ] Specific files staged (no secrets, no debug code)\n- [ ] Used `gt commit` (not `git commit`)\n- [ ] Branch pushed to origin\n- [ ] PR created via `gh pr create`\n\n---\n\n## Anti-Patterns\n\n| ❌ Don't | ✅ Do instead |\n|----------|--------------|\n| `git push origin main` | Push feature branch, create PR |\n| `git commit` directly | `gt commit` (sets agent identity) |\n| `git add .` blindly | Stage specific files, verify with `git status` |\n| Include `shared/` or `config/` without intent | Check `git submodule status` first |\n| Force-push without understanding why | Resolve the root cause |\n| Commit secrets or .env files | Always check `git diff` before staging |\n\n---\n\n## If You Get Stuck\n\n- **Rebase conflicts**: resolve carefully, then `git rebase --continue`\n- **Pushed wrong branch**: ask before force-pushing; usually `git push origin <branch>` is fine\n- **Need to undo last commit**: `git reset HEAD~1` (keeps changes staged)\n- **Committed to main by mistake**: stop immediately, ask for help\n\n<!-- File: .claude/skills/ghi-list/SKILL.md (Tokens: ~642 | Category: anthropic-skill) -->\n---\nname: ghi-list\ndescription: >\n  List GitHub issues in a formatted ASCII table. Supports filters like --state,\n  --assignee, --label. Use for issue triage and tracking workflows.\nallowed-tools: \"Bash(gh issue list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# GHI List - Formatted GitHub Issues Table\n\nDisplay GitHub issues in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/ghi-list [options]\n```\n\n## Options (passed to gh issue list)\n\n- `--state open|closed|all` - Filter by state (default: open)\n- `--assignee <user>` - Filter by assignee\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--author <user>` - Filter by author\n- `--milestone <name>` - Filter by milestone\n\n## Execution Steps\n\n1. Run `gh issue list` with any provided options plus `--json number,assignees,labels,title,state`\n2. Format output as an ASCII table using box-drawing characters\n3. Truncate titles to fit reasonable terminal width (~45 chars)\n4. Show first assignee only, or \"-\" if none\n5. Show first 2-3 labels abbreviated, or \"-\" if none\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌───────┬────────────┬─────────────────┬───────────────────────────────────────────────┬────────┐\n│ Issue │ Assignee   │ Labels          │ Title                                         │ State  │\n├───────┼────────────┼─────────────────┼───────────────────────────────────────────────┼────────┤\n│   372 │ max        │ enhancement     │ Create /pr-list and /ghi-list skills          │ OPEN   │\n│   371 │ -          │ bug, priority   │ Fix null pointer in auth module               │ OPEN   │\n│   370 │ joe        │ -               │ Update documentation for new API              │ CLOSED │\n└───────┴────────────┴─────────────────┴───────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align issue numbers\n- Left-align text columns\n- Pad columns consistently\n- For assignees: show login of first assignee, \"-\" if none\n- For labels: show comma-separated names (truncate if >17 chars)\n- Show count summary below table: \"**N issues** (M open, K closed)\"\n\n## Example Commands\n\n```bash\n# Default - open issues\ngh issue list --json number,assignees,labels,title,state\n\n# With filters\ngh issue list --state all --label bug --json number,assignees,labels,title,state\n```\n\n<!-- File: .claude/skills/pr-list/SKILL.md (Tokens: ~638 | Category: anthropic-skill) -->\n---\nname: pr-list\ndescription: >\n  List GitHub PRs in a formatted ASCII table. Supports filters like --state,\n  --author, --label. Use for PR review workflows and sheriff duties.\nallowed-tools: \"Bash(gh pr list:*)\"\nversion: \"1.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR List - Formatted Pull Request Table\n\nDisplay GitHub pull requests in a clean ASCII box-drawing table format.\n\n## Usage\n\n```\n/pr-list [options]\n```\n\n## Options (passed to gh pr list)\n\n- `--state open|closed|merged|all` - Filter by state (default: open)\n- `--author <user>` - Filter by author\n- `--label <label>` - Filter by label (can repeat)\n- `--limit <n>` - Max items to fetch (default: 30)\n- `--assignee <user>` - Filter by assignee\n- `--draft` - Show only drafts\n- `--all-reviews` - Include PRs with CHANGES_REQUESTED (excluded by default)\n\n## Execution Steps\n\n1. Run `gh pr list` with any provided options plus `--json number,author,title,state,isDraft,reviewDecision`\n2. **Filter out PRs with reviewDecision=\"CHANGES_REQUESTED\"** (unless `--all-reviews` specified)\n3. Format output as an ASCII table using box-drawing characters\n4. Truncate titles to fit reasonable terminal width (~50 chars)\n5. Truncate author names if needed (~18 chars)\n6. Show state as OPEN/CLOSED/MERGED/DRAFT, append \"(changes requested)\" if filtered with --all-reviews\n\n## Output Format\n\nUse this exact table style with box-drawing characters:\n\n```\n┌─────┬────────────────────┬───────────────────────────────────────────────────┬────────┐\n│  PR │ Author             │ Title                                             │ State  │\n├─────┼────────────────────┼───────────────────────────────────────────────────┼────────┤\n│ 123 │ username           │ feat: add new feature for something               │ OPEN   │\n│ 122 │ another-user       │ fix: resolve bug in component                     │ DRAFT  │\n└─────┴────────────────────┴───────────────────────────────────────────────────┴────────┘\n```\n\n## Table Requirements\n\n- Use Unicode box-drawing: `┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ │ ─`\n- Right-align PR numbers\n- Left-align text columns\n- Pad columns consistently\n- Show count summary below table: \"**N open PRs** (M drafts)\"\n\n## Example Commands\n\n```bash\n# Default - open PRs (excludes CHANGES_REQUESTED)\ngh pr list --json number,author,title,state,isDraft,reviewDecision\n\n# With filters\ngh pr list --state all --author boshu2 --json number,author,title,state,isDraft,reviewDecision\n```\n\n<!-- File: .claude/skills/pr-sheriff/skill.md (Tokens: ~1491 | Category: anthropic-skill) -->\n---\nname: pr-sheriff\ndescription: >\n  PR Sheriff workflow: triage PRs into easy-wins and crew assignments.\n  Prints recommendations inline - does NOT post to GitHub.\nallowed-tools: \"Bash(gh pr *), Bash(git *), Bash(gt *), Bash(bd *), Bash(cat *)\"\nversion: \"2.0.0\"\nauthor: \"Gas Town\"\n---\n\n# PR Sheriff - Triage and Review Workflow\n\nThis skill delegates to the `mol-pr-sheriff-patrol` formula, which lives at\n`$GT_ROOT/.beads/formulas/mol-pr-sheriff-patrol.formula.toml` and is shared\nacross all Gas Town rigs (gastown, beads, etc.).\n\n## Repo Scope\n\nThis rig (gastown/crew/max) is responsible for **steveyegge/gastown only**.\nThe beads repo (steveyegge/beads) is handled by beads/crew/emma.\nDo NOT discover or triage PRs from repos outside your scope.\n\nWhen loading the shared config, filter the repo list to only `steveyegge/gastown`.\n\n## Usage\n\n```\n/pr-sheriff [repo]\n```\n\n- `repo` - Optional. If provided, overrides the default scope.\n  If omitted, scan only `steveyegge/gastown` (this rig's scope).\n\n## How to Execute\n\n**1. Load the config:**\n```bash\ncat $GT_ROOT/.beads/pr-sheriff-config.json\n```\n\nThis contains crew mappings per repo and contributor policies\n(trust tiers, firewalled contributors, bot auto-merge rules).\n**Only scan repos within your scope** (see Repo Scope above).\n\n**2. Follow the formula steps in order:**\n```bash\ngt formula show mol-pr-sheriff-patrol\n```\n\nThe formula defines a 7-step workflow:\n\n| Step | What it does |\n|------|-------------|\n| load-config | Load pr-sheriff-config.json, establish repo list |\n| discover-prs | Find open PRs needing review across all repos |\n| triage-batch | Categorize all PRs in one pass (preserves cross-PR context) |\n| merge-easy-wins | Merge approved easy-wins via `gh pr merge` |\n| dispatch-crew-reviews | Nudge crew for NEEDS-CREW PRs |\n| dispatch-deep-reviews | Nudge crew for NEEDS-HUMAN PRs (full evaluation framework) |\n| collect-results | Gather crew review nudge-backs |\n| interactive-review | Walk through remaining NEEDS-HUMAN PRs with overseer |\n| summarize | Print patrol summary |\n\n**3. For each step, read the full description:**\n```bash\ngt formula show mol-pr-sheriff-patrol  # Shows all steps with descriptions\n```\n\n## Key References\n\n- **Patrol formula:** `mol-pr-sheriff-patrol` (town-level)\n- **Crew review formula:** `mol-pr-crew-review` (dispatched to crew)\n- **Deep review formula:** `mol-pr-deep-review` (dispatched for NEEDS-HUMAN)\n- **Config:** `$GT_ROOT/.beads/pr-sheriff-config.json`\n\n## Contributor Policy Tiers\n\nLoaded from config. Current tiers:\n\n| Tier | Handling |\n|------|----------|\n| bot-trusted | Auto-merge if CI passes (e.g., dependabot) |\n| community | Normal triage — easy-win / crew / deep review |\n| firewalled | Always NEEDS-HUMAN, never auto-merge, deep review required |\n\n## Category Decision Tree\n\n```\nDraft? → SKIP\nContributor firewalled? → NEEDS-HUMAN (deep review)\nDependabot patch bump + CI green? → EASY-WIN\n<50 lines, obvious bug/doc/test fix? → EASY-WIN\nSecurity/architecture/API change? → NEEDS-HUMAN\nMulti-concern PR? → NEEDS-HUMAN\n100+ lines new feature? → NEEDS-CREW or NEEDS-HUMAN\nEverything else → NEEDS-CREW\n```\n\n## Deep Review Evaluation Framework (NEEDS-HUMAN)\n\nThe deep review formula (mol-pr-deep-review) applies six lenses:\n\n1. **Plugin/integration fit** — core vs plugin/formula/integration?\n2. **Tech-debt weight** — complexity justified by user breadth?\n3. **Contributor track record** — first-time, repeat, or firewalled?\n4. **ZFC compliance** — structural checks, not string heuristics?\n5. **Problem validity + solution fit** — real problem, right solution?\n6. **Splitability** — can good parts be cherry-picked from bad?\n\nFinal verdicts: MERGE | CHERRY-PICK | REWORK | REIMPLEMENT | CLOSE\n\n## Output Format\n\nFor each PR, print a recommendation block:\n\n```\n### PR #<num>: <title>\nAuthor: <login> | +<additions>/-<deletions> | <changedFiles> files\n\n**Category**: EASY-WIN | NEEDS-CREW | NEEDS-HUMAN | SKIP\n\n**Analysis**:\n<1-3 sentences explaining the change and why it fits this category>\n\n**Recommendation**:\n<specific action>\n```\n\n## Summary Output\n\n```\n## PR Sheriff Patrol Summary — <date>\n\n**Easy-wins merged**: N\n**Crew-reviewed and merged**: N\n**Sent back for rework**: N\n**Closed**: N\n**Still pending**: N\n```\n\n## Dispatching Work: Use Ephemeral Beads\n\nWhen creating beads to track fix-merge work for polecats or crew, **use\nephemeral beads (wisps)** rather than persistent beads. PR review/fix-merge\ntasks are orchestration scaffolding — they exist to give a polecat something\nto hook and track, not to create a permanent record.\n\nEphemeral beads are the right trade-off: they give polecats and crew trackable\nwork items without polluting Dolt's permanent ledger with one-off orchestration\nnoise. If/when beads are exported to permanent ledgers, review-task wisps won't\nclutter the history.\n\n```bash\n# Ephemeral bead for fix-merge dispatch\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review \\\n  --wisp-type patrol\n\n# vs persistent (avoid for orchestration work)\nbd new -t task \"Fix-merge PR #1234: description\" -p 2 -l pr-review\n```\n\nThe `--wisp-type patrol` flag marks it as ephemeral orchestration work that\nthe reaper will eventually clean up. The polecat/crew member can still hook it,\nwork it, and close it normally.\n\n## CRITICAL Rules\n\n- All output is printed inline. Do NOT post comments to GitHub.\n- The overseer decides what gets posted externally.\n- Contributor-friendly: help contributors get to the finish line.\n- Use `Co-authored-by` trailer when fixing up contributor work.\n\n<!-- File: .cursor/skills/gas-town-cursor/SKILL.md (Tokens: ~483 | Category: anthropic-skill) -->\n---\nname: gas-town-cursor\ndescription: >\n  Develop and operate Gas Town with the Cursor agent preset (cursor-agent CLI):\n  gt flags, hooks at .cursor/hooks.json, session resume, and how this repo differs from README marketing copy.\n---\n\n# Gas Town + Cursor Agent CLI\n\nUse this skill when working **in this repository** with the **`cursor`** agent preset (CLI binary **`cursor-agent`**, sometimes symlinked as **`agent`**).\n\n## Concepts\n\n| Name | Meaning |\n|------|---------|\n| **Preset `cursor`** | Gas Town agent id (`GT_AGENT=cursor`). Config lives in `internal/config/agents.go` (`AgentCursor`). |\n| **Binary `cursor-agent`** | The Cursor Agent CLI process name for pane/detection; install docs may also symlink `agent` → same binary. |\n| **Hooks** | Cursor lifecycle hooks are configured at **`.cursor/hooks.json`** (see preset `HooksSettingsFile`). |\n\n## Essential commands\n\n- Build / run `gt` from repo root: `make build` or `go run ./cmd/gt …`.\n- Point a session at the Cursor preset: spawn or config so the runtime uses **`--agent cursor`** (or set **`GT_AGENT=cursor`** where applicable).\n- After changing hooks or settings: **`gt up --restore`** (or role-specific restart) so agents reload config.\n\n## Resume semantics\n\nThe Cursor preset uses **`--resume <chatId>`** style resume (`ResumeStyle: flag`). Session identity is not carried in a dedicated env var in the same way as Claude’s `CLAUDE_SESSION_ID`; follow the preset fields in `internal/config/agents.go` (`ResumeFlag`, `ResumeStyle`).\n\n## Read more\n\n- Beads / plan handoff: [`docs/cursor-runtime-beads-tasks.md`](../../../docs/cursor-runtime-beads-tasks.md)\n- Agent instructions for automation: [`AGENTS.md`](../../../AGENTS.md) and [`CLAUDE.md`](../../../CLAUDE.md) (project-wide, not Cursor-only)\n\n## Boundary\n\nProject **README** is user-facing product overview; **`.cursor/README.md`** is Cursor-specific onboarding for this repo. Prefer linking to those files instead of duplicating long install steps inside skills.\n\n<!-- File: docs/skills/convoy/SKILL.md (Tokens: ~5049 | Category: anthropic-skill) -->\n---\nname: convoy\ndescription: The definitive guide for working with gastown's convoy system -- batch work tracking, event-driven feeding, stage-launch workflow, and dispatch safety guards. Use when writing convoy code, debugging convoy behavior, adding convoy features, testing convoy changes, or answering questions about how convoys work. Triggers on convoy, convoy manager, convoy feeding, dispatch, stranded convoy, feedFirstReady, feedNextReadyIssue, IsSlingableType, isIssueBlocked, CheckConvoysForIssue, gt convoy, gt sling, stage, launch, staged, wave.\n---\n\n# Gastown Convoy System\n\nThe convoy system tracks batches of work across rigs. A convoy is a bead that `tracks` other beads via dependencies. The daemon monitors close events and feeds the next ready issue when one completes.\n\n## Architecture\n\n```\n+================================ CREATION =================================+\n|                                                                            |\n|   gt sling <beads>      gt convoy create ...     gt convoy stage <epic>    |\n|        |  (auto-convoy)       |  (explicit)            |  (validated)     |\n|        v                      v                        v                  |\n|   +-----------+          +-----------+         +----------------+         |\n|   |  status:  |          |  status:  |         |    status:     |         |\n|   |   open    |          |   open    |         | staged:ready   |         |\n|   +-----------+          +-----------+         | staged:warnings|         |\n|                                                +----------------+         |\n|                                                        |                  |\n|                                              gt convoy launch             |\n|                                                        |                  |\n|                                                        v                  |\n|                                                +----------------+         |\n|                                                |    status:     |         |\n|                                                |     open       |         |\n|                                                | (Wave 1 slung) |         |\n|                                                +----------------+         |\n|                                                                            |\n|   All paths produce: CONVOY (hq-cv-*)                                      |\n|                      tracks: issue1, issue2, ...                           |\n+============================================================================+\n              |                              |\n              v                              v\n+= EVENT-DRIVEN FEEDER (5s) =+   +=== STRANDED SCAN (30s) ===+\n|                              |   |                            |\n|   GetAllEventsSince (SDK)    |   |   findStranded             |\n|     |                        |   |     |                      |\n|     v                        |   |     v                      |\n|   close event detected       |   |   convoy has ready issues  |\n|     |                        |   |   but no active workers    |\n|     v                        |   |     |                      |\n|   CheckConvoysForIssue       |   |     v                      |\n|     |                        |   |   feedFirstReady           |\n|     v                        |   |   (iterates all ready)     |\n|   feedNextReadyIssue         |   |     |                      |\n|   (iterates all ready)       |   |     v                      |\n|     |                        |   |   gt sling <next-bead>     |\n|     v                        |   |   or closeEmptyConvoy     |\n|   gt sling <next-bead>       |   |                            |\n|                              |   +============================+\n+==============================+\n```\n\nThree creation paths (sling, create, stage), two feed paths, same safety guards:\n- **Event-driven** (`operations.go`): Polls beads stores every ~5s for close events. Calls `feedNextReadyIssue` which checks `IsSlingableType` + `isIssueBlocked` before dispatch. **Skips staged convoys** (`isConvoyStaged` check).\n- **Stranded scan** (`convoy_manager.go`): Runs every 30s. `feedFirstReady` iterates all ready issues. The ready list is pre-filtered by `IsSlingableType` in `findStrandedConvoys` (cmd/convoy.go). **Only sees open convoys** — staged convoys never appear.\n\n## Safety guards (the three rules)\n\nThese prevent the event-driven feeder from dispatching work it shouldn't:\n\n### 1. Type filtering (`IsSlingableType`)\n\nOnly leaf work items dispatch. Defined in `operations.go`:\n\n```go\nvar slingableTypes = map[string]bool{\n    \"task\": true, \"bug\": true, \"feature\": true, \"chore\": true,\n    \"\": true, // empty defaults to task\n}\n```\n\nEpics, sub-epics, convoys, decisions -- all skip. Applied in both `feedNextReadyIssue` (event path) and `findStrandedConvoys` (stranded path).\n\n### 2. Blocks dep checking (`isIssueBlocked`)\n\nIssues with unclosed `blocks`, `conditional-blocks`, or `waits-for` dependencies skip. `parent-child` is **not** blocking -- a child task dispatches even if its parent epic is open. This is consistent with `bd ready` and molecule step behavior.\n\nFail-open on store errors (assumes not blocked) to avoid stalling convoys on transient Dolt issues.\n\n### 3. Dispatch failure iteration\n\nBoth feed paths iterate past failures instead of giving up:\n- `feedNextReadyIssue`: `continue` on dispatch failure, try next ready issue\n- `feedFirstReady`: `for range ReadyIssues` with `continue` on skip/failure, `return` on first success\n\n## CLI commands\n\n### Stage and launch (validated creation)\n\n```bash\ngt convoy stage <epic-id>            # analyze deps, build DAG, compute waves, create staged convoy\ngt convoy stage gt-task1 gt-task2    # stage from explicit task list\ngt convoy stage hq-cv-abc            # re-stage existing staged convoy\ngt convoy stage <epic-id> --json     # machine-readable output\ngt convoy stage <epic-id> --launch   # stage + immediately launch if no errors\ngt convoy launch hq-cv-abc           # transition staged → open, dispatch Wave 1\ngt convoy launch <epic-id>           # stage + launch in one step (delegates to stage --launch)\n```\n\n### Create and manage\n\n```bash\ngt convoy create \"Auth overhaul\" gt-task1 gt-task2 gt-task3\ngt convoy add hq-cv-abc gt-task4\n```\n\n### Check and monitor\n\n```bash\ngt convoy check hq-cv-abc       # auto-closes if all tracked issues done\ngt convoy check                  # check all open convoys\ngt convoy status hq-cv-abc       # single convoy detail\ngt convoy list                   # all convoys\ngt convoy list --all             # include closed\n```\n\n### Find stranded work\n\n```bash\ngt convoy stranded               # ready work with no active workers\ngt convoy stranded --json        # machine-readable\n```\n\n### Close and land\n\n```bash\ngt convoy close hq-cv-abc --reason \"done\"\ngt convoy land hq-cv-abc         # cleanup worktrees + close\n```\n\n### Interactive TUI\n\n```bash\ngt convoy -i                     # opens interactive convoy browser\ngt convoy --interactive          # long form\n```\n\n## Batch sling behavior\n\n`gt sling <bead1> <bead2> <bead3>` creates **one convoy** tracking all beads. The rig is auto-resolved from the beads' prefixes (via `routes.jsonl`). The convoy title is `\"Batch: N beads to <rig>\"`. Each bead gets its own polecat, but they share a single convoy for tracking.\n\nThe convoy ID and merge strategy are stored on each bead, so `gt done` can find the convoy via the fast path (`getConvoyInfoFromIssue`).\n\n### Rig resolution\n\n- **Auto-resolve (preferred):** `gt sling gt-task1 gt-task2 gt-task3` -- resolves rig from the `gt-` prefix. All beads must resolve to the same rig.\n- **Explicit rig (deprecated):** `gt sling gt-task1 gt-task2 gt-task3 myrig` -- still works, prints a deprecation warning. If any bead's prefix doesn't match the explicit rig, errors with suggested actions.\n- **Mixed prefixes:** If beads resolve to different rigs, errors listing each bead's resolved rig and suggested actions (sling separately, or `--force`).\n- **Unmapped prefix:** If a prefix has no route, errors with diagnostic info (`cat .beads/routes.jsonl | grep <prefix>`).\n\n### Conflict handling\n\nIf any bead is already tracked by another convoy, batch sling **errors** with detailed conflict info (which convoy, all beads in it with statuses, and 4 recommended actions). This prevents accidental double-tracking.\n\n```bash\n# Auto-resolve: one convoy, three polecats (preferred)\ngt sling gt-task1 gt-task2 gt-task3\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n\n# Explicit rig still works but prints deprecation warning\ngt sling gt-task1 gt-task2 gt-task3 gastown\n# -> Deprecation: gt sling now auto-resolves the rig from bead prefixes.\n# -> Created convoy hq-cv-xxxxx tracking 3 beads\n```\n\n## Stage-launch workflow\n\n> Implemented in [PR #1820](https://github.com/steveyegge/gastown/pull/1820). Depends on the feeder safety guards from [PR #1759](https://github.com/steveyegge/gastown/pull/1759). Design docs: `docs/design/convoy/stage-launch/prd.md`, `docs/design/convoy/stage-launch/testing.md`.\n\nThe stage-launch workflow is a two-phase convoy creation path that validates dependencies and computes wave dispatch order **before** any work is dispatched. This is the preferred path for epic delivery.\n\n### Input types\n\n`gt convoy stage` accepts three mutually exclusive input types:\n\n| Input | Example | Behavior |\n|-------|---------|----------|\n| Epic ID | `gt convoy stage bcc-nxk2o` | BFS walks entire parent-child tree, collects all descendants |\n| Task list | `gt convoy stage gt-t1 gt-t2 gt-t3` | Analyzes exactly those tasks |\n| Convoy ID | `gt convoy stage hq-cv-abc` | Re-reads tracked beads from existing staged convoy (re-stage) |\n\nMixed types (e.g., epic + task together) error. Multiple epics or multiple convoys error.\n\n### Processing pipeline\n\n```\n1. validateStageArgs     — reject empty/flag-like args\n2. bdShow each arg       — resolve bead types\n3. resolveInputKind      — classify Epic / Tasks / Convoy\n4. collectBeads          — gather BeadInfo + DepInfo (BFS for epic, direct for tasks)\n5. buildConvoyDAG        — construct in-memory DAG (nodes + edges)\n6. detectErrors          — cycle detection + missing rig checks\n7. detectWarnings        — orphans, parked rigs, cross-rig, capacity, missing branches\n8. categorizeFindings    — split into errors / warnings\n9. chooseStatus          — staged:ready, staged:warnings, or abort on errors\n10. computeWaves         — Kahn's algorithm (only when no errors)\n11. renderDAGTree        — print ASCII dependency tree\n12. renderWaveTable      — print wave dispatch plan\n13. createStagedConvoy   — bd create --type=convoy --status=<staged-status>\n```\n\n### Wave computation (Kahn's algorithm)\n\nOnly slingable types participate in waves: `task`, `bug`, `feature`, `chore`. Epics are excluded.\n\nExecution edges (create wave ordering):\n- `blocks`\n- `conditional-blocks`\n- `waits-for`\n\nNon-execution edges (ignored for wave ordering):\n- `parent-child` — hierarchy only\n- `related`, `tracks`, `discovered-from`\n\n**Algorithm:**\n1. Filter to slingable nodes only\n2. Calculate in-degree for each node (count BlockedBy edges to other slingable nodes)\n3. Peel loop: collect all nodes with in-degree 0 → Wave N; remove them; decrement neighbors; repeat\n4. Sort within each wave alphabetically for determinism\n\nOutput example:\n```\n  Wave   ID              Title                     Rig       Blocked By\n  ──────────────────────────────────────────────────────────────────────\n  1      bcc-nxk2o.1.1   Init scaffolding          bcc       —\n  2      bcc-nxk2o.1.2   Shared types              bcc       bcc-nxk2o.1.1\n  3      bcc-nxk2o.1.3   CLI wrapper               bcc       bcc-nxk2o.1.2\n\n  3 tasks across 3 waves (max parallelism: 1 in wave 1)\n```\n\n### Convoy status model\n\nFour statuses with defined transitions:\n\n| Status | Meaning |\n|--------|---------|\n| `staged:ready` | Validated, no errors or warnings, ready to launch |\n| `staged:warnings` | Validated, no errors but has warnings. Fix and re-stage, or launch anyway. |\n| `open` | Active — daemon feeds work as beads close |\n| `closed` | Complete or cancelled |\n\nValid transitions:\n\n| From → To | Allowed? |\n|-----------|----------|\n| `staged:ready` → `open` | Yes (launch) |\n| `staged:warnings` → `open` | Yes (launch) |\n| `staged:*` → `closed` | Yes (cancel) |\n| `staged:ready` ↔ `staged:warnings` | Yes (re-stage) |\n| `open` → `closed` | Yes |\n| `closed` → `open` | Yes (reopen) |\n| `open` → `staged:*` | **No** |\n| `closed` → `staged:*` | **No** |\n\n### Error vs warning classification\n\n**Errors** (fatal — prevent convoy creation):\n\n| Category | Trigger | Fix |\n|----------|---------|-----|\n| `cycle` | Cycle detected in execution edges | Remove one blocking dep in the cycle |\n| `no-rig` | Slingable bead has no rig (prefix not in routes.jsonl) | Add routes.jsonl entry |\n\n**Warnings** (non-fatal — convoy created as `staged:warnings`):\n\n| Category | Trigger |\n|----------|---------|\n| `orphan` | Slingable task with no blocking deps in either direction (epic input only) |\n| `blocked-rig` | Bead targets a parked or docked rig |\n| `cross-rig` | Bead on a different rig than the majority |\n| `capacity` | A wave has more than 5 tasks |\n| `missing-branch` | Sub-epic with children but no integration branch |\n\n### Launch behavior\n\n`gt convoy launch <convoy-id>` transitions a staged convoy to open and dispatches Wave 1:\n\n1. Validate convoy exists and is staged\n2. Transition status to `open`\n3. Re-read tracked beads, rebuild DAG, recompute waves\n5. Dispatch every task in Wave 1 via `gt sling <beadID> <rig>`\n6. Individual sling failures do NOT abort remaining dispatches\n7. Print dispatch results (checkmark/X per task)\n8. Subsequent waves handled automatically by the daemon\n\nIf `gt convoy launch` receives an epic or task list (not a staged convoy), it delegates to `gt convoy stage --launch` to stage-then-launch in one step.\n\n### Staged convoy daemon safety\n\n**Staged convoys are completely inert to the daemon.** Neither feed path processes them:\n\n- **Event-driven feeder:** `isConvoyStaged` check in `CheckConvoysForIssue` skips any convoy with `staged:*` status. Fail-open on read errors (assumes not staged → processes, which is safe since a read error on a non-existent convoy does nothing).\n- **Stranded scan:** `gt convoy stranded` only returns open convoys. Staged convoys never appear.\n\nThis means you can stage a convoy, review the wave plan, and launch when ready — no risk of premature dispatch.\n\n### Re-staging\n\nRunning `gt convoy stage <convoy-id>` on an existing staged convoy re-analyzes and updates:\n- Re-reads tracked beads from the convoy's `tracks` deps\n- Rebuilds DAG, re-detects errors/warnings, recomputes waves\n- Updates status via `bd update` (e.g., `staged:warnings` → `staged:ready` if warnings resolved)\n- Does NOT create a new convoy or re-add track dependencies\n\n## Testing convoy changes\n\n### Running tests\n\n```bash\n# Full convoy suite (all packages)\ngo test ./internal/convoy/... ./internal/daemon/... ./internal/cmd/... -count=1\n\n# By area:\ngo test ./internal/convoy/... -v -count=1                       # feeding logic\ngo test ./internal/daemon/... -v -count=1 -run TestConvoy       # ConvoyManager\ngo test ./internal/daemon/... -v -count=1 -run TestFeedFirstReady\ngo test ./internal/cmd/... -v -count=1 -run TestCreateBatchConvoy  # batch sling\ngo test ./internal/cmd/... -v -count=1 -run TestBatchSling\ngo test ./internal/cmd/... -v -count=1 -run TestResolveRig      # rig resolution\ngo test ./internal/daemon/... -v -count=1 -run Integration      # real beads stores\n\n# Stage-launch:\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyStage     # staging logic\ngo test ./internal/cmd/... -v -count=1 -run TestConvoyLaunch    # launch + Wave 1 dispatch\ngo test ./internal/cmd/... -v -count=1 -run TestDetectCycles    # cycle detection\ngo test ./internal/cmd/... -v -count=1 -run TestComputeWaves    # wave computation\ngo test ./internal/cmd/... -v -count=1 -run TestBuildConvoyDAG  # DAG construction\n```\n\n### Key test invariants\n\n- `feedFirstReady` dispatches exactly 1 issue per call (first success wins)\n- `feedFirstReady` iterates past failures (sling exit 1 -> try next)\n- Parked rigs are skipped in both event poll and feedFirstReady\n- hq store is never skipped even if `isRigParked` returns true for everything\n- High-water marks prevent event reprocessing across poll cycles\n- First poll cycle is warm-up only (seeds marks, no processing)\n- `IsSlingableType(\"epic\") == false`, `IsSlingableType(\"task\") == true`, `IsSlingableType(\"\") == true`\n- `isIssueBlocked` is fail-open (store error -> not blocked)\n- `parent-child` deps are NOT blocking\n- Batch sling creates exactly 1 convoy for N beads (not N convoys)\n- `resolveRigFromBeadIDs` errors on mixed prefixes, unmapped prefixes, town-level prefixes\n- Cycles in blocking deps prevent staged convoy creation (exit non-zero, no side effects)\n- Wave 1 contains ONLY tasks with zero unsatisfied blocking deps among slingable nodes\n- Epics and non-slingable types are NEVER placed in waves\n- Daemon does NOT feed issues from `staged:*` convoys (both feed paths skip)\n- `staged:warnings` convoys can still be launched (warnings are informational)\n- Re-staging a convoy does NOT create duplicates (updates in place)\n- Launch dispatches ONLY Wave 1, not subsequent waves\n- Wave computation is deterministic (same input → same output, alphabetical sort within waves)\n\n### Deeper test engineering\n\nSee `docs/design/convoy/stage-launch/testing.md` for the full stage-launch test plan (105 tests across unit, integration, snapshot, and property tiers).\n\nSee `docs/design/convoy/testing.md` for the general convoy test plan covering failure modes, coverage gaps, harness scorecard, test matrix, and recommended test strategy.\n\n## Common pitfalls\n\n- **`parent-child` is never blocking.** This is a deliberate design choice, not a bug. Consistent with `bd ready`, beads SDK, and molecule step behavior.\n- **Batch sling errors on already-tracked beads.** If any bead is already in a convoy, the entire batch sling fails with conflict details. The user must resolve the conflict before proceeding.\n- **The stranded scan has its own blocked check.** `isReadyIssue` in cmd/convoy.go reads `t.Blocked` from issue details. `isIssueBlocked` in operations.go covers the event-driven path. Don't consolidate them without understanding both paths.\n- **Empty IssueType is slingable.** Beads default to type \"task\" when IssueType is unset. Treating empty as non-slingable would break all legacy beads.\n- **`isIssueBlocked` is fail-open.** Store errors assume not blocked. A transient Dolt error should not permanently stall a convoy -- the next feed cycle retries with fresh state.\n- **Explicit rig in batch sling is deprecated.** `gt sling beads... rig` still works but prints a warning. Prefer `gt sling beads...` with auto-resolution.\n- **Staged convoys are inert.** The daemon ignores them completely. Don't expect auto-feeding until you `gt convoy launch`.\n- **Review `staged:warnings` before launching.** Warnings are informational — fix and re-stage if possible, or launch anyway if they're acceptable.\n- **`gt convoy launch` on a non-staged input delegates to stage.** If you pass an epic or task list to `launch`, it runs `stage --launch` internally. Only an already-staged convoy gets the fast path.\n- **Wave computation is informational.** Waves are computed at stage time for display. Runtime dispatch uses the daemon's per-cycle `isIssueBlocked` checks, which are more dynamic.\n- **You cannot un-stage an open convoy.** Once launched, a convoy cannot return to staged status. The `open → staged:*` transition is rejected.\n\n## Key source files\n\n| File | What it does |\n|------|-------------|\n| `internal/convoy/operations.go` | Core feeding: `CheckConvoysForIssue`, `feedNextReadyIssue`, `IsSlingableType`, `isIssueBlocked` |\n| `internal/daemon/convoy_manager.go` | `ConvoyManager` goroutines: `runEventPoll` (5s), `runStrandedScan` (30s), `feedFirstReady` |\n| `internal/cmd/convoy.go` | All `gt convoy` subcommands + `findStrandedConvoys` type filter |\n| `internal/cmd/sling.go` | Batch detection at ~242, auto-rig-resolution, deprecation warning |\n| `internal/cmd/sling_batch.go` | `runBatchSling`, `resolveRigFromBeadIDs`, `allBeadIDs`, cross-rig guard |\n| `internal/cmd/sling_convoy.go` | `createAutoConvoy`, `createBatchConvoy`, `printConvoyConflict` |\n| `internal/cmd/convoy_stage.go` | `gt convoy stage`: DAG walking, wave computation, error/warning detection, staged convoy creation |\n| `internal/cmd/convoy_launch.go` | `gt convoy launch`: status transition, Wave 1 dispatch via `dispatchWave1` |\n| `internal/daemon/daemon.go` | Daemon startup -- creates `ConvoyManager` at ~237 |\n\n<!-- File: .claude/commands/backup.md (Tokens: ~969 | Category: command-prompt) -->\n---\ndescription: Run Dolt database backup — sync production DBs to backup remotes and iCloud\nallowed-tools: Bash(gt dolt status:*), Bash(dolt backup:*), Bash(dolt log:*), Bash(rsync:*), Bash(du:*), Bash(cat:*), Bash(mkdir:*), Bash(timeout:*), Bash(gt escalate:*), Bash(ls:*)\nargument-hint: [--skip-offsite]\n---\n\n# Dolt Backup\n\nSync production Dolt databases to filesystem backups with smart change detection.\nRuns the same cycle as `mol-dog-backup` / the `dolt-backup` plugin.\n\nArguments: $ARGUMENTS\nIf `--skip-offsite` is passed, skip the iCloud rsync step.\n\n## Configuration\n\n```\nDOLT_DATA_DIR=~/gt/.dolt-data\nBACKUP_DIR=~/gt/.dolt-backup\nICLOUD_DIR=~/Library/Mobile Documents/com~apple~CloudDocs/gt-dolt-backup\nPROD_DBS: auto-discovered (databases with <name>-backup remotes)\nBACKUP_TIMEOUT=120s per database\nHANG_THRESHOLD=30s for server ping\nDOLT_PORT=3307\n```\n\n## Execution Steps\n\n### Step 1: Verify Dolt server is responsive\n\n```bash\ngt dolt status\n```\n\nAlso ping directly to detect hangs:\n\n```bash\ntimeout 30 dolt sql --host 127.0.0.1 --port 3307 --user root --password \"\" \\\n  --no-tls -q \"SELECT 1\" --result-format csv\n```\n\nIf the ping hangs (takes > 30s) or fails:\n```bash\ngt escalate \"dolt-backup: Dolt server hung or unreachable\" -s CRITICAL\n```\nSTOP — do not attempt backups against a hung server.\n\n### Step 2: Discover databases with backup remotes\n\nList directories in `~/gt/.dolt-data/` and check each for a `<name>-backup` remote:\n\n```bash\nls ~/gt/.dolt-data/\n```\n\nFor each directory (skip dotfiles):\n```bash\ncd ~/gt/.dolt-data/<name> && dolt backup\n```\n\nIf the output contains `<name>-backup`, include it in the backup list.\nExpected databases: `hq`, `beads`, `gastown`.\n\n### Step 3: Check each DB for changes and sync\n\nFor each database with a backup remote:\n\n**3a. Get current HEAD hash:**\n```bash\ncd ~/gt/.dolt-data/<name> && dolt log -n 1 --oneline | head -1 | cut -d' ' -f1\n```\n\n**3b. Compare against last backed-up hash:**\n```bash\ncat ~/gt/.dolt-backup/<name>/.last-backup-hash 2>/dev/null\n```\n\nIf hashes match and current hash is not \"unknown\", skip (unchanged).\n\n**3c. Sync if changed:**\n```bash\ncd ~/gt/.dolt-data/<name> && timeout 120 dolt backup sync <name>-backup\n```\n\n**3d. Record successful hash:**\n```bash\nmkdir -p ~/gt/.dolt-backup/<name>\necho \"<current_hash>\" > ~/gt/.dolt-backup/<name>/.last-backup-hash\n```\n\n**3e. Get backup size:**\n```bash\ndu -sh ~/gt/.dolt-backup/<name> 2>/dev/null | cut -f1\n```\n\n### Step 4: Offsite sync to iCloud Drive\n\nUnless `--skip-offsite` was specified:\n\n```bash\nmkdir -p ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup\nrsync -a --delete ~/gt/.dolt-backup/ ~/Library/Mobile\\ Documents/com~apple~CloudDocs/gt-dolt-backup/\n```\n\nIf iCloud is unavailable, log and continue — not fatal.\n\n### Step 5: Report\n\nPrint a summary in this format:\n\n```\n## Backup Report\n\n**Databases synced**: N/M\n**Databases skipped** (unchanged): N\n**Databases failed**: N\n**Offsite sync**: ok | failed | skipped\n\n### Per Database\n- <name>: synced in Ns (<size>) | unchanged (<hash>) | FAILED: <error>\n\n### Failures\n<list or \"None\">\n```\n\nIf any database failed or server was hung:\n```bash\ngt escalate \"dolt-backup FAILED: <summary>\" -s HIGH\n```\n\nIf server was hung, use `-s CRITICAL` instead.\n\n<!-- File: .claude/commands/patrol.md (Tokens: ~1233 | Category: command-prompt) -->\n---\ndescription: Run a patrol cycle for the current agent role (witness, deacon, or refinery)\nallowed-tools: Bash(gt patrol:*), Bash(gt hook:*), Bash(gt mail:*), Bash(gt nudge:*), Bash(gt peek:*), Bash(gt escalate:*), Bash(gt dolt status:*), Bash(bd :*), Bash(gt mol:*)\nargument-hint: [witness|deacon|refinery]\n---\n\n# Patrol\n\nRun one patrol cycle for the specified role. Patrol is a continuous monitoring\nloop — each invocation executes one cycle of the patrol formula.\n\nArguments: $ARGUMENTS\nIf no role specified, detect from current GT_ROLE environment variable.\n\n## Role Detection\n\n```bash\necho $GT_ROLE\n```\n\nMap to patrol type:\n- `*/witness` → witness patrol (`mol-witness-patrol`)\n- `*/deacon` or `*/deacon/*` → deacon patrol (`mol-deacon-patrol`)\n- `*/refinery` → refinery patrol (`mol-refinery-patrol`)\n- Explicit argument overrides detection\n\n## Patrol Entry Point\n\n```bash\ngt patrol new --role <role>\n```\n\nThis creates a hooked wisp with steps from the patrol formula.\nIf a patrol is already running (wisp exists on hook), resume it instead.\n\n## Witness Patrol Steps\n\nThe witness is the per-rig polecat supervisor. Execute in order:\n\n### 1. inbox-check\n```bash\ngt mail inbox\n```\nProcess any pending messages: POLECAT_DONE, MERGED, HELP, escalations.\nRead each with `gt mail read <id>` and take appropriate action.\n\n### 2. process-cleanups\nCheck for cleanup wisps (dirty state from dead polecats):\n```bash\nbd list --status=open --label=cleanup --json\n```\nProcess each: verify git state, clean worktrees, close cleanup wisps.\n\n### 3. check-refinery\n```bash\ngt peek gastown/refinery\n```\nVerify refinery is alive and processing the merge queue.\nIf stuck, nudge: `gt nudge gastown/refinery \"Health check — are you processing?\"`\n\n### 4. survey-workers\nCheck all active polecats in the rig:\n```bash\ngt peek gastown/polecats\n```\nFor each active polecat:\n- Check if session is alive (has recent activity)\n- Check if work is progressing (commits, bead updates)\n- Detect zombies: session dead but agent_state says working\n- Detect stale spawns: spawning > 10 minutes\n\nNudge idle polecats:\n```bash\ngt nudge gastown/polecats/<name> \"Progress check — what's your status?\"\n```\n\n### 5. check-timer-gates\n```bash\nbd list --label=gate:timer --status=open --json\n```\nEvaluate any timer-based gates that may have elapsed.\n\n### 6. check-swarm\nCheck for convoy/swarm completion across coordinated work:\n```bash\nbd list --label=convoy --status=open --json\n```\n\n### 7. patrol-cleanup\nClose completed patrol wisps, update metrics.\n\n### 8. context-check\nCheck remaining context budget. If approaching limit:\n```bash\ngt handoff -s \"Patrol cycling\" -m \"Patrol cycle N complete, cycling for fresh context\"\n```\n\n### 9. loop-or-exit\nReport cycle results and spawn next cycle:\n```bash\ngt patrol report --summary \"<cycle summary>\" --steps \"inbox:OK,cleanup:OK,...\"\n```\n\n## Deacon Patrol Steps\n\nThe deacon is the town-wide daemon monitor. Key steps:\n\n1. **inbox-check** — Process callbacks from witnesses, refineries, polecats\n2. **trigger-pending-spawns** — Launch queued polecat spawns\n3. **gate-evaluation** — Check async gates (timer, dependency)\n4. **dispatch-gated-molecules** — Release molecules whose gates cleared\n5. **check-convoy-completion** — Track multi-rig coordinated work\n6. **health-scan** — Check Dolt health (`gt dolt status`), agent health\n7. **zombie-scan** — Find dead sessions, orphaned wisps\n8. **plugin-run** — Execute enabled plugins (backup, reaper, etc.)\n9. **dog-pool-maintenance** — Manage utility worker pool\n10. **orphan-check** — Find orphaned test databases (`gt dolt cleanup`)\n11. **session-gc** — Clean up dead session artifacts\n12. **patrol-cleanup** — Close completed wisps, update metrics\n13. **context-check** — Check context budget, handoff if needed\n14. **loop-or-exit** — Report and spawn next cycle\n\n## Refinery Patrol Steps\n\nThe refinery processes the merge queue sequentially:\n\n1. **inbox-check** — Look for MERGE_READY messages from witness\n2. **queue-scan** — List pending MRs in merge queue\n3. **process-branch** — Fetch and rebase next MR branch onto target\n4. **run-tests** — Execute configured gate suite on rebased branch\n5. **handle-failures** — On test failure: bisect, isolate culprit, notify\n6. **merge-push** — Fast-forward push to main: `git push origin temp:main`\n7. **notify** — Send MERGED mail to witness immediately after push\n8. **cleanup** — Close MR bead, delete remote branch, archive mail\n9. **context-check** — Check context budget\n10. **loop-or-exit** — Report and spawn next cycle\n\n## Cycle Completion\n\nEach cycle ends with:\n```bash\ngt patrol report --summary \"<what happened>\" --steps \"<step1:OK,step2:SKIP,...>\"\n```\n\nThis closes the current patrol wisp and spawns the next cycle automatically.\n\n<!-- File: .claude/commands/reaper.md (Tokens: ~889 | Category: command-prompt) -->\n---\ndescription: Run the wisp reaper — scan, reap, purge, and auto-close stale beads across all Dolt databases\nallowed-tools: Bash(gt reaper:*), Bash(gt escalate:*), Bash(gt dolt status:*)\nargument-hint: [--dry-run]\n---\n\n# Wisp Reaper\n\nReap stale wisps and close stale issues across all production Dolt databases.\nRuns the same cycle as `mol-dog-reaper` but directly, without Dog dispatch.\n\nArguments: $ARGUMENTS\nIf `--dry-run` is passed, report counts without making changes.\n\n## Configuration Defaults\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| max_age | 24h | Wisps older than this are reaped (closed) |\n| purge_age | 72h | Closed wisps older than this are purged (deleted) |\n| stale_issue_age | 168h | Issues stale longer than this are auto-closed |\n| mail_delete_age | 72h | Closed mail older than this is purged |\n| alert_threshold | 3000 | Open wisp count that triggers escalation |\n| dolt_port | 3307 | Dolt server port |\n\n## Execution Steps\n\n### Step 1: Verify Dolt server health\n\n```bash\ngt dolt status\n```\n\nIf the server is unhealthy or unreachable, STOP and escalate:\n```bash\ngt escalate \"Reaper blocked: Dolt server unhealthy\" -s HIGH\n```\n\n### Step 2: Discover databases\n\n```bash\ngt reaper databases --json\n```\n\nThis lists all production databases on the Dolt server.\nExpected databases: `hq`, `beads`, `gastown` (and any rig-specific DBs).\n\n### Step 3: Scan each database for candidates\n\nFor each database returned in Step 2:\n\n```bash\ngt reaper scan --db=<name> --port=3307 \\\n  --max-age=24h --purge-age=72h \\\n  --mail-age=72h --stale-age=168h \\\n  --json\n```\n\nInspect the JSON output:\n- `reap_candidates`: wisps eligible for closing\n- `purge_candidates`: closed wisps eligible for deletion\n- `open_wisps`: total open wisp count\n- `anomalies`: array of detected problems\n\nIf `open_wisps` exceeds 3000 across all databases, note for escalation.\nIf no candidates found across all databases, report \"nothing to reap\" and stop.\n\n### Step 4: Reap stale wisps\n\nFor each database with reap candidates:\n\n```bash\ngt reaper reap --db=<name> --port=3307 --max-age=24h [--dry-run] --json\n```\n\n**IMPORTANT**: Scan/reap count mismatch is NORMAL (witness closes wisps concurrently).\nDo NOT escalate scan > reap mismatches. Only escalate actual errors.\n\n### Step 5: Purge old closed wisps and mail\n\nFor each database with purge candidates:\n\n```bash\ngt reaper purge --db=<name> --port=3307 \\\n  --purge-age=72h --mail-age=72h [--dry-run] --json\n```\n\nWatch for `dolt_commit_failed` anomalies — purged data may not persist.\n\n### Step 6: Auto-close stale issues\n\nFor each database with stale candidates:\n\n```bash\ngt reaper auto-close --db=<name> --port=3307 \\\n  --stale-age=168h [--dry-run] --json\n```\n\nAuto-close NEVER touches: P0/P1 issues, epics, or issues with active dependencies.\n\n### Step 7: Report\n\nPrint a summary in this format:\n\n```\n## Reaper Report\n\n**Databases scanned**: N\n**Wisps reaped**: N (stale open wisps closed)\n**Wisps purged**: N (old closed wisps deleted)\n**Mail purged**: N (old closed mail deleted)\n**Issues auto-closed**: N (stale issues past 168h)\n**Open wisps remaining**: N\n**Anomalies**: <list or \"none\">\n```\n\nIf anomalies were found:\n```bash\ngt escalate \"Reaper anomalies detected\" -s MEDIUM -m \"<anomaly details>\"\n```\n</yakaai_skills>"}