Bare clones don't have remote.origin.fetch set by default, which breaks
worktrees that need to fetch and see origin/* refs. This caused refinery
to fail because origin/main never appeared after fetch.
- Add configureRefspec() to set standard refspec on bare repos
- Call from CloneBare() and CloneBareWithReference()
- Add BareRepoRefspecCheck to doctor for existing rigs
Closes#286
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Excludes all Claude Code context files to prevent source repo instructions
from interfering with Gas Town agent configuration:
- .claude/ : settings, rules, agents, commands
- CLAUDE.md : primary context file
- CLAUDE.local.md: personal context file
- .mcp.json : MCP server configuration
Legacy configurations (only excluding .claude/) are detected and upgraded
by gt doctor --fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Handle empty repos in ConfigureSparseCheckout (skip read-tree when no HEAD)
- Fix errcheck: wrap fileLock.Unlock() error in defer
- Fix unparam: remove unused *rig.Rig return from getWitnessManager
- Fix unparam: mark unused agentType parameter with blank identifier
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When cloning or creating worktrees from repos that have their own .claude/
directory, those settings would override Gas Town's agent settings. This adds
sparse checkout configuration to automatically exclude .claude/ from all
clones and worktrees.
Changes:
- Add ConfigureSparseCheckout() to git.go, called from all Clone/WorktreeAdd methods
- Add IsSparseCheckoutConfigured() to detect if sparse checkout is properly set up
- Add doctor check to verify sparse checkout config (checks config, not symptoms)
- Doctor --fix will configure sparse checkout for repos missing it
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes gt-v07fl: Polecat lifecycle cleanup for stale worktrees and git
tracking conflicts.
Changes:
1. Add .claude/ to .gitignore (prevents untracked file accumulation)
2. Add beads runtime state patterns to .gitignore (prevents future tracking)
3. Remove .beads/ runtime state from git tracking (mq/, issues.jsonl, etc.)
- Formulas and config remain tracked (needed for go install)
- Created follow-up gt-mpyuq for formulas refactor
4. Add DetectStalePolecats() to polecat manager for identifying cleanup candidates
5. Add CountCommitsBehind() to git package for staleness detection
6. Add `gt polecat stale <rig>` command for stale polecat detection/cleanup
- Shows polecats without active sessions
- Identifies polecats far behind main (configurable threshold)
- Optional --cleanup flag to auto-nuke stale polecats
The existing `gt polecat gc` command handles branch cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- DiscoverRigs() now logs failed rig loads to stderr instead of silently
continuing
- AddRig warnings now output to stderr instead of stdout, matching the
codebase convention for non-fatal warnings
- Added clarifying comment for best-effort git ref update in worktree
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Gas Town agents must push directly to main, not create PRs.
This adds defense-in-depth:
1. .githooks/pre-push - Blocks pushes to non-main branches locally
2. .github/workflows/block-internal-prs.yml - Auto-closes PRs from
the same repo (forks/contributors can still create PRs)
3. internal/git/git.go - Auto-configures core.hooksPath on clone
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
In multi-remote setups, the code may live on a remote other than
"origin" (e.g., "gastown" for gastown.git). The verifyCommitOnMain
function now iterates through all configured remotes to find the
one containing the default branch with the merged commit.
Changes:
- Add git.Remotes() method to list all configured remote names
- Update verifyCommitOnMain to check all remotes/<defaultBranch>
instead of only origin/<defaultBranch>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When repairing a stale polecat worktree, start from origin/<default-branch>
instead of the bare repo's HEAD. This ensures repaired polecats have the
latest fetched commits rather than potentially stale code.
- Add WorktreeAddFromRef to git package for creating worktrees from a ref
- RepairWorktreeWithOptions now uses origin/<default-branch> as start point
- Respects rig's configured default branch (main, master, etc.)
Based on PR #112 by markov-kernel. Test changes from that PR can be
submitted separately.
Closes#101🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: markov-kernel <markov-kernel@users.noreply.github.com>
Adds RemoteDefaultBranch() to git.go that detects the repo's actual
default branch by checking origin/HEAD, then falling back to checking
for origin/master or origin/main.
Updates done.go to use this detection instead of hardcoded "main":
- Line 168: CommitsAhead now uses detected default branch
- Line 173: Error message uses detected branch name
- Line 187: Target branch defaults to detected branch
Fixes repos using 'master' as default branch (pre-2020 repos).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
Use git --reference-if-able when a local repo is provided so rigs and crew share objects without changing remotes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When BranchPushedToRemote fails to use the tracking ref (e.g., due to
missing remote.origin.fetch config in worktrees), fall back to using
git ls-remote to get the remote SHA directly and compare.
This makes gt done more resilient in worktrees where the fetch refspec
may be incomplete or missing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
In worktrees, git push -u origin <branch> may not create the local
refs/remotes/origin/<branch> tracking ref due to missing refspecs.
BranchPushedToRemote now explicitly creates the remote tracking ref
from FETCH_HEAD after fetching if it does not exist locally.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After confirming remote branch exists via ls-remote, fetch to ensure
the local origin/branch ref exists before using it in rev-list comparison.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add WorktreeAddExistingForce to git package (uses --force flag)
- Fix worktree creation: use force flag so main can be checked out
in multiple worktrees (needed for cross-rig work)
- Implement 'gt worktree remove <rig>' with --force flag
- Refuse to remove worktrees with uncommitted changes unless forced
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add DefaultBranch() method to git package to detect repo's default branch
- Store default_branch in rig config.json
- Use detected branch for refinery worktree instead of hardcoding 'main'
- Add LoadRigConfig() to read rig config
- Display correct branch name in rig add output
Fixes wyvern rig creation (uses 'master' not 'main').
Changed polecat branch model to use unique timestamped branches
(polecat/<name>-<timestamp>) instead of reusing persistent branches.
This prevents JSONL drift issues where stale polecat branches don't
have recently created beads.
Changes:
- Add(): create unique branch, simplified (no reuse logic)
- Recreate(): create fresh branch, old ones left for GC
- loadFromBeads(): read actual branch from git worktree
- CleanupStaleBranches(): remove orphaned polecat branches
- ListBranches(pattern): new git helper for branch enumeration
- gt polecat gc: new command to clean up stale branches
🤖 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 recreating a polecat worktree, the branch deletion might fail
silently, leaving a stale branch with old commits. The worktree would
then be created from this stale branch, missing recent main changes.
Fix:
- Add ResetBranch() method to git package for force-updating branches
- Fetch from origin before recreation to ensure fresh commits
- If branch deletion fails, force-reset the branch to origin/main
- This ensures polecats always start with the latest code
Discovered during gt-8tmz swarm when nux polecat was missing the
internal/formula/ directory that was added after its branch diverged.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add .repo.git as shared bare repo for worktrees
- Update polecat manager to use bare repo when available
- Add git.NewGitWithDir() and CloneBare() for bare repo support
- Update gt rig init to create bare repo architecture for new rigs
- Refinery and polecats now share branch visibility via shared .git
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add BranchPushedToRemote() to git package that properly handles
polecat branches without upstream tracking. Update verifyPolecatState
in witness to check that branches are pushed before allowing cleanup.
This prevents the scenario where polecats close issues without pushing
their work, causing all commits to be lost when the worktree is deleted.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive uncommitted work checks before any polecat cleanup:
- Check for uncommitted changes (modified/untracked files)
- Check for stashes
- Check for unpushed commits
Affected commands:
- gt polecat remove: now refuses if uncommitted work exists
- gt rig shutdown: checks all polecats before shutdown
- Witness cleanup: refuses to clean polecats with uncommitted work
- gt spawn: warns if spawning to polecat with uncommitted work
Safety model:
- --force: bypasses uncommitted changes check only
- --nuclear: bypasses ALL safety checks (will lose work)
New git helpers:
- StashCount(): count stashes in repo
- UnpushedCommits(): count commits not pushed to upstream
- CheckUncommittedWork(): comprehensive work status check
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement success handling for the merge queue Engineer:
- Add handleSuccess method that handles successful merge completion
- Update MR body with merge_commit SHA and close_reason
- Close MR with 'merged' reason
- Close source issue with reference to MR ID
- Delete source branch if delete_merged_branches is configured
- Add DeleteRemoteBranch method to git package
- Add git client to Engineer struct
- Add tests for new functionality
Closes gt-3x1.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement 'gt mq integration status <epic>' command that displays:
- Integration branch name and creation date
- Commits ahead of main
- Merged MRs (closed, targeting integration branch)
- Pending MRs (open, targeting integration branch)
Also adds git helpers for BranchCreatedDate and CommitsAhead.
🤖 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>
Add 'gt mq integration land <epic>' command that:
- Verifies all MRs targeting integration/<epic> are merged
- Verifies integration branch exists
- Merges integration/<epic> to main (--no-ff)
- Runs tests on main (if configured)
- Pushes to origin
- Deletes integration branch (local and remote)
- Updates epic status to closed
Options:
- --force: land even if some MRs still open
- --skip-tests: skip test run
- --dry-run: preview only
Also adds:
- MergeNoFF() and DeleteRemoteBranch() to git package
- WorkDir() accessor for git.Git
- Unit tests for mq helper functions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement 'gt mq integration create <epic>' command to create integration
branches for batch work on epics. The command:
1. Verifies the epic exists in beads
2. Creates branch integration/<epic-id> from origin/main
3. Pushes the branch to origin
4. Stores integration branch info in the epic's metadata
Also adds helper methods to git package:
- CreateBranchFrom: create branch from specific ref
- BranchExists: check if local branch exists
- RemoteBranchExists: check if branch exists on remote
Future MRs for the epic's children can target the integration branch
with: gt mq submit --epic <epic-id>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add git helper functions for merge request conflict checking:
- FetchBranch(remote, branch): fetch a specific branch from remote
- CheckConflicts(source, target): test merge to detect conflicts
- Returns list of conflicting files without modifying working directory
- runMergeCheck helper to capture stdout (where CONFLICT appears)
Tests cover clean merges, conflicting merges, and working dir cleanup.
Closes gt-3x1.2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- gt crew at: auto-detect crew from cwd, run gt prime after launch
- Polecats now use git worktrees from refinery (faster than clones)
- Updated architecture.md for two-tier beads mail model
- Town beads (gm-*) for Mayor mail/coordination
- Rig .beads/ symlinks to refinery/rig/.beads
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>