How no-mistakes Handles PR Targeting from Bare Gate Repositories
The no-mistakes daemon avoids accidental PR edits by explicitly passing --repo and PR identifiers to every gh CLI invocation, refusing to fall back to branch-based inference when running from a detached bare gate repository.
When the no-mistakes pipeline runs inside a bare gate repository—a detached worktree containing only .git metadata with HEAD pointing at the default branch—the gh CLI cannot infer the current repository or branch from the working directory. To prevent targeting errors, the tool implements explicit safeguards that fully qualify every GitHub operation with the correct repository slug and PR identifier.
The Bare Gate Repository Challenge
A bare gate repository is a minimal Git environment created by the daemon (see internal/daemon/manager.go) that lacks a checked-out working tree. In this state, gh pr commands would normally attempt to infer the target PR from the current branch (typically main), leading to "no pull requests found for branch main" errors or, worse, accidental modifications to the wrong PR. The GitHub SCM implementation in internal/scm/github/github.go eliminates this ambiguity through three coordinated mechanisms.
Three Safeguards for Explicit PR Targeting
The github.Host struct ensures deterministic PR operations by combining repository-level and PR-level explicit targeting.
Explicit Repository Flagging with repoArgs()
The Host.repoArgs() method returns []string{"--repo", h.repo} whenever the repository slug (owner/name) is known. Every gh command constructed by the host appends these arguments, guaranteeing that gh resolves the correct remote repository regardless of the process's working directory.
// Simplified from internal/scm/github/github.go
func (h *Host) repoArgs() []string {
if h.repo == "" {
return nil
}
return []string{"--repo", h.repo}
}
This ensures commands like gh pr create or gh pr edit always target owner/repo even when executed from a bare gate directory.
Strict PR Selection via prSelector()
The prSelector(pr *scm.PR) function enforces explicit PR identification by preferring the PR number and falling back to the canonical PR URL. If neither value is available, it returns a hard error:
return "", errors.New("no PR number or URL known; refusing to run gh with a cwd-inferred branch")
This guard prevents the daemon from invoking gh pr <verb> without a specific target, which would otherwise cause gh to infer the PR from the current branch—an operation that always fails or misfires in a bare gate context.
Fork-Aware Head Reference Handling
The headRef(branch string) method generates the correct --head argument for gh pr create. When operating on a fork, it returns <forkOwner>:<branch>; otherwise, it returns the branch name alone. This ensures the GitHub CLI receives the properly qualified owner:branch pair required when the source repository differs from the target.
PR Operations in Practice
These safeguards coordinate across all PR lifecycle methods in internal/scm/github/github.go.
Creating a Pull Request
When CreatePR is invoked from a bare gate, it constructs a fully qualified command:
// Assume h is a *github.Host with repo slug "owner/repo" and forkOwner ""
pr, err := h.CreatePR(ctx, "feature/foo", "main", scm.PRContent{
Title: "Add foo feature",
Body: "This PR implements foo.",
})
The generated command includes both the repository flag and head reference:
gh pr create --head feature/foo --base main --repo owner/repo \
--title "Add foo feature" --body-file -
Updating an Existing PR
UpdatePR uses prSelector to obtain a concrete identifier before appending the repository flag:
existingPR := &scm.PR{Number: "42", URL: "https://github.com/owner/repo/pull/42"}
_, err := h.UpdatePR(ctx, existingPR, scm.PRContent{
Title: "Fix typo",
Body: "Corrected a typo in the README.",
})
This produces:
gh pr edit 42 --repo owner/repo --title "Fix typo" --body-file -
Querying PR State and Checks
Read operations like GetChecks, GetPRState, and GetMergeableState follow the same pattern:
checks, err := h.GetChecks(ctx, existingPR)
Invokes:
gh pr checks 42 --repo owner/repo --json name,state,bucket,completedAt
Validation Through Testing
The unit tests in internal/scm/github/github_test.go verify that bare gate scenarios cannot trigger branch-based inference. A specific test case titled "detached bare gate repo and edit the wrong PR" ensures that UpdatePR fails explicitly rather than falling back to a branch-derived selector. Additional tests confirm that FindPR constructs gh pr list with the correct --head and --repo flags even when operating outside a normal Git checkout.
Summary
- Explicit repository flags: Every
ghcommand includes--repo owner/nameviaHost.repoArgs(), eliminating reliance on the working directory's Git context. - Mandatory PR identifiers: The
prSelectorfunction requires either a PR number or URL, refusing to execute when only branch information is available. - Fork-qualified references: The
headRefmethod correctly formatsowner:branchpairs for cross-fork PR creation. - Test coverage: Unit tests validate that bare gate operations remain deterministic and cannot accidentally target incorrect PRs.
Frequently Asked Questions
What is a bare gate repository in no-mistakes?
A bare gate repository is a detached worktree created by the daemon (defined in internal/branchsync/sync.go as GateDir) that contains only .git metadata with HEAD pointing to the default branch. It serves as a lightweight execution environment for pipelines without requiring a full clone of the source code.
Why can't the gh CLI infer the PR from a bare gate repository?
The gh CLI typically infers the target PR by examining the current Git branch and remote configuration. In a bare gate repository, the working directory is detached and HEAD points to main (or the default branch), so gh would either find no PRs associated with that branch or potentially interact with the wrong PR if multiple exist.
How does no-mistakes prevent editing the wrong PR?
The prSelector function in internal/scm/github/github.go enforces a strict contract: it returns an error if neither a PR number nor URL is provided. This prevents the daemon from invoking gh pr edit or similar commands without an explicit target identifier, eliminating the risk of branch-based inference errors.
Does no-mistakes support PR operations on forks from a bare gate?
Yes. The headRef method detects when a fork is in use and formats the --head argument as <forkOwner>:<branch>. This ensures gh pr create correctly associates the new PR with the proper source repository when the daemon is processing contributions from forked repositories.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →