gt witness start and gt refinery start now detect zombie sessions
(tmux alive but Claude dead) and automatically kill and recreate them.
This makes the start commands idempotent:
- If no session exists → create new session
- If session exists and healthy → do nothing (already running)
- If session exists but zombie → kill and recreate
Previously users had to manually run stop then start, or use restart.
Closes: gt-ekc5u
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- startCrewMember: now uses BuildCrewStartupCommand (was GetRuntimeCommand)
- refinery/manager.go: now uses BuildAgentStartupCommand (was GetRuntimeCommand)
Both now properly inject BD_ACTOR and GT_ROLE so seance can identify
sessions correctly. This completes the seance metadata fix started in
the previous commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements priority scoring for merge queue ordering:
## Changes to gt mq list
- Add SCORE column showing priority score (higher = process first)
- Sort MRs by score descending instead of simple priority
- Add CONVOY column showing convoy ID if tracked
## New gt mq next command
- Returns highest-score MR ready for processing
- Supports --strategy=fifo for FIFO ordering fallback
- Supports --quiet for just printing MR ID
- Supports --json for programmatic access
## Changes to Refinery
- Queue() now sorts by priority score instead of simple priority
- Uses ScoreMR from mrqueue package for consistent scoring
## MR Fields Extended
- Added retry_count, last_conflict_sha, conflict_task_id
- Added convoy_id, convoy_created_at for convoy tracking
- These fields feed into priority scoring function
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The refinery was checking git branches instead of the beads merge queue.
This caused MRs to pile up when branches were deleted but MR beads remained.
- manager.go: Queue() now queries beads for type=merge-request issues
- refinery.md.tmpl: Updated queue-scan to use gt mq list
- mol-refinery-patrol.formula.toml: Updated queue-scan step instructions
Remove decision-making logic from Go code and document agent responsibility:
- ProcessMR() now returns error indicating agent handles processing
- Foreground mode deprecated with message directing to background mode
- Retry() no longer calls ProcessMR (agent picks up retried MRs)
- Added ZFC compliance section to refinery role template
- Marked unused helper functions as deprecated (runTests, getMergeConfig, pushWithRetry)
The Refinery agent (Claude) now:
- Runs git commands directly (fetch, checkout, merge, push)
- Detects conflicts and decides: retry, notify polecat, escalate
- Runs tests and decides: proceed, rollback, retry
- Makes all engineering decisions based on command output
Go code provides only primitives: queue listing, status, mail notifications.
(gt-sxa64)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Stats fields from witness and refinery types that tracked
observable metrics (total counts, today counts). These are now
handled by the activity stream/beads system instead.
Removed:
- WitnessStats type and Stats field from Witness
- RefineryStats type and Stats field from Refinery
- LastCheckAt field from Witness
- Stats display from gt witness status
- Stats display from gt refinery status
- Stats increment code from refinery.completeMR()
Kept minimal process state:
- RigName, State, PID, StartedAt (both)
- MonitoredPolecats, Config, SpawnedIssues (witness)
- CurrentMR, PendingMRs, LastMergeAt (refinery)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add merge queue activity events to the refinery:
- merge_started: When refinery begins processing an MR
- merged: When MR successfully merged to main
- merge_failed: When merge fails (conflict, tests, push, etc.)
- merge_skipped: When MR skipped (superseded)
Events include MR ID, worker, branch, and reason (for failures).
Implemented in both Manager.ProcessMR and Engineer.ProcessMRFromQueue.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- polecat.go: Remove unreachable first loop in splitLines (was using filepath.SplitList incorrectly)
- townlog/logger.go: Remove unused Event.JSON() method and json import
- lock/lock.go: Remove unused ErrStaleLock error variable
- refinery/manager.go: Remove unused getTestCommand() method
Note: witness.StatePaused is actually used by cmd/witness.go, not dead code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move duplicated processExists function to shared util package:
- Create internal/util/process.go with ProcessExists function
- Add internal/util/process_test.go with basic tests
- Update witness/manager.go to use util.ProcessExists
- Update refinery/manager.go to use util.ProcessExists
- Remove local processExists functions from both files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevents data loss from concurrent/interrupted state file writes by using
atomic write pattern (write to .tmp, then rename).
Changes:
- Add internal/util package with AtomicWriteJSON/AtomicWriteFile helpers
- Update witness/manager.go saveState to use atomic writes
- Update refinery/manager.go saveState to use atomic writes
- Update crew/manager.go saveState to use atomic writes
- Update daemon/types.go SaveState to use atomic writes
- Update polecat/namepool.go Save to use atomic writes
- Add comprehensive tests for atomic write utilities
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All 156 instances of _ = error suppression in non-test code now have
explanatory comments documenting why the error is intentionally ignored.
Categories of intentional suppressions:
- non-fatal: session works without these - tmux environment setup
- non-fatal: theming failure does not affect operation - visual styling
- best-effort cleanup - defer cleanup on failure paths
- best-effort notification - mail/notifications that should not block
- best-effort interrupt - graceful shutdown attempts
- crypto/rand.Read only fails on broken system - random ID generation
- output errors non-actionable - fmt.Fprint to io.Writer
This addresses the silent failure and debugging concerns raised in the
issue by making the intentionality explicit in the code.
Generated with Claude Code https://claude.com/claude-code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When gt spawns agents (polecats, crew, patrol roles), it now sets the
BD_ACTOR env var so that bd commands (like `bd hook`) know the agent
identity without coupling to gt.
Updated spawn points:
- gt up (mayor, deacon, witness via ensureSession/ensureWitness)
- gt deacon start
- gt witness start
- gt start refinery
- gt mayor start
- Daemon deacon restart
- Daemon lifecycle restart
- Handoff respawn
- Refinery manager start
BD_ACTOR uses slash format (e.g., gastown/witness, gastown/crew/max)
while GT_ROLE may use dash format internally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Architecture changes:
- Refinery created as worktree of mayor clone (shares .git)
- Polecat branches stay local (never pushed to origin)
- MRs stored as wisps in .beads-wisp/mq/ (ephemeral)
- Only main gets pushed to origin after merge
New mrqueue package for wisp-based MR storage.
Updated spawn, done, mq_submit, refinery, molecule templates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create internal/claude package with embedded settings templates
- settings-autonomous.json: gt prime && gt mail check --inject (SessionStart)
- settings-interactive.json: gt prime only (SessionStart)
- Update witness.go: EnsureSettings before session, remove broken gt prime injection
- Update refinery/manager.go: EnsureSettings before session, remove broken NudgeSession
- Update session/manager.go: EnsureSettings for polecats, remove broken issue injection
All autonomous roles (polecat, witness, refinery) now get proper SessionStart hooks
automatically when their sessions are created. No more timing-based gt prime injection.
Wait for Claude to start before sending the prime command, and use
NudgeSession (with 500ms debounce) instead of SendKeysDelayed for
reliable message delivery.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add output field (io.Writer) to Manager and Engineer structs with
SetOutput() methods to enable testability and output redirection.
Replace all 30+ fmt.Printf/Println calls with fmt.Fprintf/Fprintln
using the configurable output writer, defaulting to os.Stdout.
This enables:
- Testing output without capturing stdout
- Redirecting output in different contexts
- Following cobra best practices
Closes: gt-cvfg
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add refinery and crew patterns to identityToSession()
- Add refinery and crew handling to restartSession() with pre-sync
- Add refinery and crew to identityToStateFile()
- Fix gt refinery start to send gt prime after Claude starts
- New syncWorkspace() helper for agents with persistent clones
In foreground mode, skip the tmux session check since we are likely
running inside the session that background mode created. Only check
PID to avoid self-detection.
Fixes the issue where gt refinery start gastown --foreground would
detect its own tmux session as already running.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Refinery now runs as a Claude agent in a tmux session instead of
a Go-based polling loop. This aligns it with how polecats work and
enables intelligent MR processing.
Changes:
- Modified refinery.Start() to spawn Claude session (not gt refinery --foreground)
- Added gt refinery attach command for interactive access to refinery session
- Updated refinery.md.tmpl with comprehensive Claude agent instructions
- Added startup directive in gt prime for refinery role
The --foreground mode is preserved for backwards compatibility but the
default behavior now launches a Claude agent that can review diffs,
run tests, handle conflicts, and notify workers via mail.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tmux status bar theming for Gas Town sessions:
- Per-rig color themes auto-assigned via consistent hashing
- 10 curated dark themes (ocean, forest, rust, plum, etc.)
- Special gold/dark theme for Mayor
- Dynamic status line showing current issue and mail count
- Mayor status shows polecat/rig counts
New commands:
- gt theme --list: show available themes
- gt theme apply: apply to running sessions
- gt issue set/clear: agents update their current issue
- gt status-line: internal command for tmux refresh
Status bar format:
- Left: [rig/worker] role
- Right: <issue> | <mail> | HH:MM
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix ~50 errcheck warnings across the codebase:
- Add explicit `_ =` for intentionally ignored error returns (cleanup,
best-effort operations, etc.)
- Use `defer func() { _ = ... }()` pattern for defer statements
- Handle tmux SetEnvironment, KillSession, SendKeysRaw returns
- Handle mail router.Send returns
- Handle os.RemoveAll, os.Rename in cleanup paths
- Handle rand.Read returns for ID generation
- Handle fmt.Fprint* returns when writing to io.Writer
- Fix for-select with single case to use for-range
- Handle cobra MarkFlagRequired returns
All tests pass. Code compiles without errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The refinery start command was only updating state.json without
actually starting a session. Now it spawns a tmux session named
gt-{rig}-refinery that runs the refinery in foreground mode.
Also updated Stop() and Status() to properly check tmux session
state alongside the PID-based tracking for backwards compatibility.
Fixes: gt-17zr
🤝 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds:
- gt mail send now triggers tmux notification for recipients
- Merge execution with config and retry logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Combined with Dag's mq retry from previous merge.
Full MQ CLI now includes: list, retry, reject subcommands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements gt-3x1.3: Merge execution (merge, test, push)
Changes:
- Add MergeConfig struct with run_tests, test_command, delete_merged_branches,
push_retry_count, and push_retry_delay_ms configuration options
- Add DefaultMergeConfig() with sensible defaults (tests enabled, go test ./...,
branch cleanup, 3 retries with 1s base delay)
- Update ProcessMR to use MergeConfig for all settings
- Add pushWithRetry() with exponential backoff for transient failures
- Add gitOutput() helper to get command stdout (for merge commit SHA)
- Return merge commit SHA in MergeResult on success
- Conditional branch deletion based on config.DeleteMergedBranches
Configuration (in .gastown/config.json):
{
"merge_queue": {
"run_tests": true,
"test_command": "go test ./...",
"delete_merged_branches": true,
"push_retry_count": 3,
"push_retry_delay_ms": 1000
}
}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add 'gt mq retry <rig> <mr-id>' command to retry failed MRs:
- Added GetMR() and Retry() methods to refinery.Manager
- Added RegisterMR() for persistent MR tracking
- Added PendingMRs field to Refinery state
- Created new mq.go command file with retry subcommand
- Support --now flag for immediate processing
- Added comprehensive tests for retry functionality
Closes gt-svi.4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add gt mq command group with reject subcommand
- Add FindMR method to locate MRs by ID or branch
- Add RejectMR method to reject MRs with reason
- Add notifyWorkerRejected for optional mail notification
- Add tests for rejection state transitions
Closes gt-svi.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update MRStatus to use beads-style statuses (open, in_progress, closed)
- Add CloseReason enum for tracking why MRs were closed
- Implement ValidateTransition() to enforce valid state transitions:
- open → in_progress (Engineer claims MR)
- in_progress → closed (merge success or rejection)
- in_progress → open (failure, reassign to worker)
- open → closed (manual rejection)
- closed → anything is blocked (immutable once closed)
- Add convenience methods: Claim(), Close(), Reopen(), SetStatus()
- Add status check methods: IsClosed(), IsOpen(), IsInProgress()
- Update ProcessMR and completeMR to use new state transition methods
- Update display code to handle new status values
- Add comprehensive tests for state transitions
Reference: docs/merge-queue-design.md#state-machine
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Mail commands (send/inbox/read/delete) now wrap bd mail CLI
- Address translation: mayor/ → mayor, rig/polecat → rig-polecat
- Beads stores messages as type=message issues
- Legacy JSONL mode retained for crew workers (local mail)
- Refinery notifications use new mail interface
- Swarm landing notifications use new mail interface
Closes gt-u1j.6, gt-u1j.12
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- notifyWorkerConflict: Mail worker with rebase instructions on conflict
- notifyWorkerMerged: Mail worker on successful merge
- findTownRoot: Walk up to find workspace for mail routing
- High priority notification for conflicts
- Integrates with mail system for agent communication
This completes the semantic merge handling for MVP - conflicts
are intelligently handled by notifying workers rather than
silently failing.
Closes gt-kmn.4
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- internal/refinery: Types for Refinery, MergeRequest, queue items
- internal/refinery: Manager with start/stop/status/queue operations
- gt refinery start: Start refinery for a rig (--foreground option)
- gt refinery stop: Stop running refinery
- gt refinery status: Show refinery state and statistics
- gt refinery queue: Show pending merge requests
- Auto-discover polecat work branches as queue items
- JSON output support for status and queue commands
Closes gt-rm3
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>