PatchPatrol

Artifacts & Schema

Public contract details for PatchPatrol output artifacts and JSON payload structure.

Artifacts & Schema Reference

Use this page when you want to integrate PatchPatrol output into automation, checkers, or any non-interactive workflow.

Source of truth: schema.json plus the current artifact writing behavior in patchpatrol/artifacts.py and patchpatrol/cli.py.

What PatchPatrol Writes

PatchPatrol writes files into AI_REVIEW_OUTPUT_DIR (default .ai-review).

ArtifactPurposeStability posture
ai-review.mdHuman-readable Markdown Run Report for quick manual review and triage.Stable, documented public artifact.
ai-review.htmlStatic printable HTML Run Report for browser review or PDF export.Default additive artifact; disabled with AI_REVIEW_HTML_REPORT=false or ai-review run --no-html-report.
ai-review.jsonMachine-readable Run Report and canonical FindingsReport payload for scripts and integrations.Stable, documented public contract.
gl-code-quality-report.jsonOptional Code Quality format mirror of findings.Optional output; enabled by default via AI_REVIEW_CODE_QUALITY_EXPORT, including early exits that have no findings and therefore render as [].

ai-review.json, ai-review.md, and ai-review.html are Run Reports for one PatchPatrol execution. The HTML and Markdown Run Reports are human-facing renderings derived from the same validated payload. They can surface review context, Review Outcome, findings, coverage, and token usage sections, but ai-review.json remains the automation contract.

A Run Report does not own the merge request's cross-run Active Finding Set. When optional MR feedback is enabled, that lifecycle belongs to the persistent GitLab Review Summary.

Use the First review output page for quick interpretation.

Core JSON contract (stable)

ai-review.json validates against schema.json with three required top-level fields:

  • meta
  • summary
  • findings

The top-level object and finding objects reject unknown properties, so key names above and their nested fields should match what integrators send to downstream systems.

meta

meta is required and includes at least these stable keys:

  • model
  • base_sha
  • head_sha
  • generated_at
  • diff_base
  • diff_stats
  • limits
  • review_coverage

meta.diff_stats requires:

  • files
  • insertions
  • deletions

meta.limits is a dictionary. It always exists and carries runtime-applied limit values and execution diagnostics.

meta.review_coverage is a deterministic execution manifest. It records what PatchPatrol attempted and what it actually reviewed, including:

  • status: complete, partial, limited, or provider_failed
  • chunk_count and chunk_order_fingerprint
  • chunks_attempted, chunks_succeeded, chunks_retried, and chunks_fallbacked
  • reviewed_bytes, skipped_bytes, and fallbacked_bytes
  • omitted_files with path, reason code, and diff-byte count
  • omitted_reasons grouped by reason code
  • validation.status: passed, fallback, or provider_failed
  • chunk_execution entries with per-chunk attempts, status, bytes, and reason codes

Use meta.review_coverage when you need to distinguish provider-runtime failure from invalid-output fallback and from successfully reviewed chunks. The older meta.limits counters remain for compatibility, but this manifest is the clearer audit surface for reviewed, skipped, retried, and fallbacked scope.

For structured-output provider behavior, meta.limits may also include compact diagnostics such as:

  • structured_output_review_call_count
  • structured_output_requested_modes
  • structured_output_effective_modes
  • structured_output_fallback_count
  • structured_output_reason_codes

These fields are optional and additive. They record output-mode decisions and fallback reason codes without persisting raw prompts or provider request payloads.

When repo-local .ai-review.yml review.rules are configured, meta.limits may also include compact counters such as:

  • prompt_review_rule_total_count
  • prompt_review_rule_matched_count
  • prompt_review_rule_included_count
  • prompt_review_rule_omitted_count

These counters make rule matching observable without persisting raw rule instructions in review artifacts.

Repository-aware runs also add meta.repository_context when repository context metadata is available. Within one execution, ai-review.json is the per-run source of truth for meta.repository_context; the Markdown and HTML Run Reports and GitHub Actions job summary render compact views of that metadata. Repository-context diagnostics stay in the current Run Reports, GitHub Actions job summary, and console Operational Diagnostics; they are excluded from the persistent GitLab Review Summary. That summary owns the merge request's separate cross-run Active Finding Set.

meta.repository_context can include mode, policy_file, policy_file_status, rule counts and matched rule identities, context_budget, context_sources, reason_codes, and persisted_memory. Rule identities expose id, severity, and scope; raw rule instructions are not stored in normal artifacts by default. Source categories can include repo_rules, preflight_hints, supporting_code, semantic_diagnostics, and repository_overview. Current context-source statuses include disabled, included, not_applicable, not_available, not_configured, not_enabled, not_matched, not_run, omitted, omitted_max_bytes, partially_included, truncated, unavailable, and unknown.

See Repository-aware rules for the customer-facing interpretation guide.

When deterministic preflight hints are generated, meta.limits may include compact counters and reason codes such as:

  • prompt_preflight_hint_total_count
  • prompt_preflight_hint_matched_count
  • prompt_preflight_hint_included_count
  • prompt_preflight_hint_omitted_count
  • prompt_preflight_hint_reason_codes

