Browse the documentation

bmad-plus review

Reference for bmad-plus review: seal a review scope, anchor findings on the code, derive a verdict from coverage, resume, compare and list rules, with flags and exit codes.

On this page
  1. Synopsis
  2. The order of work
  3. What it reads and writes
  4. Effort levels and the plan
  5. Review rules
  6. Exit codes
  7. Sample output
  8. Errors and what to do
  9. Examples
  10. Using it in CI

bmad-plus review is the evidence layer of a code review. It does not read your code with a model and it does not judge it: the assistant (usually Sentinel) does the reading. The command fixes what is being reviewed (the scope), checks that every quoted finding really sits in the code, and derives the verdict from what was actually covered, so a review that stopped halfway can never be reported as clean. Use it when you want a review whose result you can check, script or gate a pull request on.

Note What clean means

clean means: no open finding within a fully covered scope. It does not prove the code correct, and a review with zero findings is allowed. Missing, failed or invalid evidence gives incomplete, never clean.

Synopsis

In your project terminal
npx bmad-plus review <action> [id] [options]
npx bmad-plus review rules [path]
npx bmad-plus review compare <id> --since <earlier-id>

id names a review and becomes a folder: lowercase letters, digits, dots and dashes, starting with a letter or digit, at most 81 characters (for example pr-42). rules is the only action that takes a path instead of an id.

The six actions
ActionWhat it doesWrites
scope <id>Seals what is reviewed: the changed files between two commits (or the working tree), which of them are selected, which rules apply to each, and the review plan.scope.json, checklist.md
anchor <id>Validates findings.json, then locates every quoted excerpt in the code at head. Credential-like values are replaced by [REDACTED] in the written record.findings.anchored.json
gate <id>Derives the verdict from the scope, the coverage and the anchored findings: clean, findings or incomplete.optionally a CI check file
continue <id>Lists what an interrupted review still owes, against the same sealed scope. Refused when the code or the rules moved.continue.json
compare <id> --since <earlier-id>Sorts this review’s findings against an earlier review: new, persisting, resolved, refuted, not reviewed.compare.json
rules [path]Prints the effective rule set, or the rules a given path would get.nothing
Options of review
FlagArgumentDefaultWhat it does
-d, --directory<path>current folderProject folder.
--dir<path>_bmad-output/reviewReview folder inside the project. Each review lives in <dir>/<id>/.
--base<ref>HEAD~1 (HEAD with --workspace)Base commit or branch. The scope starts at the merge base of base and head.
--head<ref>HEADHead commit or branch.
--workspace-offReview the working tree against the base, untracked files included.
--include<glob>noneOnly review matching paths. Repeatable.
--exclude<glob>noneNever review matching paths. Repeatable.
--effortlow|medium|highmediumReview depth (see below).
--since<id>nonecompare only: the earlier review to compare against. Required there.
--emit-check<file>nonegate only: also write the verdict as a JSON check result for CI. Must be a .json file.
--json-offMachine-readable output instead of text.

The order of work

  1. Seal the scope

    review scope <id> writes scope.json and a checklist of the rules that apply to the changed paths. The scope has a digest: any later change of code or rules is detectable.

    In your project terminal
    npx bmad-plus review scope pr-42 --base main --effort high

  2. Review and write the evidence

    The assistant reads the files, writes findings.json (each finding quotes its code verbatim, with category, severity, confidence and disposition) and coverage.json (every selected file ends as completed, failed or waived with a reason). BMAD+ never calls a model for this.

  3. Anchor the findings

    review anchor <id> finds each quoted excerpt in the code. Line numbers written by a model are never used; only the quote is.

    In your project terminal
    npx bmad-plus review anchor pr-42

  4. Ask for the verdict

    review gate <id> derives clean, findings or incomplete. Add --emit-check to get a JSON document a CI step can consume.

    In your project terminal
    npx bmad-plus review gate pr-42 --emit-check ci/review-check.json

  5. Resume or compare when needed

    review continue <id> after an interruption; review compare <new-id> --since <id> after the code changed and you reviewed again.

