fix(branch): honor --gate-review in gx branch finish - #677
Merged
NagyVikt merged 2 commits intoJul 9, 2026
Merged
Conversation
`gx branch finish` passed its argv straight to agent-branch-finish.sh via invokePackageAsset, bypassing src/finish/index.js where runReviewGate lives. Two consequences: the script exits 1 on the unknown `--gate-review` argument, and its --via-pr path merges the moment the PR opens (the unconditional `gh pr merge` before the wait/auto fallbacks). So the documented default workflow could never gate, and merged fail-open. Split the gx-level gate flags out of the script's argv and run runReviewGate before invoking the script. It throws on a dirty review, red CI, or a PR GitHub will not merge, so the script -- and the merge -- never runs. Unrelated flags (--auto-resolve, --no-preflight, ...) still reach the script untouched. This is the gap that let lifted.sk-storefront PR #298 merge with its `review` check skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Code review caught a wrong-merge-target hazard. The gate resolved the base with resolveBaseBranch, which only knows the explicit --base, the global config, and the detected default. agent-branch-finish.sh instead honors the per-branch branch.<name>.guardexBase when --base is omitted (agent-branch-finish.sh:504), as does `gx finish` via resolveFinishBaseBranch. With `branch.agent/x.guardexBase=dev` and no --base, the gate would open and review a PR against main while the shell merged into dev — reviewing one base and merging into another. Use resolveFinishBaseBranch so both agree. Cover it, plus the inline --branch=/--base= form and the no-gate-flag passthrough that every repo depends on. The suite's git stub now exposes resolveFinishBaseBranch, so a regression to the old helper fails loudly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NagyVikt
deleted the
agent/claude/branch-finish-honor-gate-review-2026-07-09-12-52
branch
July 9, 2026 12:31
NagyVikt
added a commit
that referenced
this pull request
Aug 6, 2026
* fix(branch): forward --review-provider to the merge gate
`gx ship` / `gx finish` honor `--review-provider` — args.js parses it and
finish/index.js hands the whole options object to runReviewGate. `gx branch
finish --gate-review` passed a bare `options: {}`, so the gate always ran
review-gate.js's `codex` default no matter what the caller asked for.
On a machine where codex is unavailable that makes the gate unusable: it fails
closed on every run, and the only way to land anything is --skip-review-gate —
the gate switched off by the very mechanism meant to enforce it. Which is the
same failure mode the --gate-review routing (#677) was added to prevent.
The flag and its value are consumed here rather than passed through, because
agent-branch-finish.sh exits 1 on the unknown argument (and would otherwise see
a bare "claude" positional). An unknown provider throws before the script runs,
so a typo cannot silently downgrade to the default.
A bare --gate-review is unchanged: reviewProvider is undefined and
review-gate.js applies its own default.
* fix(branch): reject --review-provider with no value
args.js throws "requires a value of codex|claude" when the value is missing;
branch.js silently left reviewProvider undefined, so the gate fell back to its
codex default. A caller who asked for claude and mistyped would be gated by
codex without being told — the same silent-fallback failure this change set out
to remove.
A missing value now becomes "" so the existing validation rejects it.
---------
Co-authored-by: NagyVikt <nagy.viktordp@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
gx branch finishpassed its argv straight toagent-branch-finish.shviainvokePackageAsset, bypassingsrc/finish/index.jswhererunReviewGatelives. Two consequences:--gate-reviewargument.--via-prpath callsgh pr merge --squashunconditionally right after opening the PR (agent-branch-finish.sh:1267), before the wait/auto fallbacks — i.e. it merges fail-open.So the workflow every repo's CLAUDE.md documents as the default could never gate, and merged without one.
review-gate.js's own header already noted this ("can fail open (it merged PR #610 to main with red preflight tests)") — the gate existed, but onlygx ship/gx finishever ran it.This is the gap that let
lifted.sk-storefrontPR #298 merge to production with itsreviewcheck skipped.Change
runReviewGatebefore invoking the script. It throws on a dirty review, red CI, or a PR GitHub will not merge, so the script — and the merge — never runs.--auto-resolve,--no-preflight, …) still reach the script untouched.resolveFinishBaseBranch, matching how the shell resolves an omitted--base(per-branchbranch.<name>.guardexBase). Resolving it differently would review one base and merge into another.Verification
test/branch-gate-review.test.js(8 tests): gate runs, flag stripped, fail-closed (a throwing gate never invokes the script), opt-outs, HEAD fallback, per-branch base, inline--branch=/--base=, and a byte-for-byte passthrough guard for callers without the flag.branch.js.mainbaseline (this repo is baseline-red; the failing set is byte-identical).gx branch finish --gate-reviewon a storefront branch refused to merge when the review provider errored — "Refusing to merge."Known follow-ups (from review, not blocking)
options: {}hard-codes providercodex+requireChecks;--review-provider/--allow-no-checksare not parsed on this path and would reach the shell as unknown args.GUARDEX_AUTO_SHIP=1does not enable the gate here, thoughargs.jsdocuments that it should.🤖 Generated with Claude Code