These fields are optional and additive. They make hint matching observable without persisting raw hint evidence, raw prompt bodies, or provider chain-of-thought in artifacts. Preflight hints are prompt evidence only: they can point the provider at duplicate added code-like text, dependency additions, risky import additions, or missing test-counterpart signals, but they are not automatic findings or CI gates.

summary

summary is required and includes these stable fields:

  • overall_risk
  • top_issues

overall_risk is one of low, medium, or high.

findings

findings is required and is an array of finding objects.

A finding currently requires:

  • severity
  • category
  • file
  • line_start
  • line_end
  • title
  • description
  • recommendation
  • confidence

suggested_patch and provenance are optional.

When remediation output is enabled with AI_REVIEW_REMEDIATION_MODE=briefs or AI_REVIEW_REMEDIATION_MODE=suggestions, PatchPatrol derives advisory fix briefs under meta.remediation from validated, unsuppressed findings. This keeps ai-review.json as the canonical artifact for remediation guidance while making clear that all output is human-reviewed guidance. PatchPatrol does not commit, push, or modify repository state.

meta.remediation.briefs[] preserves each finding's file, line range, confidence, fingerprint, title, and recommended action. In suggestions mode, briefs[].suggestion can contain a safe suggested replacement only for high-confidence, narrow findings. GitLab suggestion blocks are emitted only when that advisory suggestion is eligible and the finding also has a valid GitLab inline anchor.

These fix briefs are advisory and human-reviewed; they are not automatic code changes.

line_start and line_end are normal new/right-side integer file line numbers. Provider prompts may render prompt-only L<number>: labels on added and context lines to help the model anchor findings, but those labels are not persisted in ai-review.json, ai-review.md, ai-review.html, or GitLab exports.

Published enums and controlled values

The following enum sets are the reliable values currently emitted and validated:

  • finding.severity: blocker, high, medium, low, info
  • finding.category: security, correctness, reliability, performance, maintainability, testing, style
  • summary.overall_risk: low, medium, high
  • finding.provenance.origin: llm, semantic, security_tool, combined
  • finding.provenance.sources: llm, semantic, security_tool
  • meta.security_precheck.status: pass, fail, unavailable, error, skipped
  • meta.license.status: valid, missing, invalid, expired, not_yet_valid, unsupported

Runtime fields in meta you may see today

The schema allows additional public metadata in meta. In the shipped runtime paths, these meta sections are currently present in supported cases:

  • meta.diff_base
  • meta.license
  • meta.semantic_precheck
  • meta.security_precheck
  • meta.trust_gate
  • meta.provider_runtime
  • meta.feedback
  • meta.incremental_review
  • meta.remediation
  • meta.repository_context
  • meta.repository_overview
  • meta.usage_ledger
  • meta.performance_diagnostics

These are additive and may grow as execution behavior evolves.

meta.license records non-sensitive Self-Hosted License evaluation state when a real-provider review is blocked before provider-backed work. It includes the following fields when available:

FieldMeaning
statusLicense Status: valid, missing, invalid, expired, not_yet_valid, or unsupported.
modeself_hosted for Self-Hosted License v1.
reason_codesStable machine-readable LICENSE_* evaluation reasons.
customer_slugTrusted non-secret customer identifier; omitted when claims are not trusted.
license_idTrusted non-secret support handle; omitted when claims are not trusted.
expires_atTrusted license expiry; omitted when claims are not trusted.
featuresTrusted enabled feature names; omitted when claims are not trusted.

Artifacts never include the raw Signed License payload, signature, or private signing key. License-blocked artifacts mean provider review did not run. Empty findings therefore do not mean the diff is clean, and for a blocked manual source scan they do not mean the codebase is clean. A source scan blocked before extraction records meta.source_coverage.status=not_run_license_blocked instead of inventing source omissions.

meta.diff_base records the strategy used to choose the reviewed diff base. Use it when a branch or merge request is behind its target branch and you need to confirm PatchPatrol reviewed only the feature branch's net changes.

FieldMeaning
strategymerge-base for branch/MR merge-base extraction, gitlab-diff-base-sha when GitLab MR diff refs were used, not-applicable for staged/working-tree modes, or error for early diff-context artifacts.
reason_codesCompact reason codes such as DIFF_BASE_MERGE_BASE, DIFF_BASE_GITLAB_DIFF_BASE_SHA, DIFF_BASE_NOT_APPLICABLE, or a diff-context error code.
base_refThe requested target/base ref when branch or MR mode selected one.
head_refThe requested head ref, usually HEAD or the CI commit SHA.
diff_base_refThe actual first ref passed to git diff; for merge-base, this is the resolved merge-base SHA.
statusPresent as error only on early diff-context artifacts.
diagnosticPresent only on early diff-context artifacts, with the reason-coded ref-resolution diagnostic.

meta.base_sha resolves from meta.diff_base.diff_base_ref when an actual diff base was selected. That keeps base_sha aligned with the reviewed patch rather than the current target-branch tip.

