From 507402dfca48ef691aceb09dbd54c5f3f4d8c0c8 Mon Sep 17 00:00:00 2001 From: chumbucket Date: Sun, 4 Jan 2026 15:12:44 -0800 Subject: [PATCH] fix: Witness checks all remotes for merge verification (gt-ncq26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/ instead of only origin/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/git/git.go | 12 ++++++++++++ internal/witness/handlers.go | 33 +++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/internal/git/git.go b/internal/git/git.go index e95120cf..21c8d95c 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -299,6 +299,18 @@ func (g *Git) RemoteURL(remote string) (string, error) { return g.run("remote", "get-url", remote) } +// Remotes returns the list of configured remote names. +func (g *Git) Remotes() ([]string, error) { + out, err := g.run("remote") + if err != nil { + return nil, err + } + if out == "" { + return nil, nil + } + return strings.Split(out, "\n"), nil +} + // Merge merges the given branch into the current branch. func (g *Git) Merge(branch string) error { _, err := g.run("merge", branch) diff --git a/internal/witness/handlers.go b/internal/witness/handlers.go index 88113230..b5dcf41a 100644 --- a/internal/witness/handlers.go +++ b/internal/witness/handlers.go @@ -750,6 +750,10 @@ func AutoNukeIfClean(workDir, rigName, polecatName string) *NukePolecatResult { // verifyCommitOnMain checks if the polecat's current commit is on the default branch. // This prevents nuking a polecat whose work wasn't actually merged. // +// In multi-remote setups, the code may live on a remote other than "origin" +// (e.g., "gastown" for gastown.git). This function checks ALL remotes to find +// the one containing the default branch with the merged commit. +// // Returns: // - true, nil: commit is verified on default branch // - false, nil: commit is NOT on default branch (don't nuke!) @@ -779,16 +783,33 @@ func verifyCommitOnMain(workDir, rigName, polecatName string) (bool, error) { return false, fmt.Errorf("getting polecat HEAD: %w", err) } - // Verify it's an ancestor of default branch (i.e., it's been merged) - // We use the polecat's git context to check - isOnDefaultBranch, err := g.IsAncestor(commitSHA, "origin/"+defaultBranch) + // Get all configured remotes and check each one for the commit + // This handles multi-remote setups where code may be on a remote other than "origin" + remotes, err := g.Remotes() if err != nil { - // Try without origin/ prefix in case remote isn't set up - isOnDefaultBranch, err = g.IsAncestor(commitSHA, defaultBranch) + // If we can't list remotes, fall back to checking just the local branch + isOnDefaultBranch, err := g.IsAncestor(commitSHA, defaultBranch) if err != nil { return false, fmt.Errorf("checking if commit is on %s: %w", defaultBranch, err) } + return isOnDefaultBranch, nil } - return isOnDefaultBranch, nil + // Try each remote/ until we find one where commit is an ancestor + for _, remote := range remotes { + remoteBranch := remote + "/" + defaultBranch + isOnRemote, err := g.IsAncestor(commitSHA, remoteBranch) + if err == nil && isOnRemote { + return true, nil + } + } + + // Also try the local default branch (in case we're not tracking a remote) + isOnDefaultBranch, err := g.IsAncestor(commitSHA, defaultBranch) + if err == nil && isOnDefaultBranch { + return true, nil + } + + // Commit is not on any remote's default branch + return false, nil }