What it reads and writes

The command reads the git history and files of the project (it starts git for rev-parse, diff, merge-base and ls-files) and the review rules. It writes only inside <dir>/<id>/, plus the --emit-check file. It opens no network connection and calls no model.

Files in the review folder
FileWritten byContent
scope.jsonscopeBase, head, merge base, selected and excluded files with reasons, rules per file, units, plan, digest.
checklist.mdscopeThe rules that apply to the changed paths, as a checklist for the reviewer.
findings.jsonthe assistantSchema bmad-plus/review-findings/1; each finding quotes existing_code verbatim.
coverage.jsonthe assistantOne item per selected file (completed, failed, waived with a reason) and how the run ended (run.stop).
findings.anchored.jsonanchorThe findings with their located lines and counts of located, ambiguous and unlocated.
continue.jsoncontinueThe packet of remaining work.
compare.jsoncompareThe new, persisting, resolved, refuted and not-reviewed findings.

Closed vocabularies

Allowed values in findings.json and coverage.json
FieldValues
severitycritical, high, medium, low
categorycorrectness, security, data-loss, concurrency, performance, error-handling, compatibility, test-gap, maintainability, documentation
confidencehigh, medium, low
dispositionconfirmed, refuted, unresolved
coverage outcomecompleted, failed, waived
run.stopcompleted, budget, time-limit, failure-streak, interrupted

An unknown value is an error, never coerced. A refuted finding must keep its refutation, a confirmed one needs evidence, a failed or waived file needs a reason. Only run.stop: completed lets the gate reach a verdict; any other reason keeps it incomplete. A unit that fails three attempts in a row is abandoned and stays failed.

Effort levels and the plan

--effort
LevelPassesRefutation pass
low1no
medium (default)2yes
high3yes

A pass is a complete read of the scope; later passes look for what earlier ones missed. The plan printed by scope also depends on size: from 150 changed lines the reviewer plans before reading, and with more than one unit and at least 400 changed lines the units can be reviewed in parallel. A unit groups at most 8 files and 400 lines.

Files that are never selected

  • secret: .env*, keys and certificates (*.pem, *.key, *.p12, *.pfx, id_rsa*, id_ed25519*), .npmrc, .netrc, and anything under credentials/, .credentials/ or secrets/. Checked before any --include, so no pattern can bring them in.
  • binary, deleted, excluded-by-pattern (your --exclude), not-included (outside your --include).
  • generated-or-vendored: node_modules, dist, build, coverage, vendor, minified files, source maps and lockfiles, unless an --include pattern matches them.
  • The review folder itself: writing findings never changes the scope they answer.

Review rules

A rule is a Markdown checklist chosen by file path. Every rule whose patterns match a file applies to it, so rules add up. Eight ship with the CLI.

Built-in rules
Rule idGroupApplies to
generalcodeevery file
javascript-typescriptcodejs cjs mjs jsx ts cts mts tsx vue svelte
pythoncodepy pyi
sql-and-migrationsdata*.sql, migration folders, *.prisma, schema.rb
shellcodesh bash zsh ps1 psm1, Makefile
ci-workflowsdeliveryGitHub Actions, GitLab CI, Bitbucket and Azure pipelines
containersdeliveryDockerfile, Containerfile, compose files, Kubernetes and Helm manifests
configurationdeliveryjson yml yaml toml ini properties, package.json, pyproject.toml, requirements*.txt, go.mod, Cargo.toml, composer.json

When the Shield pack is installed, six compliance rules are added (they never replace or disable a built-in one): shield-access-control, shield-personal-data, shield-cryptography, shield-logging, shield-ai-integrations and shield-change-and-supply-chain. Each names the controls it examines as FRAMEWORK:ID, for example ISO27001:A.8.5, SOC2:CC6.1, NIST-800-53:AC-3 or NIS2:Art.21(2)(i), and a finding may cite only controls that the rules for its file examine.

