- Update mol-deacon-patrol formula
- Fix sling helpers, doctor branch check
- Update startup session and tests
- Remove obsolete research doc
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Fix method in BranchCheck was calling git pull --rebase without
a timeout, which could hang indefinitely when network or authentication
issues occurred. Added a 30-second timeout using exec.CommandContext.
Fixes: gt-i5qb
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Polecats weren't getting full role context (including IDLE POLECAT
HERESY guidance) because start prompts said `gt hook` instead of
`gt prime --hook`. The SessionStart hook already runs `gt prime --hook`,
but manual nudge messages were inconsistent.
Changed:
- sling_helpers.go: nudge message now says `gt prime --hook`
- startup.go: assigned beacon now says `gt prime --hook`
- startup_test.go: updated test expectation
Fixes: hq-iqyu9
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Findings:
- Two competing mechanisms: embedded templates vs local-fork edits
- Local-fork created ~200 lines of divergent content in mayor/CLAUDE.md
- TOML config overrides exist but only handle operational config
Recommendation: Extend TOML override system to support [content] sections
for template customization, unifying all override mechanisms.
Cherry-picked from lost commit 123d0b2b. Adds ability to override
embedded role templates at town or rig level:
- Town: <townRoot>/templates/roles/<role>.md.tmpl
- Rig: <rigPath>/templates/roles/<role>.md.tmpl
New APIs:
- NewWithOverrides(townRoot, rigPath string)
- HasRoleOverride(role string) bool
- RoleOverrideCount() int
Recovered by: gt-vjhf
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
getIssueDetailsBatch was using runCmd for bd show, which doesn't set
cmd.Dir. This caused bd to use default routing instead of the town's
routes.jsonl, leading to dashboard slowness or missing data.
Use runBdCmd(f.townBeads, ...) to ensure proper database routing,
consistent with other bd commands in fetcher.go.
(gt-0v19)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --no-daemon --allow-stale flags to runBdCommand in mail/bd.go,
matching the pattern used in beads/beads.go. This avoids daemon IPC
overhead for mail operations and prevents stale sync errors.
Recovered from lost commit 2f960462.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a polecat runs gt done after work is complete, it should notify the
dispatcher (the agent that slung the work). This notification was failing
silently when the polecat's worktree was deleted before gt done finished.
The issue was that getDispatcherFromBead() used ResolveBeadsDir(cwd) which
relies on the polecat's .beads/redirect file. If the worktree is deleted
(e.g., by Witness cleanup), the redirect file is gone and bead lookup fails.
Fix: Use ResolveHookDir(townRoot, issueID, cwd) instead. ResolveHookDir uses
prefix-based routing via routes.jsonl which works regardless of worktree
state. This ensures dispatcher notifications are sent reliably even when
the worktree is cleaned up before gt done completes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add EnsureCustomTypes call to createAutoConvoy (sling) and
executeConvoyFormula (formula) to ensure the 'convoy' type is
registered before attempting to create convoy beads.
This fixes "validation failed: invalid issue type: convoy" errors
that occurred when convoy creation was attempted before custom types
were configured in the beads database.
Fixes: hq-ledua
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Configure checkout.workers=0 (auto-detect CPU count) on all clone
operations. Git 2.33+ supports this feature which parallelizes file
creation during checkout, significantly speeding up worktree creation.
This is applied to:
- Clone() - regular clones
- CloneWithReference() - clones with local reference
- CloneBare() - bare clones (primary source for worktrees)
- CloneBareWithReference() - bare clones with reference
The config is set per-repo so worktrees inherit it automatically.
Older git versions silently ignore this config (non-fatal).
Recovered from: 4ed3e983 (lost commit)
When agents hook beads from different prefixes (e.g., rig worker hooking
hq-* bead), the status check now uses ResolveHookDir to find the correct
database for fetching the hooked bead.
Also adds fallback scanning of town-level beads for rig-level roles when
no hooked beads are found locally.
Fixes: gt-rphsv
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The `gt hook` command was failing to persist hooks for beads from different
prefixes (e.g., hooking an hq-* bead from a rig worker). The issue was that
`runHook` used `b.Update()` which always writes to the local beads database,
regardless of the bead's prefix.
Changes:
- Use `beads.ResolveHookDir()` to determine the correct database directory
for the bead being hooked, based on its prefix
- Execute `bd update` with the correct working directory for cross-prefix routing
- Call `updateAgentHookBead()` to set the agent's hook_bead slot, enabling
`gt hook status` to find cross-prefix hooked beads
- Add integration test for cross-prefix hooking scenarios
This matches the pattern already used by `gt sling` for cross-prefix dispatch.
Fixes: gt-rphsv
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the gt binary is built from a local fork (e.g., ~/src/gastown),
the staleness check would incorrectly warn about being stale because
it compared against the rig's repo HEAD. This confused agents.
The fix detects fork builds by checking if the binary's embedded
commit exists in the target repo. If not, the binary was built from
a different repo and we report "fork build" instead of "stale".
Changes:
- Add IsForkBuild field to StaleBinaryInfo
- Add commitExistsInRepo helper to detect fork scenarios
- Update gt stale command to show "Binary built from fork" status
- Update doctor check to report fork builds as OK
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC path for List operations was not converting opts.Type to a label,
causing all issues to be returned when the daemon was running. This resulted
in gt mq list showing all beads (including wisps) instead of just merge-requests.
The subprocess fallback path had this conversion, but RPC did not.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When many rigs are registered, the tmux statusline would truncate or
overflow. This adds a configurable maximum (default 5) with an overflow
indicator showing how many rigs are hidden (e.g., "+3").
Running rigs are prioritized (shown first) due to existing sort order.
Configure via GT_MAX_RIGS_DISPLAY env var:
- Default: 5 rigs shown
- Set to 0 for unlimited
- Set to any positive number for custom limit
Fixes: h-4wtnc
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TestIsAgentRunning and TestEnsureSessionFresh_ZombieSession were flaky
because they checked the pane command immediately after NewSession,
before the shell had fully initialized. Added WaitForShellReady calls
to wait for shell readiness before assertions.
Closes: gt-jzwx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Multiple gt commands call git rev-parse --show-toplevel, adding ~50ms
each invocation. Results rarely change within a session, and multiple
agents calling git concurrently contend on .git/index.lock.
Add cached RepoRoot() and RepoRootFrom() functions to the git package
and update all callers to use them. This ensures a single git subprocess
call per process for the common case of checking the current directory's
repo root.
Files updated:
- internal/git/git.go: Add RepoRoot() and RepoRootFrom()
- internal/cmd/prime.go: Use cached git.RepoRoot()
- internal/cmd/molecule_status.go: Use cached git.RepoRoot()
- internal/cmd/sling_helpers.go: Use cached git.RepoRoot()
- internal/cmd/rig_quick_add.go: Use git.RepoRootFrom() for path arg
- internal/version/stale.go: Use cached git.RepoRoot()
Closes: bd-2zd.5
storeDispatcherInBead and storeAttachedMoleculeInBead were calling
bd show/update without --no-daemon, while all other sling operations
used --no-daemon. This inconsistency could cause daemon socket hangs
if the daemon was in a bad state during sling operations.
Changes:
- Add --no-daemon --allow-stale to bd show calls in both functions
- Add --no-daemon to bd update calls in both functions
- Add empty stdout check for bd --no-daemon exit 0 bug
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add CrewRegistryConfig to RigEntry allowing crew members to be defined
in rigs.json and synced across machines. The new `gt crew sync` command
creates missing crew members from the configuration.
Configuration example:
"rigs": {
"gastown": {
"crew": {
"theme": "mad-max",
"members": ["diesel", "chrome", "nitro"]
}
}
}
Closes: gt-tu4
Replace bd subprocess spawns with direct SQLite queries:
- queryEpicsInDir: direct sqlite3 query vs bd list subprocess
- getLinkedConvoys: direct JOIN query vs bd dep list + getIssueDetails loop
- computeGoalLastMovement: reuse epic.UpdatedAt vs separate bd show call
Also includes mailbox optimization from earlier session:
- Consolidated multiple parallel queries into single bd list --all query
- Filters in Go instead of spawning O(identities × statuses) bd processes
177x improvement (6.2s → 35ms) by eliminating subprocess overhead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace bd subprocess calls in gt commands with daemon RPC when available.
Each subprocess call has ~40ms overhead for Go binary startup, so using
the daemon's Unix socket protocol significantly reduces latency.
Changes:
- Add RPC client to beads package (beads_rpc.go)
- Modify List/Show/Update/Close methods to try RPC first, fall back to subprocess
- Replace runBdPrime() with direct content output (avoids bd subprocess)
- Replace checkPendingEscalations() to use beads.List() with RPC
- Replace hook.go bd subprocess calls with beads package methods
The RPC client:
- Connects to daemon via Unix socket at .beads/bd.sock
- Uses JSON-based request/response protocol (same as bd daemon)
- Falls back gracefully to subprocess if daemon unavailable
- Lazy-initializes connection on first use
Performance improvement targets (from bd-2zd.2):
- gt prime < 100ms (was 5.8s with subprocess chain)
- gt hook < 100ms (was ~323ms)
Closes: bd-2zd.2
The previous approach using KillPaneProcessesExcluding/KillPaneProcesses
killed the pane's main process (Claude/node) before calling RespawnPane.
This caused the pane to close (since tmux's remain-on-exit is off by default),
which then made RespawnPane fail because the target pane no longer exists.
The respawn-pane -k flag handles killing atomically - it kills the old process
and starts the new one in a single operation without closing the pane in between.
If orphan processes remain (e.g., Claude ignoring SIGHUP), they will be cleaned
up when the new session starts or by periodic cleanup processes.
This fixes both self-handoff and remote handoff paths.
Fixes: hq-bv7ef
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The `gt plugin run` command was recording a "success" run even though it
only prints plugin instructions for an agent/user to execute - it doesn't
actually run the plugin.
This poisoned the cooldown gate: CountRunsSince counted these false
successes, preventing actual executions from running because the gate
appeared to have recent successful runs.
Remove the recording from `gt plugin run`. The actual plugin execution
(by whatever follows the printed instructions) should record the result.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Under high concurrency (17+ agents), the bd version check spawns
multiple git subprocesses per invocation, causing timeouts when
85-120+ git processes compete for resources.
This fix:
- Caches successful version checks to ~/.cache/gastown/beads-version.json
- Uses cached results for 24 hours to avoid subprocess spawning
- On timeout, uses stale cache if available or gracefully degrades
- Prints warning when using cached/degraded path
Fixes: https://github.com/steveyegge/gastown/issues/503
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Stop hook with `gt costs record` was causing 30-second timeouts
on every session stop due to beads socket connection issues. Since
cost tracking is disabled anyway (Claude Code doesn't expose session
costs), this hook provided no value.
Changes:
- Remove Stop hook from settings-autonomous.json and settings-interactive.json
- Remove Stop hook validation from claude_settings_check.go
- Update tests to not expect Stop hook
The cost tracking infrastructure remains in costs.go for future use
when Claude Code exposes session costs via API or environment variable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add assignee display to both list and single-goal views. In list view,
assignee appears on the second line when present. In single-goal view,
it appears as a dedicated field after priority. JSON output also includes
the assignee field.
Closes: gt-libj
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The getCurrentWork function was returning ANY in_progress bead from the
workspace rather than only beads assigned to the current agent. This caused
crew workers to see wisps assigned to polecats in their status bar.
Changes:
- Add identity parameter to getCurrentWork function
- Add identity guard (return empty if identity is empty)
- Filter by Assignee in the beads query
This complements the earlier getHookedWork fix and ensures both hooked
AND in_progress beads are filtered by the agent's identity.
Fixes gt-zxnr (additional fix).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: tmux statusline showed wrong hook for all java crewmembers
because GT_CREW env var wasn't set in tmux session environment.
Changes:
- statusline.go: Add early return in getHookedWork() when identity is empty
to prevent returning ALL hooked beads regardless of assignee
- crew_at.go: Call SetEnvironment in the restart path so sessions created
before GT_CREW was being set get it on restart
Fixes gt-zxnr.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
KillPaneProcesses was killing ALL processes in the pane, including the
gt handoff process itself. This created a race condition where the
process could be killed before RespawnPane executes, causing the pane
to close prematurely and requiring manual reattach.
Added KillPaneProcessesExcluding() function that excludes specified PIDs
from being killed. The handoff command now passes its own PID to avoid
the race condition.
Fixes: gt-85qd
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When deacon patrol molecules completed, their child step wisps were not being
closed automatically. This caused orphan wisp accumulation - 143+ orphaned
wisps were found in one cleanup session.
The fix ensures that when a molecule completes (via gt done or gt mol step done),
all descendant step issues are recursively closed before the molecule itself.
Changes:
- done.go: Added closeDescendants() call in updateAgentStateOnDone before
closing the attached molecule
- molecule_step.go: Added closeDescendants() call in handleMoleculeComplete
for all roles (not just polecats)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Deacon patrol formula now clearly documents the continuous loop:
1. Execute patrol steps (inbox-check through context-check)
2. Squash wisp, wait for activity via await-signal (15min max)
3. Create new patrol wisp and hook it
4. Repeat from step 1
Changes:
- Formula description emphasizes CONTINUOUS EXECUTION with flow diagram
- loop-or-exit step renamed to "Continuous patrol loop" with explicit
instructions for creating/hooking new wisps after await-signal
- plugin-run step now clearly shows gt plugin list + gt dog dispatch
- Deacon role template updated to match formula changes
- Formula version bumped to 9
Fixes gt-fm2c: Deacon needs continuous patrol loop for plugin dispatch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gt goals was only querying the default beads location (town-level
with hq- prefix), missing epics from rig-level beads (j-, sc-, etc.).
Now iterates over all rig directories with .beads/ subdirectories
and aggregates epics, deduplicating by ID.
Wisp molecules (gt-wisp-* IDs, mol-* titles) are transient operational
beads for witness/refinery/polecat patrol, not strategic goals that
need human attention. These are now filtered by default.
Add --include-wisp flag to show them when debugging.
Fixes gt-ysmj
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add `bd tree <id>` to Key Commands in bd prime template (beads.go)
- Add `bd tree <issue>` to prime_output.go for mayor/polecat/crew roles
- Helps agents understand bead ancestry, siblings, and dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add three new flags for filtering convoys by epic relationship:
- --orphans: show only convoys without a parent epic
- --epic <id>: show only convoys under a specific epic
- --by-epic: group convoys by parent epic
These support the Goals Layer feature (Phase 3) for hierarchical
focus management.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements gt goals command to show epics sorted by staleness × priority.
Features:
- List all open epics with staleness indicators (🟢/🟡/🔴)
- Sort by attention score (priority × staleness hours)
- Show specific goal details with description and linked convoys
- JSON output support
- Priority and status filtering
Staleness thresholds:
- 🟢 active: moved in last hour
- 🟡 stale: no movement for 1+ hours
- 🔴 stuck: no movement for 4+ hours
Closes: gt-vix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create goals.go with basic command structure for viewing strategic
goals (epics) with staleness indicators. Includes --json, --status,
and --priority flags. Implementation stubs return not-yet-implemented
errors.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit guidance on the Mayor → Crew → Polecats delegation model:
- Crew are coordinators for epics/goals needing decomposition
- Polecats are executors for well-defined tasks
- Include decision framework table for work type routing
Closes: gt-9jd
Implements the Overseer Experience epic (gt-k0kn):
- gt focus: Shows stalest high-priority goals, sorted by priority × staleness
- gt attention: Shows blocked items, PRs awaiting review, stuck workers
- gt status: Now includes GOALS and ATTENTION summary sections
- gt convoy list: Added --orphans, --epic, --by-epic flags
These commands reduce Mayor bottleneck by giving the overseer direct
visibility into system state without needing to ask Mayor.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit guidance on the Mayor → Crew → Polecats delegation model:
- Crew are coordinators for epics/goals needing decomposition
- Polecats are executors for well-defined tasks
- Include decision framework table for work type routing
Closes: gt-9jd
Adds clear guidance that crew members are coordinators, not implementers:
- Lists 4 key responsibilities: Research, Decompose, Sling, Review
- Clarifies "goal-specific mayor" model - own outcomes via delegation
- Documents when to implement directly vs delegate (trivial fixes, spikes, etc.)
Closes: gt-gig
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --convoy flag to gt sling that allows adding an issue to an existing
convoy instead of creating a new one. When specified:
- Validates the convoy exists and is open
- Adds tracking relation between convoy and issue
- Skips auto-convoy creation
Changes:
- Add slingConvoy variable and --convoy flag registration
- Add addToExistingConvoy() helper function in sling_convoy.go
- Modify auto-convoy logic to check slingConvoy first
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add flag variable declarations and Cobra flag registrations for:
- --epic: link auto-created convoy to parent epic
- --convoy: add to existing convoy instead of creating new
Closes: gt-n3o
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change molecule step completion instructions to use `gt mol step done`
instead of `bd close`. This ensures polecats get fresh context between
each step, which is critical for multi-step review workflows like
shiny-enterprise where each refinement pass should have unbiased attention.
The `gt mol step done` command already:
1. Closes the step
2. Finds the next ready step
3. Respawns the pane for fresh context
But polecats were being instructed to use `bd close` directly, which
skipped the respawn and let them run through entire workflows in a
single session with accumulated context.
Updated:
- prime_molecule.go: step completion instructions
- mol-polecat-work.formula.toml
- mol-polecat-code-review.formula.toml
- mol-polecat-review-pr.formula.toml
Fixes: hq-0kx7ra
Three fixes to make dog dispatch work end-to-end:
1. Add BuildDogStartupCommand in loader.go
- Similar to BuildPolecatStartupCommand/BuildCrewStartupCommand
- Passes AgentName to AgentEnv so BD_ACTOR is exported in startup command
2. Use BuildDogStartupCommand in dog.go
- Removes ineffective SetEnvironment calls (env vars set after shell starts
don't propagate to already-running processes)
3. Add "dog" case in mail_identity.go detectSenderFromRole
- Dogs now use BD_ACTOR for mail identity
- Without this, dogs fell through to "overseer" and couldn't find their mail
Tested: dog alpha now correctly sees inbox as deacon/dogs/alpha
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Recovered from reflog - these commits were lost during a rebase/force-push.
Dogs are directories with state files but no sessions. When `gt dog dispatch`
assigned work and sent mail, nothing executed because no session existed.
Changes:
1. Spawn tmux session after dispatch (gt-<town>-deacon-<dogname>)
2. Set BD_ACTOR=deacon/dogs/<name> so dogs can find their mail
3. Add dog case to AgentEnv for proper identity
Session spawn is non-blocking - if it fails, mail was sent and human can
manually start the session.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>