Instead of changing the convoy ID format, register the hq-cv- prefix
as a valid route pointing to town beads. This preserves the semantic
meaning of convoy IDs (hq-cv-xxxxx) while fixing the prefix mismatch.
Changes:
- Register hq-cv- prefix during gt install
- Add doctor check and fix for missing convoy route
- Update routes_check tests for both hq- and hq-cv- routes
Fixes: gt-4nmfh
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When no argument is provided, `gt hook show` now auto-detects the
current agent from context using resolveSelfTarget(), matching the
behavior of other commands like `gt hook` and `gt mail inbox`.
Fixessteveyegge/beads#1078
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
buildCVSummary always returned nil for its error value, causing
golangci-lint to fail with "result 1 (error) is always nil".
The function handles errors internally by returning partial data,
so the error return was misleading. Removed it and updated caller.
* feat(refinery,boot): add --agent flag for model selection (hq-7d5m)
Add --agent flag to gt refinery start/attach/restart and gt boot spawn
commands for consistent model selection across all agent launch points.
Implementation follows the existing pattern from gt deacon start:
- Add StringVar flag for agent alias
- Pass override to Manager/Boot via SetAgentOverride()
- Use BuildAgentStartupCommandWithAgentOverride when override is set
Files affected:
- cmd/gt/refinery.go: add flags to start/attach/restart commands
- internal/refinery/manager.go: add SetAgentOverride and use in Start()
- cmd/gt/boot.go: add flag to spawn command
- internal/boot/boot.go: add SetAgentOverride and use in spawnTmux()
Closes#438
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(refinery,boot): use parameter-passing pattern for --agent flag
Address PR review feedback:
1. ADD TESTS: Add tests for --agent flag existence following witness_test.go pattern
- internal/cmd/refinery_test.go: tests for start/attach/restart
- internal/cmd/boot_test.go: test for spawn
2. ALIGN PATTERN: Change from setter pattern to parameter-passing pattern
- Manager.Start(foreground, agentOverride) instead of SetAgentOverride + Start
- Boot.Spawn(agentOverride) instead of SetAgentOverride + Spawn
- Matches witness.go style: Start(foreground bool, agentOverride string, ...)
Updated all callers to pass empty string for default agent:
- internal/daemon/daemon.go
- internal/cmd/rig.go
- internal/cmd/start.go
- internal/cmd/up.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: furiosa <will@saults.io>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1. TestQuerySessionEvents_FindsEventsFromAllLocations
- Skip test when running inside Gas Town workspace to prevent
daemon interaction causing hangs
- Add filterGTEnv helper to isolate subprocess environment
2. TestAddWithOptions_HasAgentsMD / TestAddWithOptions_AgentsMDFallback
- Create origin/main ref manually after adding local directory as
remote since git fetch doesn't create tracking branches for local
directories
Refs: gt-zbu3x
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add commands to find and terminate orphan Claude processes (those with
PPID=1 that survived session termination):
- gt orphans list: Show orphan Claude processes
- gt orphans kill: Kill with confirmation
- gt orphans kill -f: Force kill without confirmation
Detection excludes:
- tmux processes (may contain "claude" in args)
- Claude.app desktop application processes
- Claude Helper processes
The original `gt orphans` functionality for finding orphan git commits
is preserved.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds `gt orphans kill` subcommand that permanently removes orphaned
commits by running `git gc --prune=now`.
Flags:
- --dry-run: Preview without deleting
- --days N: Kill orphans from last N days (default 7)
- --all: Kill all orphans regardless of age
- --force: Skip confirmation prompt
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Before calling tmux kill-session, explicitly kill the pane's process tree
using pkill. This ensures claude processes don't survive session termination
due to SIGHUP being caught/ignored.
Implementation:
- Add KillSessionWithProcesses() to tmux.go
- Update killSessionsInOrder() in start.go to use new method
- Update stopSession() in down.go to use new method
Fixes: gt-5r7zr
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Migrate witness, boot, and deacon spawns to use NewSessionWithCommand
instead of NewSession+SendKeys to ensure BD_ACTOR is visible in the
process tree for orphan detection via ps.
Refs: gt-emi5b
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
buildCVSummary always returned nil for its error value, causing
golangci-lint to fail with "result 1 (error) is always nil".
The function handles errors internally by returning partial data,
so the error return was misleading. Removed it and updated caller.
Combines three related sling improvements:
1. Auto-attach mol-polecat-work (Issue #288)
- Automatically attach work molecule when slinging to polecats
- Ensures polecats have standard guidance molecule attached
2. Fix polecat hook with molecule (Issue #197)
- Use beads.ResolveHookDir() for correct directory resolution
- Prevents bd cook from failing in polecat worktree
3. Spawn fresh polecat when target has no session
- When slinging to a dead polecat, spawn fresh one instead of failing
- Fixes stale convoys not progressing due to done polecats
Migrate witness, boot, and deacon spawns to use NewSessionWithCommand
instead of NewSession+SendKeys to ensure BD_ACTOR is visible in the
process tree for orphan detection via ps.
Refs: gt-emi5b
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add critical checks to prevent lost work when polecats call gt done
without having made any commits:
1. Block if working directory not available (cannot verify git state)
2. Block if uncommitted changes exist (would be lost on completion)
3. Check commits against origin/main not local main (ensures actual work)
If any check fails, refuse completion and suggest using --status DEFERRED.
This preserves the worktree so work is not lost.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gt done now completes successfully even if the polecat's worktree is
deleted mid-operation by the Witness or another process.
Changes:
- Add FindFromCwdWithFallback() that returns townRoot from GT_TOWN_ROOT
env var when getcwd fails
- Update runDone() to use fallback paths and env vars (GT_BRANCH,
GT_POLECAT) when cwd is unavailable
- Update updateAgentStateOnDone() to use env vars (GT_ROLE, GT_RIG,
GT_POLECAT) for role detection fallback
- All bead operations are now explicitly non-fatal with warnings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --owner flag to gt convoy create to track who requested a convoy.
Owner receives completion notification when convoy closes (in addition
to any --notify subscribers). Notifications are de-duplicated if owner
and notify are the same address.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove the mrqueue side-channel from gastown. The merge queue now uses
beads merge-request wisps exclusively, not parallel .beads/mq/*.json files.
Changes:
- Delete internal/mrqueue/ package (~830 lines removed)
- Move scoring logic to internal/refinery/score.go
- Update Refinery engineer to query beads via ReadyWithType("merge-request")
- Add MRInfo struct to replace mrqueue.MR
- Add ClaimMR/ReleaseMR methods using beads assignee field
- Update HandleMergeReady to not create duplicate queue entries
- Update gt refinery commands (claim, release, unclaimed) to use beads
- Stub out MQEventSource (no longer needed)
The Refinery now:
- Lists MRs via beads.ReadyWithType("merge-request")
- Claims via beads.Update(..., {Assignee: worker})
- Closes via beads.CloseWithReason("merged", mrID)
- Blocks on conflicts via beads.AddDependency(mrID, taskID)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow `gt crew status <rig>` to work without requiring --rig flag.
This matches the pattern already used by crew start and crew stop.
Desire path: hq-v33hb
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `gt polecat identity show <rig> <polecat>` command that displays:
- Identity bead ID and creation date
- Session count
- Completion statistics (completed, failed, abandoned)
- Language breakdown from file extensions in git history
- Work type breakdown (feat, fix, refactor, etc.)
- Recent work list with relative timestamps
- First-pass success rate
Supports --json flag for programmatic output.
Closes: hq-d17es.4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `gt convoy close` command to manually close convoys regardless of
tracked issue status. This addresses the desire path identified in
convoy-lifecycle.md.
Features:
- Close convoy with optional --reason flag
- Send notification with optional --notify flag
- Idempotent: closing already-closed convoy is a no-op
- Validates convoy type before closing
Closes hq-2i8yw
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use errors.Is() for all ErrAlreadyRunning comparisons (consistency)
- Remove redundant HasSession check before Start() (was a race anyway)
- Remove unused tmux parameters from startRigAgents and startWitnessForRig
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt rig park now accepts variadic args (fixes#375)
- gt rig unpark updated for consistency
- Errors collected and reported at end
Also fixes test self-interruption bug where sling tests sent real
tmux nudges containing "Work slung: gt-wisp-xyz", causing agents
running tests to interrupt themselves. Added GT_TEST_NO_NUDGE env
var to skip nudge during tests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes from code review:
- Remove duplicate generateDogNameForDispatch, reuse generateDogName
- Fix race condition: assign work BEFORE sending mail
- Add rollback if mail send fails (clear work assignment)
- Fix misleading help text (was "hooks mail", actually sends mail)
- Add --json flag for scripted output
- Add --dry-run flag to preview without executing
The order change (assign work first, then send mail) ensures that if
AssignWork fails, no mail has been sent. If mail fails after work is
assigned, we rollback by clearing the work assignment.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove duplicate *Parallel variants, consolidate into single functions
- Cache discoverAllRigs() result at top level, pass to functions
- Use sync/atomic for startedAny flag instead of extra mutex
- Functions now take rigs slice and mutex as parameters
Net reduction: 83 lines
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements gt-n08ix.2: formalized plugin dispatch to dogs.
The new `gt dog dispatch --plugin <name>` command:
- Finds plugin definition using the existing plugin scanner
- Creates a mail work unit with plugin instructions
- Assigns work to an idle dog (or creates one with --create)
- Returns immediately (non-blocking)
Usage:
gt dog dispatch --plugin rebuild-gt
gt dog dispatch --plugin rebuild-gt --rig gastown
gt dog dispatch --plugin rebuild-gt --dog alpha
gt dog dispatch --plugin rebuild-gt --create
This enables the Deacon to dispatch plugins to dogs during patrol
cycles without blocking on execution.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt plugin run: Manual plugin execution with gate check
- --force to bypass cooldown gate
- --dry-run to preview without executing
- Records successful runs as ephemeral beads
- gt plugin history: Show execution history from ephemeral beads
- --json for machine-readable output
- --limit to control number of results
- Fix recording.go to use valid bd list flags (--created-after instead of --since)
Closes: gt-n08ix.4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Start Mayor, Deacon, rig agents, and crew all in parallel rather than
sequentially. This reduces worst-case startup from N*60s to ~60s since
all agents can start concurrently.
Closes gt-dgbwk
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated all component versions:
- gt CLI: 0.2.5 → 0.2.6
- npm package: 0.2.5 → 0.2.6
Highlights:
- Unified escalation system with severity levels and routing
- gt stale command for binary staleness checks
- Per-agent-type health tracking in statusline
- Refactored sling.go into 7 focused modules
- Many bug fixes for beads, sling, and session lifecycle
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Exposes CheckStaleBinary() via CLI for scripting. Supports --json for
machine-readable output and --quiet for exit-code-only mode (0=stale,
1=fresh, 2=error).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
MR beads were being created as regular beads, showing up in `bd ready`
when they should be ephemeral wisps that get cleaned up after merge.
Added Ephemeral field to CreateOptions and set it when creating MR beads.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When using gastown/max style paths, resolvePathToSession was treating
all non-role names as polecats, generating gt-gastown-max instead of
gt-gastown-crew-max.
Now checks if <townRoot>/<rig>/crew/<name> exists before defaulting
to polecat format. This fixes gt sling to crew members using the
shorthand rig/name syntax.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add fallback instructions to start/restart topics in FormatStartupNudge()
so agents have actionable instructions even if SessionStart hook fails.
Previously, "start" and "restart" beacons only contained metadata like:
[GAS TOWN] beads/crew/fang <- human • 2025-01-12 • start
If the SessionStart hook failed to inject context via `gt prime`, agents
would sit idle at "No recent activity" screen with no instructions.
Now these topics include:
Run `gt prime` now for full context, then check your hook and mail.
Also warn instead of silently discarding settings provisioning errors in
crew_at.go.
Fixes: gt-uoc64
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(config): don't export empty GT_ROOT/BEADS_DIR in AgentEnv
Fix polecats not having GT_ROOT environment variable set. The symptom was
polecat sessions showing GT_ROOT="" instead of the expected town root.
Root cause: AgentEnvSimple doesn't set TownRoot, but AgentEnv was always
setting env["GT_ROOT"] = cfg.TownRoot even when empty. This empty value
in export commands would override the tmux session environment.
Changes:
- Only set GT_ROOT and BEADS_DIR in env map if non-empty
- Refactor daemon.go to use AgentEnv with full AgentEnvConfig instead
of AgentEnvSimple + manual additions
- Update test to verify keys are absent rather than empty
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(lint): silence unparam for unused executeExternalActions args
The external action params (beadID, severity, description) are reserved
for future email/SMS/slack implementations but currently unused.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: julianknutsen <julianknutsen@users.noreply.github>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: max <steve.yegge@gmail.com>
- Merge two session iteration loops into single pass
- Remove unused polecatCount variable
- Consolidate rig status and health tracking
- Net reduction of 17 lines
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change EscalationConfig to use Routes map with action strings
- Rename severity "normal" to "medium" per design doc
- Move config from config/ to settings/escalation.json
- Add --source flag for escalation source tracking
- Add Source field to EscalationFields
- Add executeExternalActions() for email/sms/slack with warnings
- Add default escalation config creation in gt install
- Add comprehensive unit tests for config loading
- Update help text with correct severity levels and paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds per-agent-type health tracking to the Mayor's tmux statusline, showing
working/idle counts for Polecats, Witnesses, Refineries, and Deacon.
All agent types are always displayed, even when no agents of that type are
running (shows as '0/0 😺').
Format: active: 4/4 😺 6/10 👁️ 7/10 🏭 1/1 ⛪
Co-authored-by: gastown/crew/dennis <steve.yegge@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Role beads (hq-*-role) are templates that define role characteristics.
They are created during gt install but creation may fail silently.
Without role beads, agents fall back to defaults.
Changes:
- Add beads.AllRoleBeadDefs() as single source of truth for role bead definitions
- Update gt install to use shared definitions
- Add doctor check that detects missing role beads (warning, not error)
- Doctor --fix creates missing role beads
Fixes#371
Co-authored-by: julianknutsen <julianknutsen@users.noreply.github>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(beads): prevent routes.jsonl corruption from bd auto-export
When issues.jsonl doesn't exist, bd's auto-export mechanism writes
issue data to routes.jsonl, corrupting the routing configuration.
Changes:
- install.go: Create issues.jsonl before routes.jsonl at town level
- manager.go: Create issues.jsonl in rig beads; don't create routes.jsonl
(rig-level routes.jsonl breaks bd's walk-up routing to town routes)
- Add integration tests for routes.jsonl corruption prevention
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(doctor): add check to detect and fix rig-level routes.jsonl
Add RigRoutesJSONLCheck to detect routes.jsonl files in rig .beads
directories. These files break bd's walk-up routing to town-level
routes.jsonl, causing cross-rig routing failures.
The fix unconditionally deletes rig-level routes.jsonl files since
bd will auto-export to issues.jsonl on next run.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test(rig): add verification that routes.jsonl does NOT exist in rig .beads
Add explicit test assertion and detailed comment explaining why rig-level
routes.jsonl files must not exist (breaks bd walk-up routing to town routes).
Also verify that issues.jsonl DOES exist (prevents bd auto-export corruption).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(doctor): ensure town root route exists in routes.jsonl
The RoutesCheck now detects and fixes missing town root routes (hq- -> .).
This can happen when routes.jsonl is corrupted or was created without the
town route during initialization.
Changes:
- Detect missing hq- route in Run()
- Add hq- route in Fix() when missing
- Handle case where routes.jsonl is corrupted (regenerate with town route)
- Add comprehensive unit tests for route detection and fixing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test(beads): fix routing integration test for routes.jsonl corruption
The TestBeadsRoutingFromTownRoot test was failing because bd's auto-export
mechanism writes issue data to routes.jsonl when issues.jsonl doesn't exist.
This corrupts the routing configuration.
Fix: Create empty issues.jsonl after bd init to prevent corruption.
This mirrors what gt install does to prevent the same bug.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: julianknutsen <julianknutsen@users.noreply.github>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When using `gt sling <formula> --on <bead>`, the code was only passing
the `feature` variable (set to bead title). This broke formulas that
expect `issue` (set to bead ID), like mol-polecat-work.
Now passes both common variables:
- feature: bead title (for shiny-style formulas)
- issue: bead ID (for mol-polecat-work-style formulas)
This allows either formula type to work with --on without requiring
the user to manually specify variables.
Fixes#355
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Role beads created by gt install were missing the gt:role label required
by GetRoleConfig(), causing witness startup to fail with:
"bead hq-witness-role is not a role bead (missing gt:role label)"
This regression was introduced in 96970071 which migrated from type-based
to label-based bead classification. The install code used raw exec.Command
instead of the beads API, so it wasn't updated to add labels.
Changes:
- Use bd.CreateWithID() API which auto-converts Type:"role" to gt:role label
- Add RoleLabelCheck doctor migration to fix existing installations
- Add comprehensive unit tests with mocked dependencies
Co-authored-by: julianknutsen <julianknutsen@users.noreply.github>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add severity-based routing for escalations with config-driven targets.
Changes:
- EscalationConfig type with severity routes and external channels
- beads/beads_escalation.go: Escalation bead operations (create/ack/close/list)
- Refactored gt escalate command with subcommands:
- list: Show open escalations
- ack: Acknowledge an escalation
- close: Resolve with reason
- stale: Find unacknowledged escalations past threshold
- show: Display escalation details
- Added TypeEscalationAcked and TypeEscalationClosed event types
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --debug flag for troubleshooting crew attach issues. Shows:
- Current working directory
- Detected rig and crew name
- Computed session ID
- Whether inside tmux
- Which session we are attaching to
Also adds Attaching to session message before attach.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
If the agent bead doesn't exist when gt done tries to clear the hook,
return early instead of failing. This happens for polecats created
before identity beads existed.
gt done must be resilient and forgiving - the important thing is work
gets submitted to merge queue, not that cleanup succeeds.
Fixes: hq-i26n2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>