A project adds, replaces (same id) or disables rules in _bmad/review-rules.yaml. Its doc files are Markdown, resolved next to that file. Disabling an unknown id is an error.

_bmad/review-rules.yaml
schema: bmad-plus/review-rules/1
rules:
  - id: billing-money
    title: Money amounts
    group: code
    globs: ['src/billing/**/*.ts']
    doc: review-rules/billing-money.md
disable:
  - python

Exit codes

Exit codes by action
ActionCodeMeaning
scope, rules, compare0Done.
anchor0Every finding is located.
anchor1findings.json is invalid, or at least one finding is ambiguous or unlocated: quote a longer, exact excerpt.
gate0clean.
gate1findings: at least one confirmed or unresolved finding is open.
gate2incomplete: a file is unaccounted for or failed, the evidence is invalid or missing, the run stopped early, or an open finding is not anchored.
continue0A packet of remaining work was written.
continue3moved: the code or the rules changed since the scope was sealed (or coverage.json is invalid).
any action3Error: unknown action, bad id, missing scope or findings, git failure, unreadable or invalid JSON.

Sample output

These transcripts are simulated: the lines follow the message templates of the command, the numbers and the digest are illustrative. The paths printed by the real command are absolute.

Seal a scopeSimulated
npx bmad-plus review scope pr-42 --base main --effort high
<project>/_bmad-output/review/pr-42/scope.json
3 file(s) to review, 41 changed lines, 1 unit(s) — scope 3f9a1c0d52b7
  excluded 1 × generated-or-vendored
checklist: <project>/_bmad-output/review/pr-42/checklist.md
plan: high effort, 3 pass(es), refutation pass
Every selected file must end in coverage.json as completed, failed or waived (with a reason).

Illustrative transcript, not captured from a real run. Source: tools/cli/commands/review.js (scope action message templates)

A gate that is not readySimulated
npx bmad-plus review gate pr-42
pr-42: incomplete — coverage 1/3 completed (0 waived), 0 open finding(s), 0 refuted
  - 2 selected file(s) never accounted for: src/a.js, src/b.js
Exit code 2. The review owes two files.

Illustrative transcript, not captured from a real run. Source: tools/cli/commands/review.js (gate action) and tools/cli/lib/review.js (reviewGate reasons)

A clean verdictSimulated
npx bmad-plus review gate pr-42 --emit-check ci/review-check.json
pr-42: clean — coverage 3/3 completed (0 waived), 0 open finding(s), 0 refuted
  check: <project>/ci/review-check.json
  clean: no open finding within a fully covered scope. It does not prove the code correct.
Exit code 0.

Illustrative transcript, not captured from a real run. Source: tools/cli/commands/review.js (gate action)

The --emit-check document is stable (no timestamp, so the same evidence gives the same bytes). It carries the status, exit code, reasons, counts, the scope it answers, the open findings with their lines and a github block shaped like the check-runs API: conclusion (success or failure) and an output with a Markdown summary and up to 50 annotations. A working-tree review writes its check inside the review folder or outside the project, so it cannot enter the change it reports on.

Errors and what to do

Errors print review: <message> on the error stream (or a JSON object with status: "error" under --json) and exit 3.

Messages
MessageCauseWhat to do
unknown action "x" (scope, anchor, gate, continue, compare, rules)The action is not one of the six.Use one of the listed actions.
a review id is required: lowercase letters, digits, dots and dashesNo id, or an id with other characters.Pass an id like pr-42.
no scope at <path> — run "bmad-plus review scope <id>" firstThe review folder has no scope.json.Run review scope <id> with the same --dir.
invalid ref "..." or git rev-parse failed: ...A --base or --head that does not resolve to a commit.Check the ref (fetch it in CI); refs starting with - are refused.
git is unavailable: ...git is not on the path of the process.Install git or fix the path.
effort must be one of low|medium|highUnknown --effort.Use low, medium or high.
no findings at <path>anchor or compare found no findings.json.Write it, even with an empty list.
--since <earlier review id> is required: ... / --since must name a different reviewcompare without --since, or against itself.Pass the earlier review id.
--emit-check writes a .json file / --emit-check must not overwrite the review evidenceThe check path is not a .json file, or is one of the evidence files.Choose another .json path.
<id> cannot continue: the sealed scope no longer describes the code.Exit 3 from continue: head moved, files changed or rules changed.Seal a new scope with the same options, then review compare <new-id> --since <id>.
gate reasons: no coverage.json: ..., no findings.json: ..., N selected file(s) never accounted for: ..., the review stopped before the end (budget): ...The evidence is missing, partial or the run stopped early. Exit 2.Finish the review (continue), write both files, set run.stop to completed only when it really did.

Examples

Review a pull request with checkable evidence

You want Sentinel to review branch changes against main and to report a verdict you can trust.

In your AI assistant
Sentinel, review this branch against main. If the BMAD+ CLI is available, seal the scope with bmad-plus review scope pr-42 --base main --effort high, quote every finding verbatim, then anchor and gate it, and report the gate answer without upgrading it.

What you should get Sentinel runs review scope, which writes scope.json and checklist.md under _bmad-output/review/pr-42/. It reviews the selected files, writes findings.json and coverage.json, runs review anchor (exit 1 if a quote cannot be located) and review gate. It reports clean, findings or incomplete exactly as the gate printed it. A stopped or partial review is reported as incomplete, never as clean.

Resume an interrupted review

The session ended before every file was read and coverage.json records run.stop as interrupted.

In your AI assistant
Sentinel, continue the review pr-42 where it stopped. Use bmad-plus review continue pr-42 and only do what it lists.

What you should get review continue writes continue.json and prints the files and units still to review, the findings to requote, the passes left and any unit abandoned after three failed attempts. If the code or the rules moved, it refuses with exit 3 and tells Sentinel to seal a new scope and use review compare. When nothing remains, it says to run review gate once coverage.json records the run as completed.

Review again after fixes

The author pushed fixes. You sealed a new scope pr-43 and finished the second review.

In your AI assistant
Sentinel, compare review pr-43 with pr-42 using bmad-plus review compare pr-43 --since pr-42 and tell me what is new, what persists and what is really resolved.

What you should get The command prints pr-43 since pr-42: N new, N persisting, N resolved, N refuted, N not reviewed and writes compare.json. A finding from the earlier review that sits on a file the new review did not complete is counted as not reviewed: it is not known to be fixed.

See which rules apply to a file

You wonder what Sentinel will check in an authentication file when Shield is installed.

In your AI assistant
Sentinel, run bmad-plus review rules src/auth/login.ts and tell me which rules and which compliance controls apply.

What you should get The command prints the rule set digest and the layers it was built from (built-in, pack files, project file), then src/auth/login.ts gets N rule(s), one line per rule with its id, group, layer and patterns, and for Shield rules the controls such as ISO27001:A.8.5 and SOC2:CC6.1. Rules a project disabled are listed as disabled. Nothing is written.

Using it in CI

The repository ships copy-ready GitHub Actions recipes in docs/recipes/ci-review/: review-scope.yml seals the scope and publishes the checklist (no agent, no model), review-gate.yml has the host agent installed on a self-hosted runner write the evidence, verifies that nothing outside the review folder changed, anchors the findings and fails the check on incomplete or open findings. They run only for pull requests from the repository itself, never from forks, and need no model key stored in GitHub. In a script, the three exit codes are enough: 0 passes, 1 means findings to read, 2 means the evidence is not there yet.