Add a new doctor check that detects when issues.db is empty but
issues.jsonl has content. This situation can cause "table issues has
no column named pinned" errors when running bd mail send.
The check:
- Detects empty database file alongside non-empty JSONL
- Can auto-fix by deleting the empty database and triggering rebuild
- Works for both town-level and rig-level beads
Run 'gt doctor --fix' to automatically fix this issue.
Fixes gt-bxi8
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace mail-based handoff system with pinned beads that persist
across sessions. This fixes the issue where handoff messages get
closed before successors can read them.
Changes:
- beads: Add StatusPinned constant and handoff functions:
- HandoffBeadTitle() for well-known naming
- FindHandoffBead() to locate role handoff bead
- GetOrCreateHandoffBead() to ensure bead exists
- UpdateHandoffContent() to set handoff message
- ClearHandoffContent() to reset after reading
- cmd/handoff: Update to use pinned beads instead of mail
- sendHandoffMail() now updates pinned bead content
- cmd/prime: Display handoff content on startup
- outputHandoffContent() reads and shows handoff bead
- cmd/rig: Add reset command with --handoff flag
- gt rig reset --handoff clears handoff content
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This implements the ephemeral polecat model where polecats are spawned
fresh for each task and deleted upon completion.
Key changes:
**Spawn (internal/cmd/spawn.go):**
- Always create fresh worktree from main branch
- Run bd init in new worktree to initialize beads
- Remove --create flag (now implicit)
- Replace stale polecats with fresh worktrees
**Handoff (internal/cmd/handoff.go):**
- Add rig/polecat detection from environment and tmux session
- Send shutdown requests to correct witness (rig/witness)
- Include polecat name in lifecycle request body
**Witness (internal/witness/manager.go):**
- Add mail checking in monitoring loop
- Process LIFECYCLE shutdown requests
- Implement full cleanup sequence:
- Kill tmux session
- Remove git worktree
- Delete polecat branch
**Polecat state machine (internal/polecat/types.go):**
- Primary states: working, done, stuck
- Deprecate idle/active (kept for backward compatibility)
- New polecats start in working state
- ClearIssue transitions to done (not idle)
**Polecat commands (internal/cmd/polecat.go):**
- Update list to show "Active Polecats"
- Normalize legacy states for display
- Add deprecation warnings to wake/sleep commands
Closes gt-7ik
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Remove creation of mayor/mail/ directory with legacy JSONL inbox
- Initialize town-level beads DB (gm- prefix) via `bd init` instead of
creating a .beads/redirect placeholder file
- Update help text and next-steps output to reflect new architecture
Town beads (gm-*) store mayor mail, cross-rig coordination, and handoffs.
Rig beads remain separate with their own prefixes.
Closes: gt-jpt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The spawn command now accepts --polecat and --rig flags as an
alternative to the positional rig/polecat argument. When using
--polecat without --rig, the rig is inferred from the current
working directory.
Examples:
gt spawn --issue gt-xyz --polecat Angharad
gt spawn --issue gt-abc --rig gastown --polecat Toast
Fixes gt-selw
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement 'gt mq integration create <epic>' command to create integration
branches for batch work on epics. The command:
1. Verifies the epic exists in beads
2. Creates branch integration/<epic-id> from origin/main
3. Pushes the branch to origin
4. Stores integration branch info in the epic's metadata
Also adds helper methods to git package:
- CreateBranchFrom: create branch from specific ref
- BranchExists: check if local branch exists
- RemoteBranchExists: check if branch exists on remote
Future MRs for the epic's children can target the integration branch
with: gt mq submit --epic <epic-id>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds two new commands to transition polecats back to idle state:
- gt polecat done (alias: finish): Transitions from working/done/stuck
states to idle, clearing the assigned issue. For normal workflow when
work is complete but session was not properly cleaned up.
- gt polecat reset: Force resets any state to idle. For recovery when
polecat is stuck in an unexpected state.
Both commands check that the session is stopped before modifying state.
Fixes gt-s3m0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the witness monitoring agent command with start, stop, and status
subcommands. The witness monitors polecats for stuck/idle states and
can nudge blocked workers.
Closes gt-kcee
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When using `gt spawn rig --create` and no polecats exist (or all are
busy), the command now automatically generates a Mad Max themed polecat
name and creates it, rather than failing with "no available polecats".
This improves agent UX by making the --create flag work intuitively.
Fixes: gt-szsq
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
'gt session capture rig/polecat 50' now works in addition to
'gt session capture rig/polecat -n 50'. Agent UX: commands should
work the way agents guess they work.
Closes: gt-d7i
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 200ms delay after NewSession before sending keys to fix race
condition where shell is not ready (mayor.go, crew.go)
- Use merge-request type instead of task for gt mq submit (mq.go)
Fixes gt-tulx
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
detectSender() only detected polecats, not crew workers. Crew workers
like Emma at /Users/stevey/gt/beads/crew/emma were incorrectly
defaulting to mayor/ instead of getting their proper address.
Added /crew/ directory pattern matching parallel to the existing
/polecats/ detection, extracting rig/crewName address format.
Fixes: gt-70b3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
filepath.SplitList is for PATH-like env vars (colon/semicolon separated),
not for splitting file paths. This caused inferRigFromCwd to always fail
since SplitList returns the whole path as one element, making the fallback
logic never trigger.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds the merge queue submit command for workers to submit completed
work to the merge queue. The command creates a merge-request bead
that the Engineer will process.
Features:
- Auto-detects branch, issue, worker, and rig from current context
- Parses polecat/<worker>/<issue> branch naming convention
- Supports explicit --branch, --issue, --epic, --priority flags
- Inherits priority from source issue by default
- Creates merge-request bead with structured MR fields
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds keepalive.Touch() to signal agent activity during commands.
Also ignores state.json in .gitignore.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Every gt command now touches .gastown/keepalive.json with the last
command and timestamp. This enables smarter daemon backoff:
- Fresh (< 2 min): agent is working, skip heartbeat
- Stale (2-5 min): might be thinking, gentle poke
- Very stale (> 5 min): likely idle, safe to interrupt
Uses PersistentPreRun hook to capture all commands including subcommands.
Closes gt-bfd
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Combined with Dag's mq retry from previous merge.
Full MQ CLI now includes: list, retry, reject subcommands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add gt mq list <rig> command with table output
- Support --ready flag to show only unblocked MRs
- Support --status, --worker, --epic filtering
- Support --json output format
- Parse MR fields from beads issues for display
- Show blocking info for blocked MRs
Closes gt-svi.2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add MessageType enum (task, scavenge, notification, reply)
- Expand Priority from 2 to 4 levels (low, normal, high, urgent)
- Add ThreadID and ReplyTo fields to Message struct
- Add --type and --reply-to flags to 'gt mail send'
- Add 'gt mail thread <id>' command to view conversation threads
- Update inbox/read display to show type and threading info
- Auto-generate thread IDs for new messages
- Reply messages inherit thread from original
Closes: gt-hgk
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add 'gt mq retry <rig> <mr-id>' command to retry failed MRs:
- Added GetMR() and Retry() methods to refinery.Manager
- Added RegisterMR() for persistent MR tracking
- Added PendingMRs field to Refinery state
- Created new mq.go command file with retry subcommand
- Support --now flag for immediate processing
- Added comprehensive tests for retry functionality
Closes gt-svi.4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add gt mq command group with reject subcommand
- Add FindMR method to locate MRs by ID or branch
- Add RejectMR method to reject MRs with reason
- Add notifyWorkerRejected for optional mail notification
- Add tests for rejection state transitions
Closes gt-svi.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds the 'gt mq status <id>' command for displaying detailed merge request
information. Features:
- Shows all MR fields (branch, target, source_issue, worker, rig)
- Displays current status with timestamps and relative time
- Shows dependencies (what it's waiting on) with status icons
- Shows blockers (what's waiting on it)
- Supports JSON output with --json flag
This is part of the merge queue CLI commands (gt-svi).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the agent-side lifecycle request command (gt-gby):
- Detects agent role via GT_ROLE env, tmux session, or directory
- Pre-flight checks (git clean) before retirement
- Sends handoff mail to self for context preservation
- Sends lifecycle request to manager (daemon/ for Mayor/Witness)
- Sets requesting_cycle state and waits for retirement
Usage:
gt handoff # Role-appropriate default
gt handoff --cycle # Restart with handoff mail
gt handoff --restart # Fresh restart
gt handoff --shutdown # Terminate without restart
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the town daemon (gt-99m) that handles:
- Periodic heartbeat to poke Mayor and Witnesses
- Lifecycle request processing (cycle, restart, shutdown)
- Session management for agent restarts
Commands:
- gt daemon start: Start daemon in background
- gt daemon stop: Stop running daemon
- gt daemon status: Show daemon status and stats
- gt daemon logs: View daemon log file
The daemon is a "dumb scheduler" - all intelligence remains in agents.
It simply pokes them on schedule and executes lifecycle requests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds git repository initialization for Gas Town harnesses:
1. New 'gt git-init' command for existing harnesses:
- Creates comprehensive .gitignore for Gas Town
- Initializes git repository if not present
- Optionally creates GitHub repo with --github flag
2. New flags on 'gt install':
- --git: Initialize git with .gitignore during install
- --github=owner/repo: Create and push to GitHub repo
- --private: Make GitHub repo private
The .gitignore properly excludes:
- Polecats and rig clones (recreated with gt spawn/rig add)
- Runtime state files (state.json, *.lock, registry.json)
- OS and editor files
And tracks:
- Role contexts (CLAUDE.md)
- .beads/ configuration and issues
- hop/ directory
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Cobra aliases to match PGT abbreviation support:
- mayor → may (gt may at now works)
- session → sess
- refinery → ref
- spawn → sp
- polecat → cat
- status → stat
This enables the same abbreviated commands that worked in PGT, like
"gt may at" to attach to the Mayor session.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-start Mayor session if not running (matches town mayor attach)
- Send `gt prime` after Claude starts to initialize context
- Use `exec claude` so /exit closes tmux session (no shell to return to)
- Add "may" alias for mayor command
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-start Mayor session if not running (no need for gt mayor start first)
- Restart Claude if it has exited (detects shell in pane)
- Prime with gt prime after start/restart
- Refactor: extract startMayorSession helper
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check pane_current_command to detect if Claude is still running
- If shell is detected (bash, zsh, etc.), Claude exited - restart it
- Re-prime after restart with gt prime
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt crew at: auto-detect crew from cwd, run gt prime after launch
- Polecats now use git worktrees from refinery (faster than clones)
- Updated architecture.md for two-tier beads mail model
- Town beads (gm-*) for Mayor mail/coordination
- Rig .beads/ symlinks to refinery/rig/.beads
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement AddRig with container-based approach (rig root is NOT a clone)
- Create internal/cmd/rig.go with add/list/remove subcommands
- Clone repo into refinery/rig/, mayor/rig/, crew/main/
- Initialize rig-level .beads/ with derived prefix
- Update docs/architecture.md to match implementation
- File gt-jpt epic for town-level beads redesign
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements gt-f9x.3: Create Gas Town workspace structure.
The install command creates a new harness (workspace) with:
- config/town.json - Town configuration with name and version
- config/rigs.json - Empty rigs registry
- mayor/ - Mayor agent home with:
- CLAUDE.md - Mayor role context from template
- config.json - Distinguishes town-level mayor
- mail/inbox.jsonl - Empty inbox
- state.json - Initial state
- .beads/redirect - Placeholder for default beads location
Usage:
gt install ~/gt # Create at path
gt install . --name mytown # Current dir with name
gt install ~/gt --no-beads # Skip beads setup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements gt-u1j.20: Prompt templates using go:embed.
- Add internal/templates package with embedded .md.tmpl files
- Role templates: mayor, witness, refinery, polecat, crew
- Message templates: spawn, nudge, escalation, handoff
- Update gt prime to use templates with fallback to hardcoded output
- Add crew role detection for <rig>/crew/<name>/ paths
- Include Gas Town architecture overview in all role contexts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>