Review Context Mode
How diff-only and diff+semantic change what PatchPatrol reviews before it calls the model.
Review Context Mode
AI_REVIEW_CONTEXT_MODE decides whether PatchPatrol reviews only the extracted
diff or also runs local semantic checks before the model sees the change.
Most teams should start with diff-only. Move to diff+semantic when the
project is trusted enough to run its analyzers in CI and the runner already has
the right toolchains and dependencies.
The Short Version
| Mode | What PatchPatrol does | Good fit |
|---|---|---|
diff-only | Reviews the bounded diff with the normal provider flow. Semantic analyzer tools are disabled. | Default MR pipelines, first rollout, forks, and any review where predictable execution matters more than extra analyzer evidence. |
diff+semantic | Runs best-effort local analyzer checks first, then gives relevant diagnostics to the model and records semantic findings in the report. | Trusted internal branches or MRs where CI already restores dependencies and analyzer output helps catch build, syntax, import, type, or undefined-symbol problems. |
Set it with an environment variable:
AI_REVIEW_CONTEXT_MODE=diff-onlyor:
AI_REVIEW_CONTEXT_MODE=diff+semanticYou can also set it in .ai-review.yml:
version: 1
defaults:
review_context_mode: diff-onlyWhat diff-only Means
diff-only is the default. PatchPatrol extracts the bounded diff, plans chunks,
builds the normal prompt context, calls the configured provider, validates the
provider response, and writes the review artifacts.
It does not run semantic analyzer tools first.
Use diff-only when you want the smallest execution surface. It is also the
best default for forked merge requests, untrusted branches, early pilots, and
CI jobs where you do not want project-controlled analyzer configuration to run.
What diff+semantic Adds
diff+semantic adds a precheck phase before provider review. PatchPatrol looks
at the changed files, chooses matching adapters, runs the available tools, and
keeps the diagnostics that fit inside the supporting-context budget.
Those diagnostics are used in two ways:
- Relevant diagnostics are added to the model context for the affected review chunks.
- Deterministic diagnostics can become final findings even when the model does not report them.
The report records where a finding came from. You may see provenance such as:
llm: the model reported the finding.semantic: a semantic precheck reported the finding.combined: both sources pointed at the same problem.
This helps when you are trying to understand whether PatchPatrol found an issue through model judgment, deterministic tooling, or both.
Tools PatchPatrol Can Reuse
In plain terms, semantic mode is reuse-only. PatchPatrol runs tools that already exist in the runner and repository context. It does not install toolchains, package dependencies, analyzer plugins, or project-specific configs.
| Language group | Preferred tool | Fallback | Scope |
|---|---|---|---|
| Python | ruff check --output-format json | python -m py_compile | Changed Python files |
| JavaScript / TypeScript | eslint -f json when ESLint is configured | tsc --noEmit --pretty false when tsconfig.json exists | Changed JS/TS files |
| PHP | phpstan analyse --error-format=json when PHPStan is configured | php -l | Changed PHP files |
| Shell | shellcheck --format=json1 | none | Changed shell files |
| Go | go build <affected package scope> | none | Smallest changed package scope from the nearest go.mod |
| Rust | cargo check --quiet --message-format=json | none | Smallest changed crate scope from the nearest Cargo.toml |
Missing tools are not fatal by themselves. PatchPatrol records the outcome in
meta.semantic_precheck and continues with the review unless another fatal
condition occurs.
Common statuses:
disabled: semantic mode was not enabled.unsupported: no useful adapter or tool was available for the changed files.degraded: some semantic work ran, but part of it was skipped or timed out.ok: semantic precheck completed without degraded-tool signals.
Runtime Requirements
diff+semantic is only as good as the environment it runs in.
For Python-only repositories, PatchPatrol can still get useful coverage from
ruff or the built-in python -m py_compile fallback.
For JavaScript and TypeScript repositories, restore dependencies before the
review step. Without npm ci, pnpm install --frozen-lockfile, or the
equivalent for your project, ESLint plugins and TypeScript project references
often cannot resolve.
For PHP repositories, run composer install before review so PHPStan, autoload
files, and project plugins resolve correctly.
For Go and Rust, the runner needs the language toolchain and enough project
context for go build or cargo check to run against the affected package or
crate.
Trust Impact
diff+semantic can execute project-controlled tooling.
On trusted internal code, that usually gives you better review signal. It also changes the trust boundary compared to plain diff review, because tools such as ESLint, PHPStan, Cargo, Composer plugins, or project-local scripts may load configuration and dependencies from the repository under review.
Use diff-only as the baseline for broad MR coverage. Enable diff+semantic
only where runner policy already allows local analyzer execution for that
source.
A sane default:
- Use
diff-onlyfor forks, external contributions, and the first rollout. - Use
diff+semanticfor trusted internal branches after dependency restore is already part of CI. - Keep semantic tooling behind an explicit opt-in in wrapper scripts and managed runners.
- Check
meta.semantic_precheck.statusbefore treating semantic coverage as strong evidence.
Bounds And Timeouts
Two settings matter most once semantic mode is enabled:
| Variable | Default | Meaning |
|---|---|---|
AI_REVIEW_SEMANTIC_TOTAL_TIMEOUT_SECONDS | 20 | Total timeout budget for all semantic precheck work in a run. |
AI_REVIEW_MAX_SUPPORTING_CONTEXT_BYTES | 65536 | Byte budget for supporting context that can be carried into prompts and retained in metadata. |
If the semantic budget is exhausted, PatchPatrol records timeout reason codes and continues with whatever evidence is available. It does not turn missing or partial semantic coverage into a failed review by itself.
What Changes In The Artifacts
In diff-only, semantic metadata is either absent or records that semantic
precheck was disabled.
In diff+semantic, inspect:
meta.review_context_modemeta.semantic_precheck.statusmeta.semantic_precheck.reason_codesmeta.semantic_precheck.attempted_toolsmeta.semantic_precheck.unsupported_toolsmeta.semantic_precheck.timed_out_toolsfindings[].provenance
These fields tell you whether semantic tooling ran, which tools were attempted, what was skipped, and whether a finding came from the model, semantic tooling, or both.
Which Mode Should You Pick?
Use diff-only when you are unsure. It is the stable baseline and keeps the
review closer to "read this diff and report findings."
Use diff+semantic when all of these are true:
- The source being reviewed is trusted enough to run local analyzers.
- The CI image has the needed language runtimes.
- The job restores repository dependencies before PatchPatrol runs.
- You want deterministic analyzer evidence in addition to model review.
- You are willing to read
meta.semantic_precheckto understand degraded or unsupported runs.
For many teams, rollout is straightforward: start on diff-only, then enable
diff+semantic on trusted internal projects where the extra diagnostics are
worth the runtime and trust tradeoff.
Return to Reference.