vrg-finalize-pr¶
Installed as: vrg-finalize-pr (Python console script)
Source: src/vergil_tooling/bin/vrg_finalize_pr.py
Finalizes a pull request and reconciles local state afterwards. Has three modes:
vrg-finalize-pr <PR>— runs the pre-merge provenance check, waits for checks to go green, merges the PR (or confirms it is already merged), then runs the cleanup below. This replaces a manual web merge followed by a separate cleanup step.vrg-finalize-pr(no PR) — interactive: infers the PR from the.worktrees/worktrees and always confirms before acting (see Choosing the PR below). With no candidates, cleanup-only after confirmation: switch to the target branch, fast-forward pull, delete merged local branches, and prune stale remote-tracking references.vrg-finalize-pr --cleanup-only— non-interactive release path: skips inference and merge entirely, never reads stdin, and runs only the cleanup. This is whatvrg-releaseinvokes during its close-finalize phase (issue #1448). Mutually exclusive with a PR argument.
Must be run from the main worktree — the cleanup removes worktrees, which is unsafe when the calling shell's CWD is inside one.
Choosing the PR¶
vrg-finalize-pr <pr-url-or-number>— no prompts; the explicit argument is the confirmation. This is the scriptable path (vrg-submit-prprints the URL to pass here).vrg-finalize-pr(no arguments) — infers candidates by mapping each.worktrees/worktree's branch to its open PR, and always confirms before acting: one candidate asksFinalize PR #N?; several present a menu; none asks before running cleanup-only. Worktrees without an open PR are listed with the reason they were skipped. Inference mode requires an interactive terminal and fails fast unless both stdin and stdout are TTYs — a captured stdout would make the prompts invisible (issue #1448).vrg-finalize-pr --cleanup-only— no prompts and no merge; the scriptable path for callers (likevrg-release) that only want the cleanup.
Waiting for green¶
When the PR's checks are not finished, vrg-finalize-pr waits for
them and merges automatically once everything is green and current.
Doomed outcomes abort immediately rather than after the wait: a draft
PR, merge conflicts, a failed check (named in the error), or a branch
still behind after five update attempts. A branch that is merely
behind the target is updated automatically and the wait restarts.
After the merge, the PR's own branch and worktree are cleaned up
explicitly (a squash merge hides them from git branch --merged),
followed by the usual sweep, pull, and prune.
Usage¶
vrg-finalize-pr [PR | --cleanup-only] [--target-branch BRANCH]
[--strategy {merge,squash,rebase}]
[--allow-provenance-violation] [--dry-run]
Arguments¶
| Argument | Description |
|---|---|
PR |
PR number or URL to merge and finalize. Omit to infer interactively. |
--cleanup-only |
Skip PR inference and merge; run cleanup without prompting or reading stdin (non-interactive release path). Mutually exclusive with PR. |
--target-branch |
Branch to switch to (default: develop) |
--strategy |
Merge strategy when a PR is given (default: squash) |
--allow-provenance-violation |
Proceed despite provenance violations (conscious human override) |
--dry-run |
Show what would be done without making changes |
Behavior¶
1. Provenance Check, Wait, and Merge (PR mode only)¶
Runs the pre-merge provenance check first, so violations surface
before any waiting. Advisories are printed but do not block.
Violations abort the merge unless --allow-provenance-violation
is given. If the PR is already merged, the merge step is skipped and
finalize proceeds straight to cleanup. Otherwise the wait-for-green
loop runs (see Waiting for green) and the PR is merged with the
selected strategy. --dry-run skips the wait and prints what it
would do.
1a. Explicit-Target Cleanup (PR mode only)¶
The just-merged PR branch and its .worktrees/ worktree are deleted
by name. The default squash strategy rewrites history onto the
target, so the branch is never an ancestor and the merged-branch
sweep below cannot see it.
2. Switch to Target Branch¶
Checks out the target branch (default: develop).
3. Fast-Forward Pull¶
Fetches (--tags --force) and fast-forward merges origin/{target}.
4. Delete Merged Branches and Worktrees¶
Deletes local branches merged into the target branch. If a merged
branch is still checked out in a canonical .worktrees/ worktree, that
worktree is removed first (skipped if it has uncommitted changes).
Cached container images for the branch are cleaned.
Two guards keep this sweep from racing parallel agent sessions in
their creation-to-first-commit window (issue #1445), since
git branch --merged classifies a branch just created from the
target's tip as merged:
- Zero-commit branches are skipped. A branch whose tip equals the target's tip carries no merged work, so deleting it saves nothing — and it is exactly what an in-flight issue branch looks like before its first commit.
- Merge evidence is required. A branch is only swept when a closed or merged PR exists for its head; ancestry alone cannot distinguish a merged branch from one created off an older target tip. Branches skipped for lack of evidence are listed with the reason and left for manual cleanup.
Both guards gate the worktree removal as strictly as the branch deletion. The explicit-target cleanup (step 1a) is unaffected — the just-merged PR branch has merge evidence by construction.
Eternal branches are protected based on the branching_model:
| Branching Model | Protected Branches |
|---|---|
docs-single-branch |
develop, gh-pages |
library-release |
develop, main, gh-pages |
application-promotion |
develop, release, main, gh-pages |
5. Prune Remote References¶
Runs git remote prune origin to clean up stale remote-tracking
branches.
6. Working-Tree Cleanliness Gate¶
Fails if the target branch's working tree is not clean, so leftover files are cleaned up before the next issue.
7. Post-Finalization Validation¶
Runs canonical validation via vrg-container-run to catch problems on
the target branch before the next PR is created.
8. CD Workflow Check¶
Inspects the most recent CD workflow run on the target branch and fails if it did not succeed. Docs publishing is async and used to fail silently (issue #303).
Batch mode (comma-list / --all)¶
A comma-separated PR argument (vrg-finalize-pr 123,124,125) or --all
(every open PR in .worktrees/) finalizes several PRs as a single
serialized batch (issue #1673). Each item runs
vrg-finalize-pr <pr> --skip-post-checks (merge + cleanup, deferring
the post-merge checks); after every item merges, one end-of-batch
vrg-finalize-pr --cleanup-only runs validation and the CD check, then
— with --release/--install — a single vrg-release.
Unlike vrg-submit-pr's batch, these PRs are already open, so each one
that lands behind another will update-branch and re-run its gate
(the normal serialized-merge cost). For zero-waste CI, submit the batch
with vrg-submit-pr --all --finalize instead, which rebases each branch
before opening its PR.
The batch asks one confirmation up front (skipped with --yes) and
is fail-fast: the first failure stops it and prints a
merged / failed / not started summary. The single-PR modes are
unchanged.
The --skip-post-checks flag (used internally by the batch) finalizes a
PR but skips the validation and CD-check stages and never chains a
release — the batch runs those once at the end.
Exit Codes¶
| Code | Meaning |
|---|---|
| 0 | Finalization complete, or declined at a confirmation prompt |
| 1 | Provenance violation, unmergeable PR (draft, conflicts, failed checks, stuck behind), not run from main worktree, non-TTY stdin or stdout in inference mode, dirty working tree, failed validation, failed CD run, or a batch item failed |