Work out the target first. A pull request number or URL means its diff against the base
branch: resolve the exact base and head commits with the host's CLI (gh pr view on
GitHub, az repos pr show on Azure DevOps), fetch either that is not local, and diff
them. A branch name means its diff against the merge base with the default branch. A
commit means that commit. With no argument, review the working tree against HEAD. Fix
the comparison once, as two commits or the working tree, and give every subagent the
same one. Confirm that both sides resolve and that the diff is non-empty before spawning
any pass; if either fails, report which and stop. Then find the stated intent: the pull
request title and description, the commit messages, or for an uncommitted working tree
the user's own description of the change. Look in that description and those commit
messages for an issue reference (#123, Closes #45) and, when there is one, fetch the
issue with the host's CLI (gh issue view, az boards work-item show) and pass what it
asks for as part of the intent: the description was often written after the change, the
issue before it. If the fetch fails, say the issue was not read and use the description
alone. If no intent exists, say so and review against what the diff itself appears to
do.
Read project_doc_fallback_filenames from the Codex configuration if it is readable, so
the guidelines pass knows which instruction files count. Codex loads no fallback file
unless one is configured, so if the configuration is not readable, tell the guidelines
pass that the fallback names are unknown rather than guessing one.
Run one subagent for every other skill in this plugin whose name starts with
code-review-, except the two whose surface the diff may not touch, decided here
because each decision is one command and a pass costs a whole thread:
code-review-change-size: sum the added and deleted lines the comparison reports, with
git diff --numstat over the same base and head. A binary file prints - for both
counts, so read it as zero rather than letting the sum fail. For a working tree,
git diff --numstat HEAD sees no untracked file, so a new file of any size would count
as nothing: list them with git ls-files --others --exclude-standard and add each
one's git diff --no-index --numstat /dev/null <file>. Do not stage them; the review
changes no index. Under 500 the change is under this plugin's default, since the skill's
exclusions only lower the count, so do not spawn it; instead report the count in one line
as under this plugin's default of 500. At 500 or more, spawn it and let it do the
counting properly. A repository that states a lower limit of its own states it in an
instruction file, which the guidelines pass reads, so that line speaks for the default
alone and never says the change is inside a limit this thread did not read.
code-review-guidelines: walk from the repository root down to each directory holding
a changed file and look for AGENTS.override.md, AGENTS.md, or one of the fallback
names above. Look in the tree the comparison names, with
git ls-tree -r --name-only <head>: a pull request's head is fetched but usually not
checked out, so the working tree on disk is a different commit and would answer for the
wrong one. Read the working tree itself only when the working tree is the target. If no
such directory holds one, the repository states no rule that applies to this change, so
do not spawn it; instead report that in one line. Spawn it when the fallback names are
unknown, since a fallback file may be active and unseen, and when the listing fails,
since nothing then says there is no rule.
Spawn each with a fresh context, not a fork of this thread's history:
fork_context false or fork_turns "none", whichever the spawn tool offers. Codex
applies a reasoning override only to a fresh context, and a fork would hand every pass
this thread's reading of the diff. Pass a reasoning override only when the user named a
level (low, medium, high, xhigh) with the request. With no level named, spawn at the
session's own level rather than raising it. Give
each subagent the full path to its SKILL.md, the comparison, the intent, the user's
request and any constraint it states, the fallback names, and the finding format below.
Name each subagent after its skill, with underscores for the hyphens, since the spawn
tool allows only lowercase letters, digits, and underscores. Tell each that the review
is read-only: it changes no file, branch, index, or stash. Codex caps how many agents
run at once; when a spawn is refused for that reason, wait for a running pass to finish
and spawn it again. Do not run any pass, or the verification below, yourself in the
main thread; independent passes are the point, since a single reader anchors on the
first problem it sees. A pass that could not be run is reported as not run.
Finding format
Ask every subagent to report each finding as:
path:line, the changed file and the line the finding anchors to.
- severity: high (security, data loss, crash, or a critical function failing), medium
(an edge case, performance, or maintainability problem that can go wrong), or low
(style, readability, minor best practice). A high finding blocks the merge; medium and
low do not. This is the scale every pass uses; the sub-reviews say only how their own
kind of finding maps onto it.
- what is wrong, in one sentence.
- why it matters, with the fact that shows it: the rule quoted, the caller that passes
the bad value, the test that would fail. Cite only what was observed in the
repository, the diff, the pull request, or a command's output; never a test count,
commit, ticket, or line that was not seen.
- what the code must do.
Verification
Merge the subagents' findings: two are one finding when they name the same defect with
the same required fix, even at different lines; keep both locations and the more
specific wording. Then spawn one more subagent named verification, fresh context and the
same reasoning level, with the merged list, the comparison, the intent, and the
read-only rule. It tries to refute each finding against the code and returns a verdict:
confirmed when it read the line and the defect holds; refuted when it can point to the
line that disproves it; unconfirmed when it could do neither.
Never let a verification that did not answer empty the report. When the verification
subagent cannot be spawned, fails, returns nothing, or returns no verdict for some
merged finding, every finding it left without a verdict is unconfirmed, and what would
settle it is reading the claim against the line it cites, since nothing has tried to
refute it yet. Do not drop it, and do not verify it yourself. When the answer was
empty, no verdict for any finding, spawn verification once more with the same input; an
empty return is the one failure a second thread can fix. If the second one is empty too,
report the findings as unconfirmed and do not spawn it again.
Report
Open with the verdict on its own line, one of three and never two of them. "blocking"
when any confirmed finding is high, with how many findings were confirmed. "not verified"
when no finding carries a verdict because verification did not answer, with how many of
the findings are high: "not verified, 2 high findings unconfirmed". Otherwise "not
blocking", with how many findings were confirmed and, when a high finding was left
unconfirmed, how many: "not blocking, 3 confirmed, 1 high finding unconfirmed". A reader
who stops at this line has to see that a high finding was never settled, so never let it
read as a clean pass while one stands.
Number the confirmed findings and sort them by severity. List unconfirmed findings after
them under their own heading, unnumbered, each with what would settle it. List refuted
findings last, one line each with the disproving path:line. What the fan-out rules
settled here gets its own line with the findings, in the report's own words and without
naming a pass: the changed-line count and that it is under this plugin's default of 500,
as in "18 changed lines, under the 500-line default", and that the repository states no
instruction rule that applies. A label such as "change size" over that line names a pass,
so write the count as a sentence. Neither line is a pass that was not run.
State any pass that was not run, with the reason. When verification did not run, say that
on a line of its own, whether or not any pass was missing, and say that the findings are
unconfirmed for that reason. A "not verified" verdict does not stand in for that line: the
verdict says what the report is, this line says what happened and why nothing was settled,
and a report that opens with the first still carries the second. Then the reasoning level
the passes ran at, or "session default" when no level was passed, all before the coverage
totals. Those lines are the only place a pass is named. Include the coverage totals: files
changed, reviewed, skipped with reasons. Use raw Markdown. Name the project's own tools
where a finding needs them; do not name the review passes, the model, or the review
tooling.
Do not post a comment, review, or label on the pull request host unless asked.
1---2name: code-review3description: Run a full code review of a pull request, branch, commit, or the working tree by fanning out to the code-review-* sub-reviews in this plugin that the change calls for, verifying the findings, and merging them. Use whenever the user asks for a review, a final pass before merge, or 'what's wrong with this change', even if they do not say 'code review'.4---56Work out the target first. A pull request number or URL means its diff against the base7branch: resolve the exact base and head commits with the host's CLI (`gh pr view` on8GitHub, `az repos pr show` on Azure DevOps), fetch either that is not local, and diff9them. A branch name means its diff against the merge base with the default branch. A10commit means that commit. With no argument, review the working tree against HEAD. Fix11the comparison once, as two commits or the working tree, and give every subagent the12same one. Confirm that both sides resolve and that the diff is non-empty before spawning13any pass; if either fails, report which and stop. Then find the stated intent: the pull14request title and description, the commit messages, or for an uncommitted working tree15the user's own description of the change. Look in that description and those commit16messages for an issue reference (`#123`, `Closes #45`) and, when there is one, fetch the17issue with the host's CLI (`gh issue view`, `az boards work-item show`) and pass what it18asks for as part of the intent: the description was often written after the change, the19issue before it. If the fetch fails, say the issue was not read and use the description20alone. If no intent exists, say so and review against what the diff itself appears to21do.2223Read `project_doc_fallback_filenames` from the Codex configuration if it is readable, so24the guidelines pass knows which instruction files count. Codex loads no fallback file25unless one is configured, so if the configuration is not readable, tell the guidelines26pass that the fallback names are unknown rather than guessing one.2728Run one subagent for every other skill in this plugin whose name starts with29`code-review-`, except the two whose surface the diff may not touch, decided here30because each decision is one command and a pass costs a whole thread:3132- `code-review-change-size`: sum the added and deleted lines the comparison reports, with33 `git diff --numstat` over the same base and head. A binary file prints `-` for both34 counts, so read it as zero rather than letting the sum fail. For a working tree,35 `git diff --numstat HEAD` sees no untracked file, so a new file of any size would count36 as nothing: list them with `git ls-files --others --exclude-standard` and add each37 one's `git diff --no-index --numstat /dev/null <file>`. Do not stage them; the review38 changes no index. Under 500 the change is under this plugin's default, since the skill's39 exclusions only lower the count, so do not spawn it; instead report the count in one line40 as under this plugin's default of 500. At 500 or more, spawn it and let it do the41 counting properly. A repository that states a lower limit of its own states it in an42 instruction file, which the guidelines pass reads, so that line speaks for the default43 alone and never says the change is inside a limit this thread did not read.44- `code-review-guidelines`: walk from the repository root down to each directory holding45 a changed file and look for `AGENTS.override.md`, `AGENTS.md`, or one of the fallback46 names above. Look in the tree the comparison names, with47 `git ls-tree -r --name-only <head>`: a pull request's head is fetched but usually not48 checked out, so the working tree on disk is a different commit and would answer for the49 wrong one. Read the working tree itself only when the working tree is the target. If no50 such directory holds one, the repository states no rule that applies to this change, so51 do not spawn it; instead report that in one line. Spawn it when the fallback names are52 unknown, since a fallback file may be active and unseen, and when the listing fails,53 since nothing then says there is no rule.5455Spawn each with a fresh context, not a fork of this thread's history:56`fork_context` false or `fork_turns` "none", whichever the spawn tool offers. Codex57applies a reasoning override only to a fresh context, and a fork would hand every pass58this thread's reading of the diff. Pass a reasoning override only when the user named a59level (low, medium, high, xhigh) with the request. With no level named, spawn at the60session's own level rather than raising it. Give61each subagent the full path to its `SKILL.md`, the comparison, the intent, the user's62request and any constraint it states, the fallback names, and the finding format below.63Name each subagent after its skill, with underscores for the hyphens, since the spawn64tool allows only lowercase letters, digits, and underscores. Tell each that the review65is read-only: it changes no file, branch, index, or stash. Codex caps how many agents66run at once; when a spawn is refused for that reason, wait for a running pass to finish67and spawn it again. Do not run any pass, or the verification below, yourself in the68main thread; independent passes are the point, since a single reader anchors on the69first problem it sees. A pass that could not be run is reported as not run.7071## Finding format7273Ask every subagent to report each finding as:7475- `path:line`, the changed file and the line the finding anchors to.76- severity: high (security, data loss, crash, or a critical function failing), medium77 (an edge case, performance, or maintainability problem that can go wrong), or low78 (style, readability, minor best practice). A high finding blocks the merge; medium and79 low do not. This is the scale every pass uses; the sub-reviews say only how their own80 kind of finding maps onto it.81- what is wrong, in one sentence.82- why it matters, with the fact that shows it: the rule quoted, the caller that passes83 the bad value, the test that would fail. Cite only what was observed in the84 repository, the diff, the pull request, or a command's output; never a test count,85 commit, ticket, or line that was not seen.86- what the code must do.8788## Verification8990Merge the subagents' findings: two are one finding when they name the same defect with91the same required fix, even at different lines; keep both locations and the more92specific wording. Then spawn one more subagent named verification, fresh context and the93same reasoning level, with the merged list, the comparison, the intent, and the94read-only rule. It tries to refute each finding against the code and returns a verdict:95confirmed when it read the line and the defect holds; refuted when it can point to the96line that disproves it; unconfirmed when it could do neither.9798Never let a verification that did not answer empty the report. When the verification99subagent cannot be spawned, fails, returns nothing, or returns no verdict for some100merged finding, every finding it left without a verdict is unconfirmed, and what would101settle it is reading the claim against the line it cites, since nothing has tried to102refute it yet. Do not drop it, and do not verify it yourself. When the answer was103empty, no verdict for any finding, spawn verification once more with the same input; an104empty return is the one failure a second thread can fix. If the second one is empty too,105report the findings as unconfirmed and do not spawn it again.106107## Report108109Open with the verdict on its own line, one of three and never two of them. "blocking"110when any confirmed finding is high, with how many findings were confirmed. "not verified"111when no finding carries a verdict because verification did not answer, with how many of112the findings are high: "not verified, 2 high findings unconfirmed". Otherwise "not113blocking", with how many findings were confirmed and, when a high finding was left114unconfirmed, how many: "not blocking, 3 confirmed, 1 high finding unconfirmed". A reader115who stops at this line has to see that a high finding was never settled, so never let it116read as a clean pass while one stands.117118Number the confirmed findings and sort them by severity. List unconfirmed findings after119them under their own heading, unnumbered, each with what would settle it. List refuted120findings last, one line each with the disproving `path:line`. What the fan-out rules121settled here gets its own line with the findings, in the report's own words and without122naming a pass: the changed-line count and that it is under this plugin's default of 500,123as in "18 changed lines, under the 500-line default", and that the repository states no124instruction rule that applies. A label such as "change size" over that line names a pass,125so write the count as a sentence. Neither line is a pass that was not run.126127State any pass that was not run, with the reason. When verification did not run, say that128on a line of its own, whether or not any pass was missing, and say that the findings are129unconfirmed for that reason. A "not verified" verdict does not stand in for that line: the130verdict says what the report is, this line says what happened and why nothing was settled,131and a report that opens with the first still carries the second. Then the reasoning level132the passes ran at, or "session default" when no level was passed, all before the coverage133totals. Those lines are the only place a pass is named. Include the coverage totals: files134changed, reviewed, skipped with reasons. Use raw Markdown. Name the project's own tools135where a finding needs them; do not name the review passes, the model, or the review136tooling.137138Do not post a comment, review, or label on the pull request host unless asked.