Shows detailed status for a specific rig including all workers:
- Rig info (name, path, beads prefix)
- Witness status (running/stopped, uptime)
- Refinery status (running/stopped, uptime, queue size)
- Polecats (name, state, assigned issue, session status)
- Crew members (name, branch, session status, git status)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The status line was counting rigs based on tmux session names without
validating they were actually registered in mayor/rigs.json. This could
cause incorrect rig counts when session names matched the pattern but
were not real rigs.
Now loads registered rigs from rigs.json and only counts:
- Rigs that are actually registered
- Polecats belonging to registered rigs
Fixes#17🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add repo-fingerprint check to gt doctor that verifies beads databases have
valid repository fingerprints. Missing or empty fingerprints can cause daemon
startup failures and sync issues.
The check:
- Uses bd doctor --json to check fingerprint status
- Runs on town-level and rig-level beads directories
- Can fix by running bd migrate --update-repo-id
- Restarts daemon after migration if it was running
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add validation in Manager.AddRig() to reject rig names containing
characters that break agent ID parsing. Agent IDs use format
<prefix>-<rig>-<role>[-<name>] with hyphens as delimiters, so
hyphenated rig names like op-baby cause parsing failures.
The validation rejects hyphens, dots, and spaces, and suggests a
sanitized alternative in the error message.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a new doctor check that verifies the bd (beads) daemon is running
and healthy. When the daemon fails to start, the check:
- Surfaces specific error messages (legacy database, repo mismatch)
- Provides one-liner fix commands
- Auto-fixes by running bd migrate --update-repo-id when appropriate
This addresses GH #25: gt status slow when bd daemon not running.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add bd daemon health check at the start of gt status:
- Check daemon health via bd daemon health --json
- Attempt restart if daemons are unhealthy (version mismatch, stale, unresponsive)
- Show warning at end of status output if daemons could not be started
- Non-blocking: status display continues regardless of daemon state
This prevents the 39+ second slowdown when bd daemons are not running
properly, as each bd command falls back to slow direct mode.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements cost tracking v1 for Gas Town agents:
- `gt costs` shows live costs scraped from running tmux sessions
- `gt costs --today/--week` shows historical costs from ledger
- `gt costs --by-role/--by-rig` shows cost breakdowns
- `gt costs record` for Stop hook integration to record final costs
Cost ledger stored at ~/.gt/costs.jsonl with JSONL entries per session.
Ref: gt-nrpiq
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Town beads should use 'hq-' prefix to match documented architecture:
- Town beads (~/gt/.beads/): hq-* prefix for mayor mail, coordination
- Rig beads: project-specific prefix
The 'gm' prefix was causing convoy creation failures due to prefix
mismatch.
Fixes#19🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add internal/deps package for dependency management
- Check for bd before gt install and gt rig add
- Auto-install bd via go install if missing
- Version check warns if bd is too old (min: 0.43.0)
Closes#22🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GetAllRoleTemplates tests (basic and content validity)
- Add FixMultipleRigs test for multi-rig fix scenario
- Add DetailsFormat test verifying rig:template prefix format
- Add MalformedRigsJSON test for error handling
- Add EmptyRigsConfig test for edge case
- PatrolRolesHavePromptsCheck now verifies templates exist in each rig's
mayor clone at <rig>/mayor/rig/internal/templates/roles/
- Track missing templates by rig using missingByRig map
- Fix copies embedded templates to each rig's location
- Add GetAllRoleTemplates helper to templates package
- Add tests for no-rigs case and multiple-rigs scenarios
When the Refinery Engineer detects a merge conflict during rebase,
it now creates a dispatchable task bead for conflict resolution.
Task format:
- Title: Resolve merge conflicts: <original-issue-title>
- Type: task
- Priority: boosted from original (P2 -> P1, P1 -> P0)
- Description includes: original MR ID, branch, conflict SHA,
source issue, retry count, and step-by-step instructions
The task appears in bd ready and can be dispatched to available
polecats by the Witness. After resolution and force-push, the
Refinery will automatically retry the merge.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
initAgentBeads and crew_add were looking for beads at mayor/rig/.beads/
but during initial creation, beads is at rig root. The redirect
mechanism to mayor/rig/.beads/ gets set up later.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement ScoreMR function for merge queue priority ordering with:
- Convoy age factor (prevents starvation of old convoys)
- Priority factor (P0 beats P4)
- Retry penalty (prevents thrashing on conflict-prone MRs)
- MR age tiebreaker (FIFO within same priority)
Added fields to MR struct:
- RetryCount for conflict retry tracking
- ConvoyID and ConvoyCreatedAt for convoy linkage
Includes comprehensive unit tests and documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
buildAgentIdentity was returning 2-part format (rig/name) while
sling.go sets assignee using 3-part format (rig/polecats/name) from
session.AgentIdentity.Address(). This mismatch caused gt hook to
fail when querying for hooked beads by assignee.
Changes:
- buildAgentIdentity: Return rig/polecats/name for polecats
- buildAgentBeadID: Handle both 2-part and 3-part formats
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use conditional bindings (if-shell) to check if session name starts
with "gt-" before running Gas Town commands. For non-GT sessions:
- C-b n/p fall back to default next-window/previous-window
- C-b a shows a help message
This prevents Gas Town from hijacking keybindings in unrelated tmux
sessions that happen to share the same tmux server.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The TUI query used 'dependency_type' but the actual column is 'type'.
This caused expand to show nothing when pressing Enter on a convoy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements announce channel delivery in router.go:
- Add isAnnounceAddress() and parseAnnounceName() helpers
- Add ErrUnknownAnnounce error variable
- Add expandAnnounce() to load AnnounceConfig from messaging.json
- Add sendToAnnounce() for bulletin board delivery (single copy, no claiming)
- Add pruneAnnounce() for retention-based message cleanup
- Integrate announce routing in Send()
Announce channels store ONE copy of each message (unlike lists which fan-out).
Messages persist until retention limit is reached, with oldest messages
pruned automatically when limit is exceeded.
Also includes address helpers (gt-pn2fq dependency).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add announces subcommand to internal/cmd/mail.go that provides:
- gt mail announces: Lists all announce channels from messaging.json
- gt mail announces <channel>: Reads messages from a specific channel
The command queries beads for messages with announce_channel label and
displays them in reverse chronological order. Messages are NOT marked
as read or removed, preserving bulletin board semantics.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show ✓ for closed, ▶ for in_progress/hooked, ○ for other statuses
- Display assignee name in brackets instead of issue type
- Falls back to issue type when no assignee, or "unassigned" when neither
Closes gt-cbstf
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add announce address detection to internal/mail/router.go following
the same pattern as isListAddress/parseListName and isQueueAddress/
parseQueueName.
Added:
- isAnnounceAddress(address string) bool - returns true for 'announce:' prefix
- parseAnnounceName(address string) string - extracts channel name
- ErrUnknownAnnounce error variable
(gt-pn2fq)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New outputSessionMetadata() function prints a structured line at prime start:
[GAS TOWN] role:mayor pid:12345 session:abc-uuid-123
This enables gt seance to discover sessions from Claude transcripts,
complementing the existing event emission to .events.jsonl.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds `gt mail search <query>` command with:
- Regex pattern matching (case-insensitive by default)
- --from: Filter by sender address
- --subject: Only search subject lines
- --body: Only search message body
- --archive: Include archived (closed) messages
- --json: Output as JSON
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gt swarm create was failing when using a pre-existing epic because
it tried to call `bd update --mol-type=swarm`, but bd update doesn't
support the --mol-type flag.
Fix: Only set mol-type during bd create (when epic doesn't exist.
Pre-existing epics work as-is since swarm functionality doesn't
depend on the mol-type field.
Closes gt-zqt4d
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
EOF
)
When -m flag is not provided, opens $EDITOR to compose the reply.
The editor shows a template with the original message for context.
Comment lines (starting with #) are filtered out.
- Makes -m flag optional instead of required
- Falls back to vim/vi/nano/emacs if $EDITOR not set
- Updates help text to document editor mode (gt-d46.5)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --quiet (-q) flag for scripted mail checks:
- Outputs "N new message(s)" only when mail exists
- Silent output when no mail (exit 1)
- Fixes usage output being shown on exit 1
(gt-d46.1)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt mail mark <id> --read/--unread: Change message read status
- gt mail delete <id> --force: Add confirmation prompt (skip with --force)
- gt mail archive: Batch operations with --older-than, --all-read, --dry-run
- gt mail purge: Delete archived messages with --older-than, --dry-run, --force
- gt mail search <query>: Regex search with --from, --subject, --body, --json
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The display was normalizing idle → working which was misleading.
Idle polecats should show as idle so operators know to nuke them.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The 10-minute recovery heartbeat was too slow to detect stuck agents promptly.
Reduced to 3 minutes for better balance between detection speed and overhead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The refinery template listed git branch -r | grep polecat as a reference
command, causing the refinery agent to check git branches instead of the
beads merge queue. This caused 41 MRs to pile up.
- Removed misleading git branch grep reference from Git Operations section
- Added explicit warnings about using gt mq list as sole source of truth
- Strengthened queue-scan step with CRITICAL warning
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add worker information to convoy status display:
- Query agent beads across rigs for matching hook_bead
- Display worker inline with tracked issues: @gastown/nux (12m)
- Include Worker and WorkerAge in JSON output
- Skip worker lookup for closed issues
Example output:
Tracked Issues:
○ gt-xyz: Fix bug [task] @gastown/nux (12m)
✓ gt-abc: Add feature [task]
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use NoOptDefVal so --notify defaults to "mayor/" when specified without
a value:
- `--notify` (no arg) -> defaults to "mayor/"
- `--notify ops/` -> uses "ops/"
- (no flag) -> no notification
Removed the mayor-specific auto-default since NoOptDefVal handles this
for all roles.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement MachineRegistry that manages machine configurations and
provides Connection instances for local and remote operations:
- Machine struct with name, type, host, key path, and town path
- Registry with JSON persistence (federation.json)
- CRUD operations: Get, Add, Remove, List
- Connection factory that returns appropriate Connection type
- Built-in "local" machine that cannot be removed
SSH connections return an error until SSHConnection is implemented.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Define the Connection interface that abstracts file operations, command
execution, and tmux management for both local and remote (SSH) contexts.
Includes:
- Connection interface with file, exec, and tmux operations
- FileInfo interface for remote stat results
- BasicFileInfo implementation with JSON serialization
- Error types for connection failures
This enables Gas Town to manage rigs on remote machines using the
same interface as local operations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use golang.org/x/text/cases.Title(language.English) instead of the
deprecated strings.Title function. Updated formula.go (3 usages)
and patrol_helpers.go (1 usage).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add --collect/-c flag to gt handoff: auto-collects hooked work,
inbox summary, ready beads, and in-progress items into the handoff
message body
- Add --handoff flag to gt resume: checks inbox for messages with
"HANDOFF" in subject and displays them formatted for continuation
- Supports both JSON and plain-text inbox output formats
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add 7 new checks for rig health when using `gt doctor --rig <name>`:
- rig-is-git-repo: Verify mayor/rig/ is a valid git clone
- git-exclude-configured: Check .git/info/exclude has Gas Town dirs (fixable)
- witness-exists: Verify witness/ structure exists (fixable)
- refinery-exists: Verify refinery/ structure exists (fixable)
- mayor-clone-exists: Verify mayor/rig/ clone exists (fixable)
- polecat-clones-valid: Verify polecat directories are valid clones
- beads-config-valid: Verify beads configuration works (fixable)
Checks are only registered when --rig flag is provided.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds gt mail clear [target] command that:
- Clears all messages from an inbox
- Supports clearing your own inbox (no args) or another agent's
- Reports count of deleted messages
- Handles partial failures gracefully
Use case: Town quiescence - reset all inboxes across workers efficiently.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Layer 1: Implements gt agent state command for managing agent bead labels:
- gt agent state <bead> - Get all state labels
- gt agent state <bead> --set idle=0 - Set label value
- gt agent state <bead> --incr idle - Increment numeric label
- gt agent state <bead> --del idle - Delete label
Layer 2: Fixes await-signal iteration tracking:
- Adds --agent-bead flag to read/write idle:N label
- Implements exponential backoff: base * mult^idle_cycles
- Auto-increments idle counter on timeout
- Returns idle_cycles in result for caller to reset on signal
This enables patrol agents to back off during quiet periods while staying
responsive to signals. Part of epic gt-srm3y.
(gt-srm3y)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>