code-review · git:20260910.99ce63d · 2026-09-10 · sha256 6d452816d9e3011c
code-review git:20260910.99ce63dA
Immutable. This exact content is served forever at /api/v1/blob/6d452816d9e3011c.
--- name: code-review description: >- Reviews a pull request or diff in the mergeCraft repository and produces typed, evidence-backed findings with a blocking verdict. Use when reviewing a PR, a branch diff, or staged changes here; when asked "is this safe to merge"; when grading or placing review findings; or when running mergeCraft against this repo. Covers correctness, data integrity, security, stability, performance, and maintainability, with the repo's own gates as evidence. license: Apache-2.0 metadata: mergecraft.doctrine-version: "1" --- # Reviewing code in mergeCraft A mergeCraft review is a falsifiable audit of one diff: typed findings anchored to evidence, graded on three axes, filtered hard, then one terminal verdict. A good review is not the one with the most comments — it is the one whose blocking concerns survive verification and whose silence means the author can merge. This file is **self-sufficient**. A reviewer that reads only `SKILL.md` can run a correct, complete review of this repository. The `references/` files add depth; they are never prerequisites. Nothing in this skill tree links outside `.github/skills/code-review/`. > **For humans:** `REVIEW-CHECKS.md` is the consumer-facing check catalog; > `docs/REVIEW-DOCTRINE.md` is the rationale and rejected alternatives. This > directory is the agent-facing instruction bundle mergeCraft injects at review time. ## The four rules These four are absolute. Everything else in this file is judgement. Each rule states its reason so you can generalise to cases this file never anticipated. 1. **No finding without evidence you can point at.** A claim must cite a file and line, a diff hunk, tool output, or a retrieved artifact. Without an anchor it is a question — ask it in the summary or drop it. Unfalsifiable comments teach authors to ignore this reviewer. 2. **Never re-raise a withdrawn finding.** The section `## Withdrawn review findings (known non-issues)` in the learnings file is binding. Re-litigating a refuted finding is worse than missing a real one, because it proves this reviewer does not remember prior pushback. 3. **Every blocking concern in the summary exists as a findings row.** Prose in the summary is read by no gate. If it blocks merge, it must appear in the structured `findings` array with severity, category, and evidence. 4. **Exactly one terminal verdict.** Call `approve` or `request_changes` once, after findings survive verification. The verdict follows from the findings — never the other way around. ## Review progress Copy this into your response and check items off as you go. ``` - [ ] 1. Scope — full diff read end-to-end; coverage checklist built - [ ] 2. Evidence — repo gates + analyzers run; withdrawn findings read - [ ] 3. Triage — what kind of change is this; trivial or not - [ ] 4. Lenses — load-bearing questions named, or none - [ ] 5. Findings — drafted, evidence attached, graded - [ ] 6. Filter — drop list applied; blocking findings verified - [ ] 7. Verdict — one terminal call ``` ## 1. Scope Read the **complete diff** before anything else. Use the diff table of contents and file line ranges as a coverage checklist. A reviewer that samples the diff writes findings about the part it sampled and stays silent about the rest — and silence reads as approval. Then pull **targeted** context: the touched functions, their callers, the tests that exercise them, the interfaces they cross. Not the whole repository. More context measurably makes frontier models worse at this task; stay on the blast radius. ## 2. Evidence before opinion Run the repo's own gates first and quote them. "`make lint` fails on this file" is a finding nobody argues; "consider sorting this" is one everybody does. Three outcomes mean **no signal** — report them as skipped, never as findings: - the tool is not in your toolset at all; - the tool returns `ran: false`; - a gate status is `unavailable`, `declared-but-cannot-run`, or `timed_out`. Only `failed` is a finding. Never substitute your own linter, formatter, or interpreter to fill a gap — a gate run under the wrong toolchain version manufactures findings. Read `## Withdrawn review findings (known non-issues)` **now**, not at drafting time. It changes what you bother investigating. ## 3. Triage Name what kind of change this is: which domain, which seams, which external contracts, which user-visible surfaces. **Genuinely trivial — skip to the verdict:** doc typo, whitespace-only, comment-only, lockfile or generated-code regeneration, mechanical rename whose only effect is import paths, low-risk dependency patch bump. **Looks trivial but is not — small diff, large blast radius:** - one-line changes to SQL, regex, auth, billing, permissions, or signature verification; - a flipped feature-flag default, retry/timeout constant, or money/tax constant; - a changed HTTP method, redirect URL, response code, or comparison operator; - a renamed public API surface or new direct dependency; - a "typo fix" in user-facing copy that changes meaning; - a semantic one-liner buried in a formatting-only diff. Read the shape, not the line count. ## 4. Lenses Name the load-bearing questions you cannot resolve yourself. A question is load-bearing only when its answer could change the verdict, and falsifiable only when evidence could settle it. "Another look for confidence" is neither. Two framings: - **Themed lenses** across the whole diff (correctness, security, performance). - **Subsystem lenses** for high-stakes domains (auth, billing, webhooks, schema migration). For those domains, lead with the subsystem lens — "the billing lens" primes double-charge and refund-race failure modes that a generic correctness pass misses. Run `mergecraft lens list` for the registry — each entry carries its id, triggers, rubric, and required evidence. Do not work from a remembered list. ## 5. Findings Every finding carries six fields before you place it: | Field | Value | | --- | --- | | Category | one of the six taxonomy categories (see references/grading.md) | | Severity | Critical · Major · Minor · Trivial | | Effort | Quick win · Heavy lift · Low value | | Confidence | certain · likely · possible | | Evidence | exact file and line, tool output, or retrieved artifact | | Why | one sentence of consequence, not of mechanism | **Placement is mechanical:** `Trivial` **or** `Low value` → a bullet in the body's Nitpicks list. Everything else → an inline comment at its line. The cost of a false positive is not the minute spent reading it — it is the team learning to skip every comment this reviewer ever leaves. Grade honestly; inflating a nit to Major to justify an inline anchor is the habit that makes a reviewer ignorable. **Category is a sweep, not a menu.** A PR that writes persistent state with no Data Integrity & Atomicity finding is worth one more look before concluding there was nothing there. **Hunt for non-anchored concerns too:** deletion plans for code this diff shadows; rollout sequencing and in-flight state; coverage the diff implies but does not add; scope questions only a human can answer. On substantial PRs at least one exists — if you cannot think of any, the bar is too high, not the PR too clean. See [references/grading.md](references/grading.md) for axes, placement, collateral, and the verification loop. ## 6. What gets dropped The drop list is most of what keeps a review readable: - Praise and style preferences the repo does not enforce. - Speculative and unverified claims. - Findings whose root cause predates this diff. - Anything already withdrawn. - Anything not actionable. - Bloat-shaped fixes — defensive checks for impossible cases, abstractions used once, comments restating obvious code, tests asserting tautologies, just-in-case guards. The bar is sound **and** correct **and** elegant; a change that improves one by degrading another makes the codebase worse. **Silence is a result.** If nothing survives this filter, say so explicitly and approve. An empty review from a reviewer that looked hard is a valid outcome and a good one. Manufacturing a finding to look diligent is the failure mode this section exists to prevent. Route silence through §7 — do not stop after §6 without a terminal verdict. ## 7. Verdict The terminal call is exactly one of `approve` or `request_changes`, with a `summary` and a `findings` array. Match the opening callout tier to what the author should actually do next. - **`approve`** — no blocking findings survive verification; say so plainly. - **`request_changes`** — at least one Critical or Major finding blocks merge; every blocking concern in the summary must have a matching findings row. The server **rejects** `request_changes` with an empty `findings` array — that is enforced, not a style preference. `approve` over a verifier-confirmed Critical or Major blocker is also rejected. When silence is the outcome: call `approve` with an empty `findings` array and a summary that states what you read, what gates you ran, and that nothing actionable survived the filter. See [references/tools.md](references/tools.md) for the call in each environment. ## Tools Three capability tiers share this one skill. Use the tier that matches your runtime; degrade steps — never skip them silently. **Tier 1 — mergeCraft MCP (full):** `mcp__mergecraft__checkout_pr` establishes scope and returns `diffPath`. In the same turn call `mcp__mergecraft__run_static_checks` and `mcp__mergecraft__run_analyzers` with changed paths; when CI failed on the head, call `mcp__mergecraft__analyze_ci_failures`. Before publishing, hand Critical/Major agent findings to `mcp__mergecraft__verify_agent_findings` and record each verdict with `mcp__mergecraft__record_finding_verdict`. Finish with exactly one `mcp__mergecraft__submit_review_verdict` (`verdict`, `summary`, `findings`). **Tier 2 — Copilot / hosted code review (no MCP):** Read the PR diff from the host UI. Run repo gates locally when you have shell access (`make lint`, `make typecheck`, scoped pytest). Draft findings as inline review comments with the triage tag; post an approve or request-changes review through the host. You cannot call `submit_review_verdict` — make the summary and inline comments self-contained so a human can act without mergeCraft's structured export. **Tier 3 — bare agent (file access only):** Read the diff artifact and changed files directly. Note which gates you could not run. Produce findings with the six fields above; end with an explicit approve or request-changes recommendation and the same discipline on evidence and silence. ## References - [references/checks.md](references/checks.md) — the check catalog by category - [references/grading.md](references/grading.md) — axes, placement, collateral, verification - [references/repo-traps.md](references/repo-traps.md) — mergeCraft-specific failure modes - [references/tools.md](references/tools.md) — what to call in each environment