pg-patch-review — multi-agent comprehensive PG patch review
The deep-review counterpart to the manual seven-phase review-checklist.
The cf6402 validation run on 2026-06-02 proved the corpus + skills compose
for a one-author review; this skill turns that loop into a repeatable
multi-agent pipeline.
When to use this skill vs review-checklist
| Situation |
Use |
| CF entry you intend to mail a real review on |
this skill |
| Quick "is this even sane?" pass on a patch |
review-checklist (manual seven-phase) |
| Self-review of your own patch before mailing |
patch-submission (which already invokes review-checklist) |
| Generic non-PG GitHub PR review |
neither — this is PG-specific |
The two are NOT redundant: review-checklist is the seven-phase scaffold
each critic agent applies inside its assigned slice. This skill is the
orchestration layer above that scaffold (project discovery + parallel
critic fan-out + synthesis).
Companion skills (each critic loads what it needs)
review-checklist — seven-phase scaffold each critic walks inside its slice
wal-and-xlog — WAL records / redo / hint bits (used by breaking-change critic)
locking — lock primitive choice + acquisition order (architecture critic)
catalog-conventions — pg_proc / OID assignment (breaking-change critic)
testing — regress vs isolation vs TAP vs module (test-coverage critic)
coding-style — pgindent / include order / C99 subset (style critic)
commit-message-style — upstream PG commit-message style (style critic, AND used by synthesizer for review-email tone)
memory-contexts — palloc placement / context lifetimes (architecture critic when relevant)
error-handling — ereport / SQLSTATE choices (style critic when relevant)
Inputs
- A patch reference (required), one of:
- CF number:
6402, #6402, or CF 6402
- GitHub PR number on
postgres/postgres: pr 19234 or #19234
- A local
.patch file or directory of patches: /tmp/v3-0001-foo.patch
- Optional flags (from the slash command):
--skip-build — patch already applied + built in dev/, skip Phase 0
--no-flaky-isolation — skip the isolation suite (macOS sometimes flakes)
--subsystem=<name> — hint for which knowledge/subsystems/*.md to load
first (e.g. --subsystem=access-nbtree for CF #6402)
Output
- A draft review email at
sessions/<date>-cf<N>-review.md (or
sessions/<date>-pr<N>-review.md) using the PG-hackers house style.
- A per-critic appendix at the bottom of the same file with the raw
findings each sub-agent produced (blocking / warning / suggestion).
- A run log appended to that session file: which patches applied, which
tests ran, which subsystem docs the critics consulted, wall time.
- A
dev/ branch named cf<N>-review (or pr<N>-review) with the patch
applied — disposable after the review is sent.
When NOT to invoke
- Patch already merged upstream — use
git log + corpus walkthrough instead.
- Patch is your own work — use
patch-submission (it invokes the same critics
but on the self-review path).
- Patch is non-PG — wrong skill.
Method — five stages
Stage 0 — mechanical pre-amble (5-10 min)
Done by the /pg-review slash command. If invoked directly (without
/pg-review), this skill does it inline before stage 1. See
.claude/commands/pg-review.md for the exact recipe.
Inline Stage 0 (when /pg-review wasn't used) — minimum commands:
cd dev && git checkout master && git pull
git checkout -b cf<N>-review (or pr<N>-review)
- Fetch the patch (CF:
curl the v from the CF entry;
PR: gh pr checkout <N>; .patch file: copy in).
git am /path/to/v*.patch (apply all v hunks in order).
ninja -C build-debug install — must be warning-clean.
meson test --no-rebuild regress/regress — record pass/fail.
meson test --no-rebuild --suite isolation — record pass/fail.
git diff --name-only HEAD~<N>..HEAD — capture the touched-files
list.
- Note any pre-existing flakes (e.g. macOS
recovery/040_standby_failover_slots_sync).
The output of this stage is:
dev/ on branch cf<N>-review (or pr<N>-review) with the patch applied.
- A built binary (
ninja install clean, no new warnings).
meson test --no-rebuild regress/regress result (pass/fail per test).
meson test --no-rebuild --suite isolation result.
- A list of files the patch touches (
git diff --name-only HEAD~N..HEAD).
- A note on any pre-existing flakes (e.g. macOS
recovery/040_standby_failover_slots_sync).
If stage 0 fails (patch doesn't apply, build breaks, regress fails) —
stop. Report to the user. The patch is Waiting on Author
mechanically; no point spending tokens on the critics.
Stage 1 — project discovery (orchestrator, ~5 min)
The main agent does this once before fanning out:
Touched files → touched subsystems. From the file list in stage 0,
map each file to its knowledge/subsystems/<name>.md parent. Example:
src/backend/access/nbtree/nbtpage.c → knowledge/subsystems/access-nbtree.md.
Use the §2 "File map" section of each subsystem doc to confirm. If a
touched file doesn't appear in any subsystem doc, NOTE THAT — the
review must call out that an uncovered area was changed.
Load per-file docs. For each touched file, look up
knowledge/files/<path>.md if present. These have INV-* invariants
and per-function cites the critics will rely on.
Identify the "claims" the patch makes. Read the patch's commit
message + cover letter (or the CF/PR description). Each claim that
says "fixes X", "implements Y", "no behavior change", "doesn't touch
on-disk format", "is purely a refactor" becomes a CHECK item the
critics will validate.
Build the dispatch block. Produce a small reference block that
every critic sub-agent receives in its prompt:
Patch: <CF#|PR#|path>
Branch: dev/cf<N>-review @ <short-sha>
Files touched:
- src/.../X.c (per-file doc: knowledge/files/.../X.c.md)
- src/.../Y.h (no per-file doc — flag if material)
Subsystems touched:
- access-nbtree (knowledge/subsystems/access-nbtree.md)
- storage-buffer (knowledge/subsystems/storage-buffer.md)
Claims the patch makes (verbatim from commit msg):
- "Replace duplicated metapage sanity checks..."
- "No behavior change."
- "Restores symmetry with _bt_getroot..."
Stage-0 test result: regress 245/245 pass, iso 129/129 pass,
1 unrelated TAP failure recovery/040_* (macOS flake)
Spot-check 3-5 file:line cites in the relevant subsystem doc
against current source/ — if drift > 10% (cites stale by more
than ~20 lines or naming since-removed symbols), STOP and tell the
user the corpus needs an hf(corpus): refresh before this review.
Stage 2 — fan out 5 critic sub-agents IN PARALLEL
Launch all five (A-E; Critic E added 2026-06-12 from Phase C) in
a single message with parallel tool calls. Each gets the dispatch
block from stage 1 + its assigned slice. Each is read-only —
sub-agents do NOT edit files or commit. Each returns a structured
finding list.
Use the Agent tool with subagent_type: "general-purpose" for each.
Estimate ~10-20 min wall time for all five to complete (in parallel).
Critic A — Architecture & invariants
Scope: does the patch fit the subsystem's existing invariants?
Loads: knowledge/subsystems/<each touched subsystem>.md + relevant
per-file docs + review-checklist Phase 6 (Architecture).
Checks:
- Does the patch violate any INV-* invariant tagged in the subsystem
doc? Cite the tag.
- Does the patch's locking match the subsystem's lock-order discipline?
(E.g. for nbtree: buffer locks coupled in left-to-right order; for
heap: buffer-pin-before-buffer-lock; for replication: never hold
ProcArrayLock across...)
- Does the patch interact with parallel query / extensions / logical
replication in any way the corpus warns about?
- Does the patch's claim of "no behavior change" hold up under
inspection? (For refactors: every removed line must have an
equivalent in the replacement.)
- Provenance check for any helper/struct the patch touches: run
git -C source log -S '<symbol>' --oneline | head -5 to find when
the symbol was introduced. A symbol that's existed for years +
has multiple existing callers is a safer refactor target than a
symbol introduced last release. Surfaces both "this is a long-
overdue cleanup" and "this is racing an in-flight feature".
Output: structured findings list. Each item:
File: <path:line>
Severity: blocking | warning | suggestion
Invariant: INV-... (if applicable) or "no INV cited"
Description: what and why
Suggestion: proposed fix or question to the author
Critic B — Breaking-change scan
Scope: does the patch touch anything backwards-incompatible?
Loads: wal-and-xlog, catalog-conventions, review-checklist
Phase 6 (Architecture — the ABI bullets), and the subsystem docs'
§5 "Invariants and breaking-change surfaces" sections.
Checks:
- On-disk page format change? (
pd_* fields, opaque-area layout.)
- WAL record change? (New record, new info byte, existing record
extended.) If yes, is
XLOG_PAGE_MAGIC bumped?
- Catalog change? (
pg_proc.dat, pg_type.dat, etc.) If yes, is
CATALOG_VERSION_NO bumped? Are new OIDs assigned?
- Public API / extension ABI? (Anything in
src/include/.) Inline
functions / macros there count. If touching back-branchable code:
new struct members must go at the end; no signature changes on
exported functions.
- Replication protocol change? (
libpq wire format, walsender output
plugins, logical decoding output formats.)
- pg_dump impact? (Any new schema object.)
Output: same structured list. For each blocking break, name the
upgrade/backpatch story the author needs to provide.
Critic C — Test coverage
Scope: is the patch tested adequately for what it claims?
Loads: testing skill + the touched subsystems' "test surface"
sections + src/test/ for the existing coverage of the touched code.
Checks:
- Does the diff include
src/test/ changes? If not, is the claim "pure
refactor, no new behavior, existing tests cover" defensible?
- For a refactor: does at least one existing test exercise the code
path being refactored? (Find by
git grep for the function name in
src/test/.) If not, the "existing tests cover" claim is weak.
- For new behavior: does the new test ACTUALLY fail without the code
change? (The classic "test passes both with and without the patch"
bug.) Sub-agent can't easily verify this without re-running tests
twice — instead it flags this as a question for the author or for
manual follow-up.
- Corner cases: NULL, empty input, max-length, encoding edges,
concurrent calls, parallel-worker visibility, replication catchup.
Sub-agent enumerates which apply to this patch's surface.
- Isolation tests needed? Concurrent-modification scenarios?
- TAP tests needed? Multi-node, recovery, replication, crash-recovery
scenarios?
Output: same structured list. The "blocking" bar here is whether
the patch's correctness claim is mechanically testable from what's in
the diff.
Critic D — Style & commit-message
Scope: would a committer have to fix the format before applying?
Loads: commit-message-style + coding-style + review-checklist
Phase 5 (Coding review) + Phase 7 (Committer-readiness).
Checks:
- Patch filename:
vN-NNNN-<title>.patch?
- Commit message: imperative title, no period, ~76-col wrap, no emoji,
no
Co-Authored-By (forbidden upstream), Author/Reviewed-by trailers
if relevant, Discussion: link if relevant.
- Code style: matches surrounding module (camelCase vs snake_case),
no leftover debug
elog, no commented-out code, no new compiler
warnings flagged in stage 0.
- Error messages follow the message style guide (capitalization,
no period on
errmsg, separated errdetail/errhint).
git diff --check clean? (Trailing whitespace, broken tab/space mix.)
pgindent clean? (May not be runnable locally — note pg_bsd_indent
install state; CI will catch.)
Output: same structured list. Most items here are suggestion or
warning; only fundamentally broken style is blocking.
Critic E — Reviewer-reflex probes (added 2026-06-12 from Phase C)
Scope: does the patch trigger any of the persona-driven reflexes
the corpus has documented but the generic critics A-D don't encode?
Loads: knowledge/calibration/gap-catalog.md (the 11-item
catalog) + knowledge/personas/<name>.md for each persona named in
items 4-11 that triggers + knowledge/personas/committer-map.md +
knowledge/personas/domain-ownership.md (item 11 cross-reference).
Checks (each maps 1:1 to a catalog item):
Cleanup-on-early-return tracing (catalog #4). Scan the diff for
a new return statement added inside a function whose entry block
owns a resource handle (z_stream, BufFile, FileFd,
MemoryContext, Relation, LWLock). If found, surface "trace
cleanup path under the new error return — does
<resource>_destroy() / _close() / _release() run on this
branch?". Driver: daniel-gustafsson.md errorhandling discipline.
Multibyte/encoding interaction (catalog #5). Scan the diff for
byte-walking patterns (*p++, *input++, manual for loops over
varlena/text/cstring) OR size caps on text-processing
primitives. If found, surface "enumerate worst-case per encoding
(UTF-8 documented, GB18030, EUC_JP, EUC_KR, EUC_CN, EUC_TW); cite
the Unicode TR / SpecialCasing.txt entry for any UTF-8-specific
bound". Driver: noah-misch.md §4 + jeff-davis.md Unicode
standard fidelity.
Subsystem-local cap discoverability (catalog #6). Scan the
diff for a new #define in a contrib/*/*.c file (not header).
If found, surface "move to <subsystem>.h if a public-style cap;
cite the precedent constant in the same area (e.g.
LQUERY_MAX_LEVELS for ltree_io.c)". Driver:
peter-eisentraut.md style reflex.
"Third state" cross-check for binary-format changes (catalog
#7). Scan the diff for changes in how a flag-bit, version-bit,
or layout-bit is interpreted. If found, surface "enumerate the
third state: bit set but structure invalid, OR bit unset but
structure looks valid — what handles each?". Driver:
heikki-linnakangas.md binary-format reflex.
injection_points reproducer for DoS / scratch-allocation /
race claims (catalog #8). Scan the commit-message + COVER for
phrases like "prevents N MB scratch", "N GB allocation", "fixes a
race", "OOB read", "amplification". If found AND the patch has
no src/test/modules/injection_points/ change, surface "include
an injection_points measurement at the allocation /
race-windowed boundary; the structural argument is not enough on
a security claim". Driver: noah-misch.md §5.
Hot-path branch-prediction / micro-benchmark (catalog #9).
When the patch touches a function in src/backend/utils/adt/*,
src/backend/access/{heap,nbtree}/, src/backend/optimizer/, or
similar query-evaluator path AND adds a new guard check, surface
"include micro-benchmark numbers confirming the guard is in the
unlikely branch and adds <1% overhead on typical inputs". Driver:
thomas-munro.md + heikki-linnakangas.md performance reflex on
hot paths.
Symmetric-check refactor for N-entry-point guards (catalog
#10). Diff scan for 3+ near-identical added blocks (heuristic:
same if/ereport/ereturn pattern at 3+ places). If found,
surface "consider a shared inline helper <module>_check_<thing>()
to keep entry points symmetric". Driver: peter-eisentraut.md
symmetric-primitives reflex.
Persona-aware backpatch routing (catalog #11). When COVER
claims back-patching AND the predicted top committer for the
touched subsystem (from domain-ownership.md top-committer
column) has a 24mo backpatch rate < 5% (compute from
committer-map.md or /usr/bin/git log --author=<name> --since= '2yr' --pretty=%s | grep -ciE 'back.?patch' ratio), surface "X
doesn't backpatch in 24mo; the realistic v16/v17/v18 landing
committer is Y (from domain-ownership.md reviewer column — pick
the highest-ranked committer who backpatches at ≥10%). CC them
on the thread.". Driver: Peter Eisentraut row in
committer-map.md.
Severity rules for Critic E:
- Catalog #1-#3 are NOT this critic's job — they live in
review-checklist Phase 0 (gates that block before the patch
enters the critic fan-out).
- Catalog #4, #5, #7, #8 are
warning (sometimes blocking if the
COVER doesn't even acknowledge the question).
- Catalog #6, #9, #10, #11 are
suggestion by default — they
improve the patch but don't block.
- Catalog #5 escalates to
blocking if the patch caps a text
primitive AND no per-encoding analysis is in the COVER — that's
a real correctness gap (e.g. SP2 had this; the 3× UTF-8 bound
may not hold for GB18030).
REJECT-track escalation (M4). When Critic E surfaces 3+
blocking-severity findings from the catalog AND the
context-awareness signal (engagement class contested OR a
documented INV-* invariant is foreclosed), the critic's output
should explicitly recommend a REJECT-A Stage-3 verdict rather than
"Waiting on Author". The Stage-3 orchestrator then decides between
REJECT-A (the grade above), REJECT-B (acknowledge that the critic
may have missed a concern), or downgrade to non-REJECT if the
findings don't actually compose to a design-level NACK. Critic E
recommends; Stage 3 decides.
Critic E severity matrix at a glance:
| Catalog # |
Probe |
Default |
Escalates to blocking when |
| #4 |
Cleanup-on-early-return |
warning |
COVER doesn't acknowledge the cleanup question |
| #5 |
Multibyte / encoding |
warning |
text-primitive cap added with no per-encoding analysis in COVER |
| #6 |
Subsystem-local cap discoverability |
suggestion |
— |
| #7 |
"Third state" binary-format |
warning |
COVER doesn't enumerate bit-set-but-invalid AND bit-unset-but-looks-valid cases |
| #8 |
injection_points reproducer |
warning |
structural argument on a security claim with no injection_points test |
| #9 |
Hot-path micro-benchmark |
suggestion |
— |
| #10 |
Symmetric-check refactor |
suggestion |
— |
| #11 |
Persona-aware backpatch routing |
suggestion |
— |
REJECT-track escalation: 3+ blocking from this table AND context-
awareness signal (engagement class contested OR foreclosed
INV-*) → recommend REJECT-A to Stage 3.
Output: same structured-finding list as critics A-D, plus an
optional recommend_verdict: REJECT-A | REJECT-B field when the
escalation rule above triggers.
Stage 3 — orchestrator consolidates (10 min)
Critic-E recommendation vs orchestrator verdict. Critic E may
emit recommend_verdict: REJECT-A | REJECT-B when its catalog-item
threshold (3+ blocking findings + context-awareness signal) fires.
The orchestrator at Stage 3 decides; Critic E recommends. The
orchestrator may downgrade the recommendation to "Waiting on
Author" if the findings, in aggregate, do NOT compose to a
design-level NACK. Critic E's recommendation is one input, not the
verdict.
The main agent gathers all four critics' outputs and:
Deduplicates. Two critics may flag the same issue from different
angles — merge into one finding with both rationales.
Resolves conflicts. If critic A says "this is fine" but critic B
says "this breaks ABI", the orchestrator re-reads both and picks the
stronger argument. Cite both in the merged finding.
Severity prioritization. Group findings into:
- Blocking (must fix before commit; flip CF to "Waiting on Author")
- Warning (should fix or justify)
- Nits / suggestions (take or leave)
- Open questions (need author input)
Verdict. Decide one of:
- Ready for Committer
- Waiting on Author (blocking issues)
- Needs more info from author (open questions dominate)
- REJECT-A — design fundamentally wrong, all critical problems
identified, alternative proposed. The right deliverable is a
thread reply explaining the rejection with cites; saves community
cycles. Use this when the patch is in
contested engagement
class or the Context-awareness probe (from
pg-feature-plan) flagged it.
- REJECT-B — design wrong, but you missed at least one major
concern that a critic from the community will raise. Solid but
incomplete; send the reply, acknowledge gaps.
- REJECT-C — rejected for the wrong reasons OR rejected when
the proposal is actually sound. STOP — escalate to user
before posting. Likely you need to re-run with looser
priors or load more corpus.
M4 origin:
knowledge/shadow-implementations/money-fx-exchange/skill-gaps.md.
The REJECT-A/B/C grades parallel the A-F grade rubric on
non-REJECT outcomes — they're not lesser verdicts, just the right
shape for proposals that shouldn't proceed.
Stage 4 — synthesize the review email
Use the commit-message-style skill's tone rules — imperative,
plain text, no HTML, no emoji, ~76 col wrap. The review email lives at
sessions/<date>-cf<N>-review.md (or pr) and has this shape:
To: pgsql-hackers@lists.postgresql.org
Cc: <author> <author@email>
Subject: Re: [PATCH v<N>] <patch subject>
<one-line summary of where the patch stands>
<one or two paragraphs of the high-level read — what the patch does, why
the corpus thinks it's coherent (or not). Cite specific anchors where
relevant: nbtpage.c:407, knowledge/subsystems/access-nbtree.md §4.>
Blocking issues:
1. <one-line summary>
<2-4 lines of context + concrete ask>
2. ...
Warnings / consider:
1. ...
Nits, take or leave:
1. ...
Open questions:
1. ...
Testing performed:
- git am: <clean | rejected hunk in X>
- ninja install: <clean | warnings: ...>
- meson test regress/regress: <NNN subtests, all pass | failed: ...>
- meson test --suite isolation: <NNN subtests, all pass | failed: ...>
- Patch base: <upstream-master short-sha>
<closing line: "I think this is ready for a committer" / "Marking
Waiting on Author pending the items above" / etc.>
Regards,
[Reviewer]
Below the email in the SAME session file, append:
---
## Per-critic raw findings
### Critic A — Architecture & invariants
<paste the sub-agent's structured list>
### Critic B — Breaking-change scan
<paste>
### Critic C — Test coverage
<paste>
### Critic D — Style & commit-message
<paste>
## Stage 0 mechanical log
- Patch source: <URL or path>
- Base ref: <upstream-master sha>
- Apply: <git am output summary>
- Build: <ninja install summary>
- regress: <pass/fail counts + duration>
- isolation: <pass/fail counts + duration>
- Targeted suites: <if any>
- Pre-existing flakes encountered: <list, with dismissal rationale>
## Wall time
- Stage 0: <min>
- Stage 1: <min>
- Stage 2 (4 critics in parallel): <max of the four, plus orchestration overhead>
- Stage 3: <min>
- Stage 4: <min>
- Total: <min>
Boundaries vs other skills
review-checklist (the eight-phase scaffold — Phase 0 added
2026-06-12 for reviewer-reflex gates): each critic walks the
relevant phase of it. This skill orchestrates five critics doing
that in parallel (A-E; E added 2026-06-12 from Phase C) and
synthesizes. Don't bypass review-checklist's phase definitions —
extend them.
patch-submission: the self-review counterpart. If you're
reviewing YOUR OWN patch before mailing, use that — it invokes the
same critics but on the pre-submission path.
commit-message-style (upstream PG): used by the synthesizer for
the review-email tone AND by critic D for judging the patch's commit
message.
meta-commit-style (postgres-claude): does NOT apply to the
review email (which goes to pgsql-hackers, not into postgres-claude).
It WOULD apply to the session-log commit (if any) and to the
STATE.md update.
What to escalate to the user mid-review
- Stage-0 fail (patch doesn't apply, build breaks, regress fails):
stop, report, ask whether to send a "rebase needed" reply or to skip.
- Corpus drift detected in stage 1 (cites stale > 10%): stop, ask
the user whether to (a) refresh the corpus first via a separate
hf(corpus): commit (per Rule R9 of
.claude/rules/pg-implement-discipline.md — corpus fixes are their
own commits in the meta-repo), or (b) proceed with a "best-effort
against possibly-stale docs" caveat noted in the review email's
"Testing performed" block.
- Touched file not in any subsystem doc: don't stop; note in the
review email's "Testing performed" block that this area is
uncovered by the corpus. After the review, file a followup to
document that subsystem.
- Two critics genuinely disagree after orchestrator consolidation:
ask the user to break the tie before drafting the email.
Style notes
- The review email is the deliverable; everything else is working notes.
Make the email scannable — bullets, no walls of prose.
- Cite specific file:line anchors in the email when relevant. The
validation run proved this is what makes a review feel grounded vs
generic.
- Distinguish blocking from nits in EVERY review. "Needs more tests" is
not blocking unless the patch's correctness claim depends on the
missing test.
- For performance-impacting patches: ask for pgbench numbers with
exact recipe (hardware, build flags, run count, master baseline).
Numerical claims without a recipe get bounced.
- If invoking via the
/pg-review slash command, the command already
did stage 0 — skip ahead to stage 1.
Where the artifacts live
- Review email + appendices:
sessions/<date>-cf<N>-review.md in
postgres-claude/ (this repo).
- Patch branch:
dev/cf<N>-review (the mutable PG clone). Disposable
after review is sent.
- No
knowledge/ writes by this skill — if the review surfaces a
corpus gap, file a follow-up hf(corpus): commit separately (per
R10 of .claude/rules/pg-implement-discipline.md).
Validation reference
The 2026-06-02 v0 review of CF #6402
[unverified: session log not preserved in sessions/ at the time of this writing]
is the calibration target — re-running THIS skill against that patch
should reproduce a review of comparable quality (same draft conclusion,
same blocking-vs-nit split) in less wall time than the v0 manual walk.
A future preserved-and-named calibration session can replace this
paragraph.
Cross-references
.claude/skills/review-checklist/SKILL.md — the eight-phase scaffold each critic walks; Phase 0 hosts the REJECT-A/B/C grade rubric this skill's Stage 3 verdict consumes.
.claude/skills/patch-submission/SKILL.md — invokes this skill in --self mode for the self-review path.
.claude/skills/pg-feature-plan/SKILL.md — supplies the Context-awareness probe + Thread-engagement classification that drive Critic E's REJECT-track escalation.
.claude/skills/commit-message-style/SKILL.md — Critic D + synthesizer use this for upstream PG commit-message format.
.claude/skills/coding-style/SKILL.md — Critic D style check.
.claude/skills/testing/SKILL.md — Critic C test-coverage check.
.claude/skills/wal-and-xlog/SKILL.md, .claude/skills/catalog-conventions/SKILL.md — Critic B breaking-change scan.
.claude/skills/locking/SKILL.md, .claude/skills/memory-contexts/SKILL.md, .claude/skills/error-handling/SKILL.md — Critic A architecture check.
knowledge/calibration/gap-catalog.md — items 4-11 source Critic E's eight reflex probes.
knowledge/personas/*.md — Critic E loads relevant persona docs per probe.
knowledge/shadow-implementations/money-fx-exchange/skill-gaps.md — M4 origin (REJECT-A/B/C verdict).
.claude/commands/pg-review.md — slash-command wrapper that runs Stage 0 inline.
1---2name: pg-patch-review3description: Run a multi-agent comprehensive review of a PostgreSQL patch (CommitFest entry, GitHub PR, or local .patch file) — orchestrates the mechanical pre-amble (fetch + apply + build + regress / iso / TAP) and then fans out 5 critic sub-agents IN PARALLEL (architecture / invariants critic cross-checking knowledge/subsystems/*.md INV-* tags, breaking-change critic for on-disk / WAL / catalog / extension-ABI, test-coverage critic, style / commit-message critic, reviewer-reflex critic against knowledge/calibration/gap-catalog.md), then synthesizes one PG-house-style review email. Stage 3 verdict supports REJECT-A/B/C grades for design-level rejections. Use when the user says "/pg-review <CF# | PR# | patchfile>", "deep-review this patch", "comprehensive review of CF NNNN", "mailing-grade review of this patch", or "run the 5-critic fan-out on <patch>". Skip for non-PG patch review, self-review-before-mail (use patch-submission), the lightweight 7-phase walk (use review-checklist), generic GitHub PR review (use review-cha4---56# pg-patch-review — multi-agent comprehensive PG patch review78The deep-review counterpart to the manual seven-phase `review-checklist`.9The cf6402 validation run on 2026-06-02 proved the corpus + skills compose10for a one-author review; this skill turns that loop into a repeatable11multi-agent pipeline.1213## When to use this skill vs `review-checklist`1415| Situation | Use |16|---|---|17| CF entry you intend to mail a real review on | **this skill** |18| Quick "is this even sane?" pass on a patch | `review-checklist` (manual seven-phase) |19| Self-review of your own patch before mailing | `patch-submission` (which already invokes `review-checklist`) |20| Generic non-PG GitHub PR review | neither — this is PG-specific |2122The two are NOT redundant: `review-checklist` is the seven-phase scaffold23each critic agent applies inside its assigned slice. This skill is the24**orchestration layer** above that scaffold (project discovery + parallel25critic fan-out + synthesis).2627## Companion skills (each critic loads what it needs)2829- `review-checklist` — seven-phase scaffold each critic walks inside its slice30- `wal-and-xlog` — WAL records / redo / hint bits (used by breaking-change critic)31- `locking` — lock primitive choice + acquisition order (architecture critic)32- `catalog-conventions` — `pg_proc` / OID assignment (breaking-change critic)33- `testing` — regress vs isolation vs TAP vs module (test-coverage critic)34- `coding-style` — pgindent / include order / C99 subset (style critic)35- `commit-message-style` — upstream PG commit-message style (style critic, AND used by synthesizer for review-email tone)36- `memory-contexts` — palloc placement / context lifetimes (architecture critic when relevant)37- `error-handling` — `ereport` / SQLSTATE choices (style critic when relevant)3839## Inputs4041- **A patch reference** (required), one of:42 - CF number: `6402`, `#6402`, or `CF 6402`43 - GitHub PR number on `postgres/postgres`: `pr 19234` or `#19234`44 - A local `.patch` file or directory of patches: `/tmp/v3-0001-foo.patch`45- **Optional flags** (from the slash command):46 - `--skip-build` — patch already applied + built in dev/, skip Phase 047 - `--no-flaky-isolation` — skip the isolation suite (macOS sometimes flakes)48 - `--subsystem=<name>` — hint for which `knowledge/subsystems/*.md` to load49 first (e.g. `--subsystem=access-nbtree` for CF #6402)5051## Output5253- A draft review email at `sessions/<date>-cf<N>-review.md` (or54 `sessions/<date>-pr<N>-review.md`) using the PG-hackers house style.55- A per-critic appendix at the bottom of the same file with the raw56 findings each sub-agent produced (blocking / warning / suggestion).57- A run log appended to that session file: which patches applied, which58 tests ran, which subsystem docs the critics consulted, wall time.59- A `dev/` branch named `cf<N>-review` (or `pr<N>-review`) with the patch60 applied — disposable after the review is sent.6162## When NOT to invoke6364- Patch already merged upstream — use `git log` + corpus walkthrough instead.65- Patch is your own work — use `patch-submission` (it invokes the same critics66 but on the self-review path).67- Patch is non-PG — wrong skill.6869## Method — five stages7071### Stage 0 — mechanical pre-amble (5-10 min)7273Done by the `/pg-review` slash command. If invoked directly (without74`/pg-review`), this skill does it inline before stage 1. See75`.claude/commands/pg-review.md` for the exact recipe.7677**Inline Stage 0 (when /pg-review wasn't used) — minimum commands:**78791. `cd dev && git checkout master && git pull`802. `git checkout -b cf<N>-review` (or `pr<N>-review`)813. Fetch the patch (CF: `curl` the v<N> from the CF entry;82 PR: `gh pr checkout <N>`; .patch file: copy in).834. `git am /path/to/v*.patch` (apply all v<N> hunks in order).845. `ninja -C build-debug install` — must be warning-clean.856. `meson test --no-rebuild regress/regress` — record pass/fail.867. `meson test --no-rebuild --suite isolation` — record pass/fail.878. `git diff --name-only HEAD~<N>..HEAD` — capture the touched-files88 list.899. Note any pre-existing flakes (e.g. macOS90 `recovery/040_standby_failover_slots_sync`).9192The output of this stage is:9394- `dev/` on branch `cf<N>-review` (or `pr<N>-review`) with the patch applied.95- A built binary (`ninja install` clean, no new warnings).96- `meson test --no-rebuild regress/regress` result (pass/fail per test).97- `meson test --no-rebuild --suite isolation` result.98- A list of files the patch touches (`git diff --name-only HEAD~N..HEAD`).99- A note on any pre-existing flakes (e.g. macOS100 `recovery/040_standby_failover_slots_sync`).101102If stage 0 fails (patch doesn't apply, build breaks, regress fails) —103**stop**. Report to the user. The patch is `Waiting on Author`104mechanically; no point spending tokens on the critics.105106### Stage 1 — project discovery (orchestrator, ~5 min)107108The main agent does this **once** before fanning out:1091101. **Touched files → touched subsystems.** From the file list in stage 0,111 map each file to its `knowledge/subsystems/<name>.md` parent. Example:112 `src/backend/access/nbtree/nbtpage.c` → `knowledge/subsystems/access-nbtree.md`.113 Use the §2 "File map" section of each subsystem doc to confirm. If a114 touched file doesn't appear in any subsystem doc, NOTE THAT — the115 review must call out that an uncovered area was changed.1161172. **Load per-file docs.** For each touched file, look up118 `knowledge/files/<path>.md` if present. These have INV-* invariants119 and per-function cites the critics will rely on.1201213. **Identify the "claims" the patch makes.** Read the patch's commit122 message + cover letter (or the CF/PR description). Each claim that123 says "fixes X", "implements Y", "no behavior change", "doesn't touch124 on-disk format", "is purely a refactor" becomes a CHECK item the125 critics will validate.1261274. **Build the dispatch block.** Produce a small reference block that128 every critic sub-agent receives in its prompt:129130 ```131 Patch: <CF#|PR#|path>132 Branch: dev/cf<N>-review @ <short-sha>133 Files touched:134 - src/.../X.c (per-file doc: knowledge/files/.../X.c.md)135 - src/.../Y.h (no per-file doc — flag if material)136 Subsystems touched:137 - access-nbtree (knowledge/subsystems/access-nbtree.md)138 - storage-buffer (knowledge/subsystems/storage-buffer.md)139 Claims the patch makes (verbatim from commit msg):140 - "Replace duplicated metapage sanity checks..."141 - "No behavior change."142 - "Restores symmetry with _bt_getroot..."143 Stage-0 test result: regress 245/245 pass, iso 129/129 pass,144 1 unrelated TAP failure recovery/040_* (macOS flake)145 ```1461475. **Spot-check 3-5 file:line cites** in the relevant subsystem doc148 against current `source/` — if drift > 10% (cites stale by more149 than ~20 lines or naming since-removed symbols), STOP and tell the150 user the corpus needs an `hf(corpus):` refresh before this review.151152### Stage 2 — fan out 5 critic sub-agents IN PARALLEL153154Launch **all five** (A-E; Critic E added 2026-06-12 from Phase C) in155a single message with parallel tool calls. Each gets the dispatch156block from stage 1 + its assigned slice. Each is read-only —157sub-agents do NOT edit files or commit. Each returns a structured158finding list.159160Use the `Agent` tool with `subagent_type: "general-purpose"` for each.161Estimate ~10-20 min wall time for all five to complete (in parallel).162163#### Critic A — Architecture & invariants164165**Scope:** does the patch fit the subsystem's existing invariants?166167**Loads:** `knowledge/subsystems/<each touched subsystem>.md` + relevant168per-file docs + `review-checklist` Phase 6 (Architecture).169170**Checks:**171- Does the patch violate any INV-* invariant tagged in the subsystem172 doc? Cite the tag.173- Does the patch's locking match the subsystem's lock-order discipline?174 (E.g. for nbtree: buffer locks coupled in left-to-right order; for175 heap: buffer-pin-before-buffer-lock; for replication: never hold176 ProcArrayLock across...)177- Does the patch interact with parallel query / extensions / logical178 replication in any way the corpus warns about?179- Does the patch's claim of "no behavior change" hold up under180 inspection? (For refactors: every removed line must have an181 equivalent in the replacement.)182- **Provenance check** for any helper/struct the patch touches: run183 `git -C source log -S '<symbol>' --oneline | head -5` to find when184 the symbol was introduced. A symbol that's existed for years +185 has multiple existing callers is a safer refactor target than a186 symbol introduced last release. Surfaces both "this is a long-187 overdue cleanup" and "this is racing an in-flight feature".188189**Output:** structured findings list. Each item:190```191File: <path:line>192Severity: blocking | warning | suggestion193Invariant: INV-... (if applicable) or "no INV cited"194Description: what and why195Suggestion: proposed fix or question to the author196```197198#### Critic B — Breaking-change scan199200**Scope:** does the patch touch anything backwards-incompatible?201202**Loads:** `wal-and-xlog`, `catalog-conventions`, `review-checklist`203Phase 6 (Architecture — the ABI bullets), and the subsystem docs'204§5 "Invariants and breaking-change surfaces" sections.205206**Checks:**207- On-disk page format change? (`pd_*` fields, opaque-area layout.)208- WAL record change? (New record, new info byte, existing record209 extended.) If yes, is `XLOG_PAGE_MAGIC` bumped?210- Catalog change? (`pg_proc.dat`, `pg_type.dat`, etc.) If yes, is211 `CATALOG_VERSION_NO` bumped? Are new OIDs assigned?212- Public API / extension ABI? (Anything in `src/include/`.) Inline213 functions / macros there count. If touching back-branchable code:214 new struct members must go at the end; no signature changes on215 exported functions.216- Replication protocol change? (`libpq` wire format, walsender output217 plugins, logical decoding output formats.)218- pg_dump impact? (Any new schema object.)219220**Output:** same structured list. For each blocking break, name the221upgrade/backpatch story the author needs to provide.222223#### Critic C — Test coverage224225**Scope:** is the patch tested adequately for what it claims?226227**Loads:** `testing` skill + the touched subsystems' "test surface"228sections + `src/test/` for the existing coverage of the touched code.229230**Checks:**231- Does the diff include `src/test/` changes? If not, is the claim "pure232 refactor, no new behavior, existing tests cover" defensible?233- For a refactor: does at least one existing test exercise the code234 path being refactored? (Find by `git grep` for the function name in235 `src/test/`.) If not, the "existing tests cover" claim is weak.236- For new behavior: does the new test ACTUALLY fail without the code237 change? (The classic "test passes both with and without the patch"238 bug.) Sub-agent can't easily verify this without re-running tests239 twice — instead it flags this as a question for the author or for240 manual follow-up.241- Corner cases: NULL, empty input, max-length, encoding edges,242 concurrent calls, parallel-worker visibility, replication catchup.243 Sub-agent enumerates which apply to this patch's surface.244- Isolation tests needed? Concurrent-modification scenarios?245- TAP tests needed? Multi-node, recovery, replication, crash-recovery246 scenarios?247248**Output:** same structured list. The "blocking" bar here is whether249the patch's correctness claim is mechanically testable from what's in250the diff.251252#### Critic D — Style & commit-message253254**Scope:** would a committer have to fix the format before applying?255256**Loads:** `commit-message-style` + `coding-style` + `review-checklist`257Phase 5 (Coding review) + Phase 7 (Committer-readiness).258259**Checks:**260- Patch filename: `vN-NNNN-<title>.patch`?261- Commit message: imperative title, no period, ~76-col wrap, no emoji,262 no `Co-Authored-By` (forbidden upstream), Author/Reviewed-by trailers263 if relevant, Discussion: link if relevant.264- Code style: matches surrounding module (camelCase vs snake_case),265 no leftover debug `elog`, no commented-out code, no new compiler266 warnings flagged in stage 0.267- Error messages follow the message style guide (capitalization,268 no period on `errmsg`, separated `errdetail`/`errhint`).269- `git diff --check` clean? (Trailing whitespace, broken tab/space mix.)270- `pgindent` clean? (May not be runnable locally — note `pg_bsd_indent`271 install state; CI will catch.)272273**Output:** same structured list. Most items here are `suggestion` or274`warning`; only fundamentally broken style is `blocking`.275276#### Critic E — Reviewer-reflex probes (added 2026-06-12 from Phase C)277278**Scope:** does the patch trigger any of the persona-driven reflexes279the corpus has documented but the generic critics A-D don't encode?280281**Loads:** `knowledge/calibration/gap-catalog.md` (the 11-item282catalog) + `knowledge/personas/<name>.md` for each persona named in283items 4-11 that triggers + `knowledge/personas/committer-map.md` +284`knowledge/personas/domain-ownership.md` (item 11 cross-reference).285286**Checks (each maps 1:1 to a catalog item):**287288- **Cleanup-on-early-return tracing (catalog #4).** Scan the diff for289 a new `return` statement added inside a function whose entry block290 owns a resource handle (`z_stream`, `BufFile`, `FileFd`,291 `MemoryContext`, `Relation`, `LWLock`). If found, surface "trace292 cleanup path under the new error return — does293 `<resource>_destroy()` / `_close()` / `_release()` run on this294 branch?". Driver: `daniel-gustafsson.md` errorhandling discipline.295296- **Multibyte/encoding interaction (catalog #5).** Scan the diff for297 byte-walking patterns (`*p++`, `*input++`, manual `for` loops over298 `varlena`/`text`/`cstring`) OR size caps on text-processing299 primitives. If found, surface "enumerate worst-case per encoding300 (UTF-8 documented, GB18030, EUC_JP, EUC_KR, EUC_CN, EUC_TW); cite301 the Unicode TR / SpecialCasing.txt entry for any UTF-8-specific302 bound". Driver: `noah-misch.md` §4 + `jeff-davis.md` Unicode303 standard fidelity.304305- **Subsystem-local cap discoverability (catalog #6).** Scan the306 diff for a new `#define` in a `contrib/*/*.c` file (not header).307 If found, surface "move to `<subsystem>.h` if a public-style cap;308 cite the precedent constant in the same area (e.g.309 `LQUERY_MAX_LEVELS` for `ltree_io.c`)". Driver:310 `peter-eisentraut.md` style reflex.311312- **"Third state" cross-check for binary-format changes (catalog313 #7).** Scan the diff for changes in how a flag-bit, version-bit,314 or layout-bit is interpreted. If found, surface "enumerate the315 third state: bit set but structure invalid, OR bit unset but316 structure looks valid — what handles each?". Driver:317 `heikki-linnakangas.md` binary-format reflex.318319- **`injection_points` reproducer for DoS / scratch-allocation /320 race claims (catalog #8).** Scan the commit-message + COVER for321 phrases like "prevents N MB scratch", "N GB allocation", "fixes a322 race", "OOB read", "amplification". If found AND the patch has323 no `src/test/modules/injection_points/` change, surface "include324 an `injection_points` measurement at the allocation /325 race-windowed boundary; the structural argument is not enough on326 a security claim". Driver: `noah-misch.md` §5.327328- **Hot-path branch-prediction / micro-benchmark (catalog #9).**329 When the patch touches a function in `src/backend/utils/adt/*`,330 `src/backend/access/{heap,nbtree}/`, `src/backend/optimizer/`, or331 similar query-evaluator path AND adds a new guard check, surface332 "include micro-benchmark numbers confirming the guard is in the333 unlikely branch and adds <1% overhead on typical inputs". Driver:334 `thomas-munro.md` + `heikki-linnakangas.md` performance reflex on335 hot paths.336337- **Symmetric-check refactor for N-entry-point guards (catalog338 #10).** Diff scan for 3+ near-identical added blocks (heuristic:339 same `if`/`ereport`/`ereturn` pattern at 3+ places). If found,340 surface "consider a shared inline helper `<module>_check_<thing>()`341 to keep entry points symmetric". Driver: `peter-eisentraut.md`342 symmetric-primitives reflex.343344- **Persona-aware backpatch routing (catalog #11).** When COVER345 claims back-patching AND the predicted top committer for the346 touched subsystem (from `domain-ownership.md` top-committer347 column) has a 24mo backpatch rate < 5% (compute from348 `committer-map.md` or `/usr/bin/git log --author=<name> --since=349 '2yr' --pretty=%s | grep -ciE 'back.?patch'` ratio), surface "X350 doesn't backpatch in 24mo; the realistic v16/v17/v18 landing351 committer is Y (from `domain-ownership.md` reviewer column — pick352 the highest-ranked committer who backpatches at ≥10%). CC them353 on the thread.". Driver: Peter Eisentraut row in354 `committer-map.md`.355356**Severity rules for Critic E:**357358- Catalog #1-#3 are NOT this critic's job — they live in359 `review-checklist` Phase 0 (gates that block before the patch360 enters the critic fan-out).361- Catalog #4, #5, #7, #8 are `warning` (sometimes `blocking` if the362 COVER doesn't even acknowledge the question).363- Catalog #6, #9, #10, #11 are `suggestion` by default — they364 improve the patch but don't block.365- Catalog #5 escalates to `blocking` if the patch caps a text366 primitive AND no per-encoding analysis is in the COVER — that's367 a real correctness gap (e.g. SP2 had this; the 3× UTF-8 bound368 may not hold for GB18030).369370**REJECT-track escalation (M4).** When Critic E surfaces 3+371`blocking`-severity findings from the catalog AND the372context-awareness signal (engagement class `contested` OR a373documented `INV-*` invariant is foreclosed), the critic's output374should explicitly recommend a `REJECT-A` Stage-3 verdict rather than375"Waiting on Author". The Stage-3 orchestrator then decides between376REJECT-A (the grade above), REJECT-B (acknowledge that the critic377may have missed a concern), or downgrade to non-REJECT if the378findings don't actually compose to a design-level NACK. Critic E379*recommends*; Stage 3 *decides*.380381**Critic E severity matrix at a glance:**382383| Catalog # | Probe | Default | Escalates to blocking when |384|---|---|---|---|385| #4 | Cleanup-on-early-return | warning | COVER doesn't acknowledge the cleanup question |386| #5 | Multibyte / encoding | warning | text-primitive cap added with no per-encoding analysis in COVER |387| #6 | Subsystem-local cap discoverability | suggestion | — |388| #7 | "Third state" binary-format | warning | COVER doesn't enumerate bit-set-but-invalid AND bit-unset-but-looks-valid cases |389| #8 | injection_points reproducer | warning | structural argument on a security claim with no injection_points test |390| #9 | Hot-path micro-benchmark | suggestion | — |391| #10 | Symmetric-check refactor | suggestion | — |392| #11 | Persona-aware backpatch routing | suggestion | — |393394REJECT-track escalation: 3+ `blocking` from this table AND context-395awareness signal (engagement class `contested` OR foreclosed396`INV-*`) → recommend REJECT-A to Stage 3.397398**Output:** same structured-finding list as critics A-D, plus an399optional `recommend_verdict: REJECT-A | REJECT-B` field when the400escalation rule above triggers.401402### Stage 3 — orchestrator consolidates (10 min)403404**Critic-E recommendation vs orchestrator verdict.** Critic E may405emit `recommend_verdict: REJECT-A | REJECT-B` when its catalog-item406threshold (3+ blocking findings + context-awareness signal) fires.407The orchestrator at Stage 3 *decides*; Critic E *recommends*. The408orchestrator may downgrade the recommendation to "Waiting on409Author" if the findings, in aggregate, do NOT compose to a410design-level NACK. Critic E's recommendation is one input, not the411verdict.412413The main agent gathers all four critics' outputs and:4144151. **Deduplicates.** Two critics may flag the same issue from different416 angles — merge into one finding with both rationales.4172. **Resolves conflicts.** If critic A says "this is fine" but critic B418 says "this breaks ABI", the orchestrator re-reads both and picks the419 stronger argument. Cite both in the merged finding.4203. **Severity prioritization.** Group findings into:421 - **Blocking** (must fix before commit; flip CF to "Waiting on Author")422 - **Warning** (should fix or justify)423 - **Nits / suggestions** (take or leave)424 - **Open questions** (need author input)4254. **Verdict.** Decide one of:426 - Ready for Committer427 - Waiting on Author (blocking issues)428 - Needs more info from author (open questions dominate)429 - **REJECT-A** — design fundamentally wrong, all critical problems430 identified, alternative proposed. The right deliverable is a431 thread reply explaining the rejection with cites; saves community432 cycles. Use this when the patch is in `contested` engagement433 class or the Context-awareness probe (from434 `pg-feature-plan`) flagged it.435 - **REJECT-B** — design wrong, but you missed at least one major436 concern that a critic from the community will raise. Solid but437 incomplete; send the reply, acknowledge gaps.438 - **REJECT-C** — rejected for the wrong reasons OR rejected when439 the proposal is actually sound. **STOP** — escalate to user440 before posting. Likely you need to re-run with looser441 priors or load more corpus.442443 M4 origin:444 `knowledge/shadow-implementations/money-fx-exchange/skill-gaps.md`.445 The REJECT-A/B/C grades parallel the A-F grade rubric on446 non-REJECT outcomes — they're not lesser verdicts, just the right447 shape for proposals that shouldn't proceed.448449### Stage 4 — synthesize the review email450451**Use the `commit-message-style` skill's tone rules** — imperative,452plain text, no HTML, no emoji, ~76 col wrap. The review email lives at453`sessions/<date>-cf<N>-review.md` (or pr<N>) and has this shape:454455```456To: pgsql-hackers@lists.postgresql.org457Cc: <author> <author@email>458Subject: Re: [PATCH v<N>] <patch subject>459460<one-line summary of where the patch stands>461462<one or two paragraphs of the high-level read — what the patch does, why463the corpus thinks it's coherent (or not). Cite specific anchors where464relevant: nbtpage.c:407, knowledge/subsystems/access-nbtree.md §4.>465466Blocking issues:467 1. <one-line summary>468 <2-4 lines of context + concrete ask>469 2. ...470471Warnings / consider:472 1. ...473474Nits, take or leave:475 1. ...476477Open questions:478 1. ...479480Testing performed:481 - git am: <clean | rejected hunk in X>482 - ninja install: <clean | warnings: ...>483 - meson test regress/regress: <NNN subtests, all pass | failed: ...>484 - meson test --suite isolation: <NNN subtests, all pass | failed: ...>485 - Patch base: <upstream-master short-sha>486487<closing line: "I think this is ready for a committer" / "Marking488Waiting on Author pending the items above" / etc.>489490Regards,491[Reviewer]492```493494Below the email in the SAME session file, append:495496```497---498499## Per-critic raw findings500501### Critic A — Architecture & invariants502<paste the sub-agent's structured list>503504### Critic B — Breaking-change scan505<paste>506507### Critic C — Test coverage508<paste>509510### Critic D — Style & commit-message511<paste>512513## Stage 0 mechanical log514- Patch source: <URL or path>515- Base ref: <upstream-master sha>516- Apply: <git am output summary>517- Build: <ninja install summary>518- regress: <pass/fail counts + duration>519- isolation: <pass/fail counts + duration>520- Targeted suites: <if any>521- Pre-existing flakes encountered: <list, with dismissal rationale>522523## Wall time524- Stage 0: <min>525- Stage 1: <min>526- Stage 2 (4 critics in parallel): <max of the four, plus orchestration overhead>527- Stage 3: <min>528- Stage 4: <min>529- Total: <min>530```531532## Boundaries vs other skills533534- **`review-checklist`** (the eight-phase scaffold — Phase 0 added535 2026-06-12 for reviewer-reflex gates): each critic walks the536 relevant phase of it. This skill orchestrates five critics doing537 that in parallel (A-E; E added 2026-06-12 from Phase C) and538 synthesizes. Don't bypass `review-checklist`'s phase definitions —539 extend them.540- **`patch-submission`**: the self-review counterpart. If you're541 reviewing YOUR OWN patch before mailing, use that — it invokes the542 same critics but on the pre-submission path.543- **`commit-message-style`** (upstream PG): used by the synthesizer for544 the review-email tone AND by critic D for judging the patch's commit545 message.546- **`meta-commit-style`** (postgres-claude): does NOT apply to the547 review email (which goes to pgsql-hackers, not into postgres-claude).548 It WOULD apply to the session-log commit (if any) and to the549 STATE.md update.550551## What to escalate to the user mid-review552553- **Stage-0 fail** (patch doesn't apply, build breaks, regress fails):554 stop, report, ask whether to send a "rebase needed" reply or to skip.555- **Corpus drift** detected in stage 1 (cites stale > 10%): stop, ask556 the user whether to (a) refresh the corpus first via a separate557 `hf(corpus):` commit (per Rule R9 of558 `.claude/rules/pg-implement-discipline.md` — corpus fixes are their559 own commits in the meta-repo), or (b) proceed with a "best-effort560 against possibly-stale docs" caveat noted in the review email's561 "Testing performed" block.562- **Touched file not in any subsystem doc**: don't stop; note in the563 review email's "Testing performed" block that this area is564 uncovered by the corpus. After the review, file a followup to565 document that subsystem.566- **Two critics genuinely disagree** after orchestrator consolidation:567 ask the user to break the tie before drafting the email.568569## Style notes570571- The review email is the deliverable; everything else is working notes.572 Make the email scannable — bullets, no walls of prose.573- Cite specific file:line anchors in the email when relevant. The574 validation run proved this is what makes a review feel grounded vs575 generic.576- Distinguish blocking from nits in EVERY review. "Needs more tests" is577 not blocking unless the patch's correctness claim depends on the578 missing test.579- For performance-impacting patches: ask for pgbench numbers with580 exact recipe (hardware, build flags, run count, master baseline).581 Numerical claims without a recipe get bounced.582- If invoking via the `/pg-review` slash command, the command already583 did stage 0 — skip ahead to stage 1.584585## Where the artifacts live586587- Review email + appendices: `sessions/<date>-cf<N>-review.md` in588 `postgres-claude/` (this repo).589- Patch branch: `dev/cf<N>-review` (the mutable PG clone). Disposable590 after review is sent.591- No `knowledge/` writes by this skill — if the review surfaces a592 corpus gap, file a follow-up `hf(corpus):` commit separately (per593 R10 of `.claude/rules/pg-implement-discipline.md`).594595## Validation reference596597The 2026-06-02 v0 review of CF #6402598`[unverified: session log not preserved in sessions/ at the time of this writing]`599is the calibration target — re-running THIS skill against that patch600should reproduce a review of comparable quality (same draft conclusion,601same blocking-vs-nit split) in less wall time than the v0 manual walk.602A future preserved-and-named calibration session can replace this603paragraph.604605## Cross-references606607- `.claude/skills/review-checklist/SKILL.md` — the eight-phase scaffold each critic walks; Phase 0 hosts the REJECT-A/B/C grade rubric this skill's Stage 3 verdict consumes.608- `.claude/skills/patch-submission/SKILL.md` — invokes this skill in `--self` mode for the self-review path.609- `.claude/skills/pg-feature-plan/SKILL.md` — supplies the Context-awareness probe + Thread-engagement classification that drive Critic E's REJECT-track escalation.610- `.claude/skills/commit-message-style/SKILL.md` — Critic D + synthesizer use this for upstream PG commit-message format.611- `.claude/skills/coding-style/SKILL.md` — Critic D style check.612- `.claude/skills/testing/SKILL.md` — Critic C test-coverage check.613- `.claude/skills/wal-and-xlog/SKILL.md`, `.claude/skills/catalog-conventions/SKILL.md` — Critic B breaking-change scan.614- `.claude/skills/locking/SKILL.md`, `.claude/skills/memory-contexts/SKILL.md`, `.claude/skills/error-handling/SKILL.md` — Critic A architecture check.615- `knowledge/calibration/gap-catalog.md` — items 4-11 source Critic E's eight reflex probes.616- `knowledge/personas/*.md` — Critic E loads relevant persona docs per probe.617- `knowledge/shadow-implementations/money-fx-exchange/skill-gaps.md` — M4 origin (REJECT-A/B/C verdict).618- `.claude/commands/pg-review.md` — slash-command wrapper that runs Stage 0 inline.