meta.incremental_review records the GitLab MR incremental-review decision when ai-review run has resolved review scope. Use it to distinguish a full MR provider review from a rerun where the provider only reviewed the delta since the previous PatchPatrol-reviewed head SHA.

FieldMeaning
configured_modeEffective AI_REVIEW_INCREMENTAL_MODE: auto, always, or never.
statusincremental when provider scope was narrowed, full when PatchPatrol used full provider scope, or disabled when incremental review was not applicable.
provider_scopeincremental or full, matching the scope sent to the provider.
reason_codesStable reason codes such as INCREMENTAL_PRIOR_HEAD_REACHABLE, INCREMENTAL_PRIOR_HEAD_MISSING, INCREMENTAL_PRIOR_HEAD_UNAVAILABLE, INCREMENTAL_PRIOR_HEAD_NOT_ANCESTOR, or INCREMENTAL_DIFF_EXTRACTION_FAILED.
prior_reviewed_head_shaPrior PatchPatrol-reviewed MR head SHA when available.
current_head_shaCurrent reviewed MR head SHA when available.
full_scopeThe complete MR scope kept for line anchoring and Active Finding lifecycle comparison.
provider_scope_detailsThe actual scope sent to the provider. When incremental, this uses diff_base_strategy=incremental-prior-head-sha.

meta.usage_ledger, when present, is interpretive provider-call metadata used for token usage tables. It has three levels: calls for all provider calls, by_phase for phase totals, and records for individual calls. If the trust gate blocks execution before provider review, no provider call is made; fail-fast artifacts can therefore show meta.usage_ledger.calls.call_count as 0 and zero prompt/completion/total tokens. In that same blocked state, findings: [] means the provider review did not run, not that the merge request was clean.

Provider timing fields in meta.usage_ledger are additive. When the configured provider exposes native timings, records and totals may include these fields:

FieldMeaning
prompt_tokensPrompt/input tokens reported for the provider call.
completion_tokensGenerated/completion tokens reported for the provider call.
total_tokensPrompt plus completion tokens when available.
wall_elapsed_secondsPatchPatrol-measured wall time for the provider call or total.
provider_total_duration_secondsProvider/server total runtime when exposed by the provider.
provider_load_duration_secondsProvider-reported model load time, useful for cold-start diagnosis.
provider_prompt_eval_duration_secondsProvider-reported prompt ingestion/evaluation time.
provider_generation_duration_secondsProvider-reported generation/decode time.
total_tokens_per_second_wallTotal tokens divided by PatchPatrol wall time. Human reports label this Wall total tok/s.
prompt_tokens_per_second_providerPrompt tokens divided by provider prompt-eval time. Human reports label this Prompt tok/s.
generation_tokens_per_second_providerCompletion tokens divided by provider generation time. Human reports label this Generation tok/s; this is the Ollama model decode-speed metric.
total_tokens_per_second_providerTotal tokens divided by provider total runtime. Human reports label this Provider total tok/s.
provider_wall_overhead_secondsPatchPatrol wall time minus provider total runtime. Use this to spot Docker, network, wrapper, or orchestration overhead.

For Ollama, provider-native durations come from nanosecond fields in the /api/chat response and are converted to seconds:

prompt_tok_s = prompt_eval_count / (prompt_eval_duration / 1e9)
generation_tok_s = eval_count / (eval_duration / 1e9)
provider_total_tok_s = total_tokens / (total_duration / 1e9)
wall_total_tok_s = total_tokens / PatchPatrol_wall_elapsed_seconds

Blended wall/provider total rates are not generation speed. A large prompt and short completion can make Wall total tok/s or Provider total tok/s much higher than Generation tok/s. Providers that expose only token counts leave provider-native prompt/generation rates as unavailable, rendered as n/a in human reports, while wall throughput may still be available.

meta.performance_diagnostics, when enabled with AI_REVIEW_ENABLE_PERFORMANCE_DIAGNOSTICS=true, mirrors the same usage values under observed.token_usage and duration values under observed.elapsed_seconds. The markdown and optional HTML reports render the same concepts in ## Token Usage and ## Performance Diagnostics.

Treat missing optional sections as normal and preserve unknown keys when forwarding or storing reports.

Minimal valid payload example

{
  "meta": {
    "model": "deepseek-coder-v2:16b",
    "base_sha": "1111111",
    "head_sha": "2222222",
    "generated_at": "2026-02-26T12:00:00Z",
    "diff_stats": {
      "files": 0,
      "insertions": 0,
      "deletions": 0
    },
    "limits": {
      "max_diff_bytes": 32768,
      "max_files": 50
    }
  },
  "summary": {
    "overall_risk": "low",
    "top_issues": []
  },
  "findings": []
}

That structure is intentionally minimal, but valid for parser bootstrap checks and contract tests.

Stability posture

  • ai-review.json is the contract source of truth.
  • ai-review.md and ai-review.html are human-facing renderings derived from that validated payload.
  • schema.json is the contract source for those artifacts.
  • Integrators should validate required fields and enums from schema.json and treat extra fields as optional forward-compatible extensions.
  • Any optional output sections should be handled defensively (null/absent checks first), because these sections are surfaced opportunistically.

On this page