Commit Graph

994 Commits

Author SHA1 Message Date
gastown/crew/dennis
e30e46a87a feat(mail): add queue management commands
Add beads-native queue management commands to gt mail:
- gt mail queue create <name> --claimers <pattern>
- gt mail queue show <name>
- gt mail queue list
- gt mail queue delete <name>

Also enhanced QueueFields struct with CreatedBy and CreatedAt fields
to support queue metadata tracking.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:29:37 -08:00
gastown/crew/jack
2ffc8e8712 feat(mail): implement beads-native gt mail claim command
Implement claiming for queue messages using beads-native approach:

- Add claim_pattern field to QueueFields for eligibility checking
- Add MatchClaimPattern function for pattern matching (wildcards supported)
- Add FindEligibleQueues to find all queues an agent can claim from
- Rewrite runMailClaim to use beads-native queue lookup
- Support optional queue argument (claim from any eligible if not specified)
- Use claimed-by/claimed-at labels instead of changing assignee
- Update runMailRelease to work with new claiming approach
- Add comprehensive tests for pattern matching and validation

Queue messages are now claimed via labels:
  - claimed-by: <agent-identity>
  - claimed-at: <RFC3339 timestamp>

Messages with queue:<name> label but no claimed-by are unclaimed.

Closes gt-xfqh1e.11

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:25:11 -08:00
gastown/crew/max
bf8bddb004 feat(mail): add channel viewing and management commands
Add gt mail channel subcommands for beads-native channels:
- gt mail channel [name] - list channels or show messages
- gt mail channel list - list all channels
- gt mail channel show <name> - show channel messages
- gt mail channel create <name> [--retain-count=N] [--retain-hours=N]
- gt mail channel delete <name>

Channels are pub/sub streams for broadcast messaging with retention policies.
Messages are stored with channel:<name> label and retrieved via beads queries.

Part of gt-xfqh1e.12 (channel viewing task).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:22:00 -08:00
gastown/crew/max
42999d883d feat(mail): update mail send to use address resolver
Integrate the new address resolver into gt mail send:
- Resolves addresses to determine delivery mode (agent, queue, channel)
- Queue/channel: single message delivery
- Agent/group/pattern: fan-out to all resolved recipients
- Falls back to legacy routing if resolver fails
- Shows resolved recipients when fan-out occurs

