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>
The beads.go run() function uses --no-daemon for faster read operations,
but this fails when the database is out of sync with JSONL (e.g., after
the daemon is killed during shutdown before it can sync).
Adding --allow-stale prevents these failures and makes witness/refinery
startup more reliable after gt down --all.
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>
Replace weak "If You're Stuck" section with comprehensive escalation
guidance including:
- When to escalate (specific scenarios)
- How to escalate (gt escalate, mail to Witness, mail to Mayor)
- What to do after escalating (continue or exit cleanly)
- Anti-pattern example showing wrong vs right approach
This prevents polecats from filing beads and passively waiting for
human input, which caused them to appear stuck in sessions.
Fixes: hq-t8zy
The RejectMR function was modifying the in-memory MR object but never
persisting the change to beads storage. This caused rejected MRs to
continue showing in the queue with status "open".
Fix: Call beads.CloseWithReason() to properly close the MR bead before
updating the in-memory state.
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>
Merge polecat/nux-mkd083ff: Updates KillSessionWithProcesses to use
cleaner inline exec.Command style and improved documentation.
Prevents orphan processes that survive tmux kill-session due to
SIGHUP being ignored by Claude processes.
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>
When starting Mayor via 'gt may at', the session now:
1. Works from townRoot (~/gt) instead of mayorDir (~/gt/mayor)
2. Includes startup beacon with explicit instructions in initial prompt
3. Removes redundant post-start nudges (beacon has instructions)
This matches the 'gt handoff' behavior where the agent immediately
knows to check hook and mail on startup.
Fixes: hq-h3449 (P0 escalation - horrendous starting UX)
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>
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>
ZFC violation: InUse was being persisted to JSON and loaded from disk,
but Reconcile() immediately overwrites it with filesystem-derived state.
Changes:
- Mark InUse with json:"-" to exclude from serialization
- Load() now initializes InUse as empty (derived via Reconcile)
- Updated test to verify OverflowNext persists but InUse does not
Per ZFC "Discover, Don't Track", InUse should always be derived from
existing polecat directories, not tracked as separate state.
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 ConvoyWatcher that monitors bd activity for issue closes and
triggers convoy completion checks immediately rather than waiting
for patrol.
- Watch bd activity --follow --town --json for status=closed events
- Query SQLite for convoys tracking the closed issue
- Trigger gt convoy check when tracked issue closes
- Convoys close within seconds of last issue closing
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>
Adds supervision for dispatched dogs that may get stuck.
The new step (between dog-pool-maintenance and orphan-check):
- Lists dogs in "working" state
- Checks work duration vs plugin timeout (default 10m)
- Decision matrix based on how long overdue:
- < 2x timeout: log warning, check next cycle
- 2x-5x timeout: file death warrant
- > 5x timeout: force clear + escalate to Mayor
- Tracks chronic failures for repeat offenders
This closes the supervision gap where dogs could hang forever
after being dispatched via `gt dog dispatch --plugin`.
Closes: gt-s4dp3
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>
The Recorder calls bd commands but wasn't setting the BEADS_DIR
environment variable. This could cause plugin run beads to be
created in the wrong database when redirects are in play.
Fixes: gt-z4ct5
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>
Workers now get primed on the desire-paths philosophy:
- crew.md.tmpl: New "Desire Paths" section before Tips
- polecat.md.tmpl: Updated "Agent UX" section with desire-path label
When a command fails but the guess was reasonable, workers are
encouraged to file a bead with the desire-path label. This helps
improve agent ergonomics by surfacing intuitive command patterns.
References ~/gt/docs/AGENT-ERGONOMICS.md for full philosophy.
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>
The build target was signing the binary, but install just copied
it without re-signing. On macOS, copying can invalidate signatures.
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>
Fix misleading language that could suggest polecats wait in an idle pool:
- refinery/engineer.go: "available polecat" → "fresh polecat (spawned on demand)"
- namepool.go: Clarify this pools NAMES not polecats; polecats are spawned
fresh and nuked when done, only name slots are reused
- dog-pool-architecture.md: "Pool allocation pattern" → "Name slot allocation
pattern (pool of names, not instances)"
There is no idle pool of polecats. They are spawned for work and nuked when done.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>