Safe Merge Review
Outcome
Treat "merge succeeded" and "merge is correct" as two different things, and produce verifiable evidence for every field of the Reporting skeleton at the end of this file — that field list is the definition of done.
Trigger Matrix
| Trigger |
Required context |
Path |
"Merge feature/foo into the current branch" |
repo path + source ref |
Path 1 + Path 2 |
| "Check whether this merge missed anything" |
repo path + source ref or merge commit |
Path 1 + Path 3 |
| "How should this conflict be resolved, and can I push after resolving it" |
repo path + conflicted files + source ref |
Path 1 + Path 2 |
| "The corresponding branches in these repos all need merging; help me confirm whether it is correct" |
repo list + source refs |
Path 1 + Path 2 |
| "This branch looks already merged; help me prove whether it is really included" |
repo path + source ref or merge commit |
Path 3 |
| "Review this merge request before we merge it" |
merge request link or id |
resolve to refs first, then Path 1 + Path 2 |
A merge request link is a pointer, not a ref pair. Resolve it before any path runs:
read the request's source branch, target branch, and current head sha from the
forge (the gitlab skill or glab/gh when available), then restate them as the
source ref and target branch this review is actually about, and confirm the local
repo has both fetched. A request retargeted or force-pushed since it was opened
still shows its original title — trust the head sha you just read, not the link.
Context Sources
Path 1 collects the repo scope, worktree state, and merge evidence step by step. Before starting, scan instead for the boundaries that change how those steps run, because each one invalidates a default the workflow would otherwise take:
- A dirty worktree, multi-repo coordination, submodules, binary files, or large numbers of renames — none of these are handled by a plain diff model
- The repo's history strategy (fast-forward, merge commit, squash, or a rewritten history) — it decides which completeness proof is even valid
- Whether a networked
fetch is required, and whether it is available
Environment prerequisites: a working git CLI with read access for modeling or auditing, and write access only for Path 2; judging a remote source ref usually requires a networked fetch.
Bundled Resources
Load these on demand instead of cramming every detail into the main flow:
- When you need command templates, the strategy matrix, patch-equivalent, or completeness-verification methods, read references/merge-workflow.md
- When you need to judge hotspot risk, conflict semantics, or post-merge logical-mismatch patterns, read references/merge-review-checklist.md
- After the refs are locked down, run scripts/build_merge_evidence.py with
--collect --repo <path> --source-ref <ref> to derive the read-only Git facts and a stable reporting skeleton in one bounded output. For manual fields and unfilled-marker behavior, read references/merge-workflow.md section 9, "Reporting skeleton".
Workflow Paths
Path 1: Model the diff and decide the merge plan
- Stabilize the worktree.
- First check
git status --short --branch
- Confirm the actual branch and worktree with
git rev-parse --abbrev-ref HEAD + git worktree list; do not rely on a shell prompt or statusline (it can be stale or wrong). When the user named a target branch or worktree, assert HEAD matches it before editing or pushing — if it does not, stop and correct, rather than acting on the wrong line.
- A dirty worktree is not merged directly by default; first state the risk, then decide whether to continue
- Lock down the source and target refs.
- Clarify the source ref, the remote, and the target branch (normally the current branch you merge into)
- When the source ref is unclear, do not guess "the latest line"
- Fetch the latest state and model the diff.
- Fetch the locked source ref, then use the evidence script's
--collect mode for merge base, left/right counts, incoming commits, and hotspot intersection; inspect its residual-risk line if a long list was truncated
- When the history shows signs of rebase / squash / rewrite, additionally run the patch-equivalent check
- Identify the hotspot overlap and do a semantic pre-review.
- Prioritize reviewing shared logic, public interfaces, config, schema, migrations, build scripts, tests, and generated artifacts that both sides changed
- For high-risk files, review item by item per references/merge-review-checklist.md
- Choose a merge strategy.
- When the source is already included, report
already contained directly
- For a non-trivial merge, default to a reviewable path: inspect the staged result first, then land the final commit
Path 2: Execute the merge and prove the result is correct
- Execute the chosen merge strategy.
- Even fast-forward candidates first complete diff modeling and semantic pre-review
- For a non-trivial merge, review the staged result first by default; do not treat "no text conflicts" as "no logical conflicts"
- Any commit this path lands (merge commit or conflict-resolution commit) must not carry AI/agent provenance in its message — no attribution, generation disclosure, tool/model name, or signature marker such as
Co-Authored-By: Claude, Generated with Claude Code, or 🤖; strip any such line a global default, template, or harness convention injects before committing; the same goes for content you author while resolving conflicts — do not introduce AI-provenance comments or markers into the resolved files
- Resolve conflicts using three-way evidence.
- For each conflicted file, look at base / ours / theirs
- Record the final resolution and why no necessary semantics from the other side were lost
- Prove "complete merge".
- Re-run the evidence script's
--collect mode against the final HEAD
- Prove the source ref is included in
HEAD
- Prove
HEAD..<source-ref> is empty
- For a squash merge,
is-ancestor does not apply; choose an alternative proof method per references/merge-workflow.md section 7.5, "Squash merge completeness verification", and annotate proof-method
- List the files and diffs that actually landed
- Do another post-merge semantic re-review.
- Check whether the final code is just one side's logic winning by mistake
- Focus on shared boundaries, initialization chains, configuration closure, default resources, and upstream/downstream repo coordination
- Run the minimal relevant verification.
- Run only the verification commands that could actually fail because of this merge
- In multi-repo scenarios, record per repo; do not collapse into a single "all passed"
- When the diff's own updated tests only assert configuration shape (counts, JSON structure) and never exercise the runtime, disk, or external state where this merge could actually fail, a green run is not evidence — trace the downstream consumer's code path and simulate the post-merge pipeline (for example a re-pin /
bump / apply against the tracked ref) by reading it
- Decide whether to allow a push.
- Push only when the user explicitly requests it or the process explicitly requires it
- When the change registers or references an externally-sourced artifact (a skill, package, submodule pin, generated asset), gate the merge on that artifact already being published on the exact ref the config tracks (
git ls-remote the tracked branch), not merely present in a local unpushed commit — otherwise the post-merge pipeline resolves the tracked ref and hard-fails on the missing artifact
- If any gate is skipped, you must explicitly state the reason and the residual risk
Path 3: Audit a completed merge
- Lock down the audit target.
- Clarify whether you are auditing a specific merge commit, a specific source ref, or the current worktree result
- Reconstruct the expected diff.
- Recompute the merge base, incoming commits, file sets, and hotspot overlap
- Do not equate "there is no diff now" with "it was merged correctly back then"
- On parallel/independent baseline lines, the same logical change often lands via a different commit and issue id on each line;
is-ancestor <sha>, a commit-id search, and an issue-number search can all report "missing" while the content is actually present. Judge "does this branch contain the fix" by the file content / patch, not the commit graph or issue id (see references/merge-workflow.md section 3.4, "Parallel baseline lines").
- Check completeness and semantics.
- Cross-check the source ref, the landed files, and the final code
- Focus on the post-merge error patterns in references/merge-review-checklist.md
- Run the minimal relevant verification and produce a conclusion.
- The conclusion can only be
Green / Yellow / Red
- It must come with an evidence matrix and residual risks
Failure and Escalation
Stop or escalate, instead of continuing to guess, when:
- The source ref, target ref, or remote is unclear
- A dirty worktree would contaminate the merge evidence, but the user has not yet confirmed a handling strategy
- You cannot
fetch the latest source state but still need to judge a remote branch
- A destructive action is required (such as
reset, checkout --, or force-overwriting the conflict result), but the user has not yet approved it
- In a multi-repo coordination, some repo lacks context, lacks a source ref, or lacks a verification command
- You cannot provide a minimal relevant verification, so you can only report "not verified" and cannot claim completion
Reporting
After completing, report at least the following:
Safe merge review summary
The skeleton and field order come from scripts/build_merge_evidence.py; what each field means:
- repo: the repository under review
- current branch: the target branch
HEAD actually points to
- source ref: the exact ref being merged in
- merge base: the common ancestor all diff modeling is based on
- left/right counts: commits exclusive to each side
- incoming key commits: the source-side commits that matter semantically
- hotspot overlap files: files both sides changed since the merge base
- dirty worktree status: worktree state and how it was handled
- merge strategy: already-contained / fast-forward / no-ff / squash, and why
- conflicted files and reasoning: each conflict and why the resolution loses no needed semantics
- completeness proof: the evidence that the source landed fully
- proof method: (is-ancestor | patch-equivalent | tree-diff | cherry-pick-noop)
- semantic review conclusion: result of the post-merge semantic re-review
- verification command(s): the minimal relevant verification actually run
- push status: pushed / not pushed, and the gate decision
- residual risks: anything skipped, unverified, or still risky
For a multi-repo scenario, report per repo; do not substitute a single "all merged fine".
1---2name: safe-merge-review3description: Use when the user wants to merge a branch, a remote ref, or the corresponding branches across a set of related repos into the current working branch, or wants to review whether "is this branch ready to merge", "this merge is correct", "anything was missed", "the conflict resolution is reliable", or "it is safe to push after the merge". Applies when the user provides a branch name, remote ref, repo path, conflicted files, a merge commit, a merge request link, or a multi-repo set of branches; also when confirming a fix is really present on a parallel release line that commit-id or is-ancestor searches report as missing, and when a merge decision turns on another repo's dependency not yet on the tracked ref. Proves the merge is correct, not merely that git merge ran. Not for branch code-quality review while no merge, audit, or conflict is in play.4---56# Safe Merge Review78## Outcome910Treat "merge succeeded" and "merge is correct" as two different things, and produce verifiable evidence for every field of the Reporting skeleton at the end of this file — that field list is the definition of done.1112## Trigger Matrix1314| Trigger | Required context | Path |15| --- | --- | --- |16| "Merge `feature/foo` into the current branch" | repo path + source ref | Path 1 + Path 2 |17| "Check whether this merge missed anything" | repo path + source ref or merge commit | Path 1 + Path 3 |18| "How should this conflict be resolved, and can I push after resolving it" | repo path + conflicted files + source ref | Path 1 + Path 2 |19| "The corresponding branches in these repos all need merging; help me confirm whether it is correct" | repo list + source refs | Path 1 + Path 2 |20| "This branch looks already merged; help me prove whether it is really included" | repo path + source ref or merge commit | Path 3 |21| "Review this merge request before we merge it" | merge request link or id | resolve to refs first, then Path 1 + Path 2 |2223A merge request link is a pointer, not a ref pair. Resolve it before any path runs:24read the request's source branch, target branch, and current head sha from the25forge (the `gitlab` skill or `glab`/`gh` when available), then restate them as the26source ref and target branch this review is actually about, and confirm the local27repo has both fetched. A request retargeted or force-pushed since it was opened28still shows its original title — trust the head sha you just read, not the link.2930## Context Sources3132Path 1 collects the repo scope, worktree state, and merge evidence step by step. Before starting, scan instead for the boundaries that change how those steps run, because each one invalidates a default the workflow would otherwise take:3334- A dirty worktree, multi-repo coordination, submodules, binary files, or large numbers of renames — none of these are handled by a plain diff model35- The repo's history strategy (fast-forward, merge commit, squash, or a rewritten history) — it decides which completeness proof is even valid36- Whether a networked `fetch` is required, and whether it is available3738Environment prerequisites: a working git CLI with read access for modeling or auditing, and write access only for Path 2; judging a remote source ref usually requires a networked `fetch`.3940## Bundled Resources4142Load these on demand instead of cramming every detail into the main flow:4344- When you need command templates, the strategy matrix, patch-equivalent, or completeness-verification methods, read [references/merge-workflow.md](references/merge-workflow.md)45- When you need to judge hotspot risk, conflict semantics, or post-merge logical-mismatch patterns, read [references/merge-review-checklist.md](references/merge-review-checklist.md)46- After the refs are locked down, run [scripts/build_merge_evidence.py](scripts/build_merge_evidence.py) with `--collect --repo <path> --source-ref <ref>` to derive the read-only Git facts and a stable reporting skeleton in one bounded output. For manual fields and unfilled-marker behavior, read [references/merge-workflow.md](references/merge-workflow.md) section 9, "Reporting skeleton".4748## Workflow Paths4950### Path 1: Model the diff and decide the merge plan51521. Stabilize the worktree.53 - First check `git status --short --branch`54 - Confirm the actual branch and worktree with `git rev-parse --abbrev-ref HEAD` + `git worktree list`; do not rely on a shell prompt or statusline (it can be stale or wrong). When the user named a target branch or worktree, assert HEAD matches it before editing or pushing — if it does not, stop and correct, rather than acting on the wrong line.55 - A dirty worktree is not merged directly by default; first state the risk, then decide whether to continue562. Lock down the source and target refs.57 - Clarify the source ref, the remote, and the target branch (normally the current branch you merge into)58 - When the source ref is unclear, do not guess "the latest line"593. Fetch the latest state and model the diff.60 - Fetch the locked source ref, then use the evidence script's `--collect` mode for merge base, left/right counts, incoming commits, and hotspot intersection; inspect its residual-risk line if a long list was truncated61 - When the history shows signs of rebase / squash / rewrite, additionally run the patch-equivalent check624. Identify the hotspot overlap and do a semantic pre-review.63 - Prioritize reviewing shared logic, public interfaces, config, schema, migrations, build scripts, tests, and generated artifacts that both sides changed64 - For high-risk files, review item by item per [references/merge-review-checklist.md](references/merge-review-checklist.md)655. Choose a merge strategy.66 - When the source is already included, report `already contained` directly67 - For a non-trivial merge, default to a reviewable path: inspect the staged result first, then land the final commit6869### Path 2: Execute the merge and prove the result is correct70711. Execute the chosen merge strategy.72 - Even fast-forward candidates first complete diff modeling and semantic pre-review73 - For a non-trivial merge, review the staged result first by default; do not treat "no text conflicts" as "no logical conflicts"74 - Any commit this path lands (merge commit or conflict-resolution commit) must not carry AI/agent provenance in its message — no attribution, generation disclosure, tool/model name, or signature marker such as `Co-Authored-By: Claude`, `Generated with Claude Code`, or `🤖`; strip any such line a global default, template, or harness convention injects before committing; the same goes for content you author while resolving conflicts — do not introduce AI-provenance comments or markers into the resolved files752. Resolve conflicts using three-way evidence.76 - For each conflicted file, look at base / ours / theirs77 - Record the final resolution and why no necessary semantics from the other side were lost783. Prove "complete merge".79 - Re-run the evidence script's `--collect` mode against the final `HEAD`80 - Prove the source ref is included in `HEAD`81 - Prove `HEAD..<source-ref>` is empty82 - For a squash merge, `is-ancestor` does not apply; choose an alternative proof method per [references/merge-workflow.md](references/merge-workflow.md) section 7.5, "Squash merge completeness verification", and annotate `proof-method`83 - List the files and diffs that actually landed844. Do another post-merge semantic re-review.85 - Check whether the final code is just one side's logic winning by mistake86 - Focus on shared boundaries, initialization chains, configuration closure, default resources, and upstream/downstream repo coordination875. Run the minimal relevant verification.88 - Run only the verification commands that could actually fail because of this merge89 - In multi-repo scenarios, record per repo; do not collapse into a single "all passed"90 - When the diff's own updated tests only assert configuration shape (counts, JSON structure) and never exercise the runtime, disk, or external state where this merge could actually fail, a green run is not evidence — trace the downstream consumer's code path and simulate the post-merge pipeline (for example a re-pin / `bump` / `apply` against the tracked ref) by reading it916. Decide whether to allow a push.92 - Push only when the user explicitly requests it or the process explicitly requires it93 - When the change registers or references an externally-sourced artifact (a skill, package, submodule pin, generated asset), gate the merge on that artifact already being published on the exact ref the config tracks (`git ls-remote` the tracked branch), not merely present in a local unpushed commit — otherwise the post-merge pipeline resolves the tracked ref and hard-fails on the missing artifact94 - If any gate is skipped, you must explicitly state the reason and the residual risk9596### Path 3: Audit a completed merge97981. Lock down the audit target.99 - Clarify whether you are auditing a specific merge commit, a specific source ref, or the current worktree result1002. Reconstruct the expected diff.101 - Recompute the merge base, incoming commits, file sets, and hotspot overlap102 - Do not equate "there is no diff now" with "it was merged correctly back then"103 - On parallel/independent baseline lines, the same logical change often lands via a **different commit and issue id** on each line; `is-ancestor <sha>`, a commit-id search, and an issue-number search can all report "missing" while the content is actually present. Judge "does this branch contain the fix" by the **file content / patch**, not the commit graph or issue id (see [references/merge-workflow.md](references/merge-workflow.md) section 3.4, "Parallel baseline lines").1043. Check completeness and semantics.105 - Cross-check the source ref, the landed files, and the final code106 - Focus on the post-merge error patterns in [references/merge-review-checklist.md](references/merge-review-checklist.md)1074. Run the minimal relevant verification and produce a conclusion.108 - The conclusion can only be `Green / Yellow / Red`109 - It must come with an evidence matrix and residual risks110111## Failure and Escalation112113Stop or escalate, instead of continuing to guess, when:114115- The source ref, target ref, or remote is unclear116- A dirty worktree would contaminate the merge evidence, but the user has not yet confirmed a handling strategy117- You cannot `fetch` the latest source state but still need to judge a remote branch118- A destructive action is required (such as `reset`, `checkout --`, or force-overwriting the conflict result), but the user has not yet approved it119- In a multi-repo coordination, some repo lacks context, lacks a source ref, or lacks a verification command120- You cannot provide a minimal relevant verification, so you can only report "not verified" and cannot claim completion121122## Reporting123124After completing, report at least the following:125126### Safe merge review summary127128The skeleton and field order come from [scripts/build_merge_evidence.py](scripts/build_merge_evidence.py); what each field means:129130- repo: the repository under review131- current branch: the target branch `HEAD` actually points to132- source ref: the exact ref being merged in133- merge base: the common ancestor all diff modeling is based on134- left/right counts: commits exclusive to each side135- incoming key commits: the source-side commits that matter semantically136- hotspot overlap files: files both sides changed since the merge base137- dirty worktree status: worktree state and how it was handled138- merge strategy: already-contained / fast-forward / no-ff / squash, and why139- conflicted files and reasoning: each conflict and why the resolution loses no needed semantics140- completeness proof: the evidence that the source landed fully141- proof method: (is-ancestor | patch-equivalent | tree-diff | cherry-pick-noop)142- semantic review conclusion: result of the post-merge semantic re-review143- verification command(s): the minimal relevant verification actually run144- push status: pushed / not pushed, and the gate decision145- residual risks: anything skipped, unverified, or still risky146147For a multi-repo scenario, report per repo; do not substitute a single "all merged fine".