Supports all new address types:
- Direct: gastown/crew/max
- Patterns: */witness, gastown/*
- Groups: @ops-team (beads-native groups)
- Queues: queue:work-requests
- Channels: channel:alerts

Part of gt-xfqh1e.10 (mail send update task).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:19:54 -08:00
gastown/crew/max
b3b980fd79 feat(mail): add group management commands
Add gt mail group subcommands:
- gt mail group list - list all groups
- gt mail group show <name> - show group details
- gt mail group create <name> [members...] - create new group
- gt mail group add <name> <member> - add member
- gt mail group remove <name> <member> - remove member
- gt mail group delete <name> - delete group

Includes validation for group names and member patterns.
Supports direct addresses, wildcards, @-patterns, and nested groups.

Part of gt-xfqh1e.7 (group commands task).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:18:20 -08:00
gastown/crew/jack
8eafcc8a16 feat(mail): extend message bead for queues/channels
Add queue/channel routing fields to message beads:
- queue: string (queue name, mutually exclusive with to/channel)
- channel: string (channel name, mutually exclusive with to/queue)
- claimed_by: string (who claimed queue message)
- claimed_at: timestamp (when claimed)

Messages can now be direct (To), queued (Queue), or broadcast (Channel).
Added constructors NewQueueMessage/NewChannelMessage, type helpers
IsQueueMessage/IsChannelMessage/IsDirectMessage/IsClaimed, and
Validate() for mutual exclusivity checks.

Also fixes build error in mail_queue.go (QueueConfig struct nil comparison).

Closes gt-xfqh1e.4

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:14:36 -08:00
Steve Yegge
42d9890e5c fix(deacon): improve health check reliability and error handling (#499)
Co-authored-by: Dylan <sigfawn@gmail.com>
2026-01-13 22:34:03 -08:00
Julian Knutsen
e7ca4908dc refactor(config): remove BEADS_DIR from agent environment and add doctor check (#455)
* fix(sling_test): update test for cook dir change

The cook command no longer needs database context and runs from cwd,
not the target rig directory. Update test to match this behavior
change from bd2a5ab5.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(tests): skip tests requiring missing binaries, handle --allow-stale

- Add skipIfAgentBinaryMissing helper to skip tests when codex/gemini
  binaries aren't available in the test environment
- Update rig manager test stub to handle --allow-stale flag

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(config): remove BEADS_DIR from agent environment

Stop exporting BEADS_DIR in AgentEnv - agents should use beads redirect
mechanism instead of relying on environment variable. This prevents
prefix mismatches when agents operate across different beads databases.

Changes:
- Remove BeadsDir field from AgentEnvConfig
- Remove BEADS_DIR from env vars set on agent sessions
- Update doctor env_check to not expect BEADS_DIR
- Update all manager Start() calls to not pass BeadsDir

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(doctor): detect BEADS_DIR in tmux session environment

Add a doctor check that warns when BEADS_DIR is set in any Gas Town
tmux session. BEADS_DIR in the environment overrides prefix-based
routing and breaks multi-rig lookups - agents should use the beads
redirect mechanism instead.

The check:
- Iterates over all Gas Town tmux sessions (gt-* and hq-*)
- Checks if BEADS_DIR is set in the session environment
- Returns a warning with fix hint to restart sessions

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>
2026-01-13 22:13:57 -08:00
sigfawn
3cf77b2e8b fix(daemon): improve error handling and security (#445)
* fix(beads): cache version check and add timeout to prevent cli lag

* fix(mail_queue): add nil check for queue config

Prevents potential nil pointer panic when queue config exists
in map but has nil value. Added || queueCfg == nil check to
the queue lookup condition in runMailClaim function.

Fixes potential panic that could occur if a queue entry exists
in config but with a nil value.

* fix(migrate_agents_test): fix icon expectations to match actual output

The printMigrationResult function uses icons with two leading spaces
("  ✓", "  ⊘", "  ✗") but the test expected icons without spaces.
This fixes the test expectations to match the actual output format.

* fix(hook): handle error from events.LogFeed

Previously the error from LogFeed was silently ignored with _.
Now we log the error to stderr at warning level but don't fail
the operation since the primary hook action succeeded.

* fix(tmux): security and error handling improvements

- Fix unchecked regexp error in IsClaudeRunning (CVE-like)
- Add input sanitization to SetPaneDiedHook to prevent shell injection
- Add session name validation to SetDynamicStatus
- Sanitize mail from/subject in SendNotificationBanner
- Return error on parse failure in GetEnvironment
- Track skipped lines in ListSessionIDs for debuggability

See: tmux.fix for full analysis

* fix(daemon): improve error handling and security

- Capture stderr in syncWorkspace for better debuggability
- Fail fast on git fetch failures to prevent stale code
- Add logging to previously silent bd list errors
- Change notification state file permissions to 0600
- Improve error messages with actual stderr content

This prevents agents from starting with stale code and provides
better visibility into daemon operations.
2026-01-13 22:13:54 -08:00
Julian Knutsen
a1195cb104 fix(crew): prevent restart when attaching to crew session with running agent (#491)
* fix(sling_test): update test for cook dir change

The cook command no longer needs database context and runs from cwd,
not the target rig directory. Update test to match this behavior
change from bd2a5ab5.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(tests): skip tests requiring missing binaries, handle --allow-stale

- Add skipIfAgentBinaryMissing helper to skip tests when codex/gemini
  binaries aren't available in the test environment
- Update rig manager test stub to handle --allow-stale flag

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(crew): prevent restart when attaching to session with running agent

When running `gt crew at <name>` while already inside the target tmux
session, the command would unconditionally start the agent, causing
Claude to restart even if it was already running.

Add IsAgentRunning check before starting the agent when already in
the target session, matching the behavior for the external attach case.

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>
2026-01-13 22:13:47 -08:00
Julian Knutsen
80af0547ea chore: fix build break (#483)
* fix(sling_test): update test for cook dir change

The cook command no longer needs database context and runs from cwd,
not the target rig directory. Update test to match this behavior
change from bd2a5ab5.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(tests): skip tests requiring missing binaries, handle --allow-stale

- Add skipIfAgentBinaryMissing helper to skip tests when codex/gemini
  binaries aren't available in the test environment
- Update rig manager test stub to handle --allow-stale flag

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>
2026-01-13 22:13:35 -08:00
Keith Wyatt
08755f62cd perf(tmux): batch session queries in gt down (#477)
* perf(tmux): batch session queries in gt down to reduce N+1 subprocess calls

Add SessionSet type to tmux package for O(1) session existence checks.
Instead of calling HasSession() (which spawns a subprocess) for each
rig/session during shutdown, now calls ListSessions() once and uses
in-memory map lookups.

Changes:
- internal/tmux/tmux.go: Add SessionSet type with GetSessionSet() and Has()
- internal/cmd/down.go: Use SessionSet for dry-run checks and session stops
- internal/session/town.go: Add StopTownSessionWithCache() variant
- internal/tmux/tmux_test.go: Add test for SessionSet

With 5 rigs, this reduces subprocess calls from ~15 to 1 during shutdown
preview, saving 60-150ms of execution time.

Closes: gt-xh2bh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* perf(tmux): optimize SessionSet to avoid intermediate slice allocation

- Build map directly from tmux output instead of calling ListSessions()
- Use strings.IndexByte for efficient newline parsing
- Pre-size map using newline count to avoid rehashing
- Simplify nil checks in Has() and Names()

* fix(sling): restore bd cook directory context for formula-on-bead mode

The bd cook command needs to run from the target rig's directory to
access the correct formula database. This was accidentally removed
in a previous commit, causing TestSlingFormulaOnBeadRoutesBDCommandsToTargetRig
to fail.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 22:07:05 -08:00
Johann Dirry
5d96243414 fix: Windows build support with platform-specific process/signal handling
Separate platform-dependent code into build-tagged files:
- process_unix.go / process_windows.go: isProcessRunning() implementation
- signals_unix.go / signals_windows.go: daemon signal handling (Windows lacks SIGUSR1)

Windows implementation uses windows.OpenProcess with PROCESS_QUERY_LIMITED_INFORMATION
and checks exit code against STILL_ACTIVE (259).

Original-PR: #447
Co-Authored-By: Johann Dirry <johann.dirry@microsea.at>
2026-01-13 20:59:15 -08:00
gastown/crew/jack
60da5de104 feat(identity): add gt commit wrapper and gt trail command
gt-f6mkz: Agent git identity
- Add `gt commit` wrapper that sets git author from agent identity
- Identity mapping: gastown/crew/jack → gastown.crew.jack@gastown.local
- Add `agent_email_domain` to TownSettings (default: gastown.local)
- Add `gt config agent-email-domain` command to manage domain

gt-j1m5v: gt trail command
- Add `gt trail` with aliases `gt recent` and `gt recap`
- Subcommands: commits, beads, hooks
- Flags: --since, --limit, --json, --all
- Filter commits by agent email domain

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 19:34:29 -08:00
gastown/refinery
8660641009 fix(tests): prevent sling tests from inheriting TMUX_PANE
Merge polecat/nux-mkd36irl: Clears TMUX_PANE env var in tests to
prevent test failures when running inside tmux.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:15:16 -08:00
mayor
4ee1a4472d fix(done,mayor): push branch before MR creation, restart runtime on attach
done.go: Push branch to origin BEFORE creating MR bead (hq-6dk53, hq-a4ksk)
- The MR bead triggers Refinery to process the branch
- If branch isnt pushed, Refinery finds nothing to merge
- The worktree gets nuked at end of gt done, losing commits forever
- This is why polecats kept submitting MRs with empty branches

mayor.go: Restart runtime with context when attaching (hq-95xfq)
- When runtime has exited, gt may at now respawns with startup beacon
- Previously, attaching to dead session left agent with no context
- Now matches gt handoff behavior: hook check, inbox check, full prime

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:53:28 -08:00
joe
5882039715 fix(mail_queue): remove invalid nil check for struct type
QueueConfig is a struct, not a pointer, so comparing to nil is invalid.
The `!ok` check is sufficient for map key existence.

Fixes build error introduced in PR #437.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 17:52:04 -08:00
Keith Wyatt
7d8d96f7f9 perf(up): parallelize all agent startup with concurrency limit (#476)
* perf(up): parallelize agent startup with worker pool and channel-based collection

- Run daemon, deacon, mayor, and rig prefetch all in parallel (4-way concurrent init)
- Use fixed worker pool instead of goroutine-per-task for bounded concurrency
- Replace mutex-protected maps with channel-based result collection (zero lock contention)
- Pre-allocate maps with known capacity to reduce allocations
- Use string concatenation instead of fmt.Sprintf for display names
- Reduce `gt up` startup time from ~50s to ~10s for towns with multiple rigs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(lint): fix errcheck and misspell issues in orphans.go

- Check error return from fmt.Scanln calls
- Fix "Cancelled" -> "Canceled" spelling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:46:50 -08:00
sigfawn
69110309cc fix(mail): refactor duplicated inbox logic and fix clear race condition (#435) 2026-01-13 13:45:25 -08:00
sigfawn
aa0bfd0c40 fix(hook): handle error from events.LogFeed (#440)
* fix(beads): cache version check and add timeout to prevent cli lag

* fix(mail_queue): add nil check for queue config

Prevents potential nil pointer panic when queue config exists
in map but has nil value. Added || queueCfg == nil check to
the queue lookup condition in runMailClaim function.

Fixes potential panic that could occur if a queue entry exists
in config but with a nil value.

* fix(migrate_agents_test): fix icon expectations to match actual output

The printMigrationResult function uses icons with two leading spaces
("  ✓", "  ⊘", "  ✗") but the test expected icons without spaces.
This fixes the test expectations to match the actual output format.

* fix(hook): handle error from events.LogFeed

Previously the error from LogFeed was silently ignored with _.
Now we log the error to stderr at warning level but don't fail
the operation since the primary hook action succeeded.
2026-01-13 13:40:57 -08:00
Julian Knutsen
1453b8b592 fix(handoff): use correct witness working directory (#444)
The witness role doesn't have a /rig worktree like the refinery does.
The handoff command was trying to cd to <rig>/witness/rig which doesn't
exist, causing the respawned pane to fail immediately and the session
to die.

Changed witness workdir from <rig>/witness/rig to <rig>/witness.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:39:55 -08:00
Julian Knutsen
65c5e05c43 fix(polecat): kill orphan sessions and clear stale hooks during allocation (#448)
ReconcilePool now detects and kills orphan tmux sessions (sessions without
corresponding polecat directories). This prevents allocation from being
blocked by broken state from crashed polecats.

Changes:
- Add tmux to Manager to check for orphan sessions during reconciliation
- Add ReconcilePoolWith for testable session/directory reconciliation logic
- Always clear hook_bead slot when reopening agent beads (fixes stale hooks)
- Prune stale git worktree entries during reconciliation

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:37:00 -08:00
Julian Knutsen
bd2a5ab56a fix(sling): fix formula lookup in --on mode (#422) (#449)
Reviewed: Fix is correct - cook runs from cwd for formula access, wisp gets GT_ROOT for formula lookup.
2026-01-13 13:36:07 -08:00
Julian Knutsen
f32a63e6e5 feat(done): complete self-cleaning by killing tmux session (#450)
Polecats now fully clean up after themselves on `gt done`:
- Step 1: Nuke worktree (existing behavior)
- Step 2: Kill own tmux session (new)

This completes the "done means gone" model - both worktree and
session are terminated. Previously the session survived as a zombie.

Audit logging added to both systems:
- townlog: EventKill for `gt log` visibility
- events: TypeSessionDeath with structured payload

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:34:49 -08:00
Subhrajit Makur
c61b67eb03 fix(config): implement role_agents support in BuildStartupCommand (#19) (#456)
* fix(config): implement role_agents support in BuildStartupCommand

The role_agents field in TownSettings and RigSettings existed but was
not being used by the startup command builders. All services fell back
to the default agent instead of using role-specific agent assignments.

Changes:
- BuildStartupCommand now extracts GT_ROLE from envVars and uses
  ResolveRoleAgentConfig() for role-based agent selection
- BuildStartupCommandWithAgentOverride follows the same pattern when
  no explicit override is provided
- refinery/manager.go uses ResolveRoleAgentConfig with constants
- cmd/start.go uses ResolveRoleAgentConfig with constants
- Updated comments from hardcoded agent name to generic "agent"
- Added ValidateAgentConfig() to check agent exists and binary is in PATH
- Added lookupAgentConfigIfExists() helper for validation
- ResolveRoleAgentConfig now warns to stderr and falls back to default
  if configured agent is invalid or binary is missing

Resolution priority (now working):
1. Explicit --agent override
2. Rig's role_agents[role] (validated)
3. Town's role_agents[role] (validated)
4. Rig's agent setting
5. Town's default_agent
6. Hardcoded default fallback

Adds tests for:
- TestBuildStartupCommand_UsesRoleAgentsFromTownSettings
- TestBuildStartupCommand_RigRoleAgentsOverridesTownRoleAgents
- TestBuildAgentStartupCommand_UsesRoleAgents
- TestValidateAgentConfig
- TestResolveRoleAgentConfig_FallsBackOnInvalidAgent

Fixes: role_agents configuration not being applied to services

* fix(config): add GT_ROOT to BuildStartupCommandWithAgentOverride

- Fixes missing GT_ROOT and GT_SESSION_ID_ENV exports in
  BuildStartupCommandWithAgentOverride, matching BuildStartupCommand behavior
- Adds test for override priority over role_agents
- Adds test verifying GT_ROOT is included in command

This addresses the Greptile review comment about agents started with
an override not having access to town-level resources.

Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
2026-01-13 13:34:22 -08:00
gus
ff6c02b15d fix(lint): fix errcheck and misspell in orphans.go
- Check fmt.Scanln return values (errcheck)
- Fix "Cancelled" → "Canceled" spelling (misspell)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:32:13 -08:00
beads/crew/emma
bedccb1634 fix(handoff): use workspace.FindFromCwd for town root detection
detectTownRootFromCwd() only checked for mayor/town.json, but
workspace.FindFromCwd() also accepts mayor/ directory as a secondary
marker. This fixes handoff failing in workspaces without town.json.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:27:25 -08:00
Steve Yegge
275910b702 Merge pull request #461 from sauerdaniel/pr/sling-fixes
fix(sling): auto-attach work molecule and handle dead polecats
2026-01-13 13:22:05 -08:00
Daniel Sauer
fdd4b0aeb0 test: Add test coverage for 16 files (40.3% → 45.5%) (#463)
* test: Add test coverage for 16 files (40.3% -> 45.5%)

Add comprehensive tests for previously untested packages:
- internal/agent/state_test.go
- internal/cmd/errors_test.go
- internal/crew/types_test.go
- internal/doctor/errors_test.go
- internal/dog/types_test.go
- internal/mail/bd_test.go
- internal/opencode/plugin_test.go
- internal/rig/overlay_test.go
- internal/runtime/runtime_test.go
- internal/session/town_test.go
- internal/style/style_test.go
- internal/ui/markdown_test.go
- internal/ui/terminal_test.go
- internal/wisp/io_test.go
- internal/wisp/types_test.go
- internal/witness/types_test.go

style_test.go uses func(...string) to match lipgloss variadic Render signature.

* fix(lint): remove unused error return from buildCVSummary

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.
2026-01-13 13:19:27 -08:00
Keith Wyatt
f42ec42268 fix(sling): register hq-cv- prefix for convoy beads (#475)
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>
2026-01-13 13:19:15 -08:00
beads/crew/emma
8051c8bdd7 feat(hook): auto-detect agent in gt hook show
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`.

Fixes steveyegge/beads#1078

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 13:17:51 -08:00
Daniel Sauer
c0526f244e fix(lint): remove unused error return from buildCVSummary (#466)
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.
2026-01-13 13:16:44 -08:00
Will Saults
bda248fb9a feat(refinery,boot): add --agent flag for model selection (#469)
* 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>
2026-01-13 13:14:47 -08:00
gastown/refinery
73a349e5ee fix(tests): resolve test failures in costs and polecat tests
Merge polecat/dementus-mkcdzdlu: Test fixes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 12:09:16 -08:00
dementus
a2607b5b72 fix(tests): resolve test failures in costs and polecat tests
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>
2026-01-13 12:07:50 -08:00
gastown/refinery
18893e713a feat(orphans): add list and kill subcommands for Claude process orphans
Merge polecat/rictus-mkd0azo9: Adds `gt orphans procs` command group
for managing orphaned Claude processes (PPID=1).

- `gt orphans procs` / `gt orphans procs list` - list orphan processes
- `gt orphans procs kill [-f]` - kill orphan processes with confirmation

Resolves conflict with existing `gt orphans kill` (for git commits) by
placing process orphan commands under `procs` subcommand.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 12:07:00 -08:00
rictus
ea12679a5a feat(orphans): add list and kill subcommands for Claude process orphans
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>
2026-01-13 12:02:38 -08:00
rictus
a43c89c01b feat(orphans): add kill command to remove orphaned commits
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>
2026-01-13 11:54:52 -08:00
nux
e043f4a16c feat(tmux): add KillSessionWithProcesses for explicit process termination
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>
2026-01-13 11:53:57 -08:00
dementus
87fde4b4fd feat(spawn): migrate to NewSessionWithCommand pattern
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>
2026-01-13 11:06:21 -08:00
mayor
e083317cc3 fix(lint): remove unused error return from buildCVSummary
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.
2026-01-13 17:44:15 +01:00
mayor
7924921d17 fix(sling): auto-attach work molecule and handle dead polecats
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
2026-01-13 14:01:49 +01:00
mayor
791b388a93 chore: add design docs and ready command
- Add convoy-lifecycle.md design doc
- Add formula-resolution.md design doc
- Add mol-mall-design.md design doc
- Add ready.go command implementation
- Move dog-pool-architecture.md to docs/design/
- Update .gitignore for beads sync files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 03:24:42 -08:00
dementus
38bedc03e8 feat(spawn): migrate to NewSessionWithCommand pattern
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>
2026-01-13 01:27:03 -08:00
capable
e7b0af0295 fix(done): verify commits exist before completing (hq-xthqf)
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>
2026-01-13 00:58:04 -08:00
dementus
f9ca7bb87b fix(done): handle getcwd errors when worktree deleted (hq-3xaxy)
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>
2026-01-13 00:17:59 -08:00
rictus
392ff1d31b feat(convoy): add --owner flag for targeted completion notifications
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>
2026-01-13 00:03:02 -08:00
george
58207a00ec refactor(mrqueue): remove mrqueue package, use beads for MRs (gt-dqi)
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>
2026-01-12 23:48:56 -08:00
mayor
15cfb76c2c feat(crew): accept rig name as positional arg in crew status
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>
2026-01-12 23:07:49 -08:00
nux
2d8949a3d3 feat(polecat): add identity show command with CV summary
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>
2026-01-12 22:55:39 -08:00