// docs · v1.x

Policy gate — guard

A declarative merge gate that caps how many findings of each severity a change may carry, via an opt-in .commitbrief/policy.yml. Richer than a single --fail-on threshold; aimed at gating high-volume, often AI-authored, pull requests.

Updated August 22, 2026

commitbrief guard is a declarative merge gate. Instead of one severity cutoff, it evaluates a review’s actionable findings against a .commitbrief/policy.yml and exits non-zero when the policy is breached. Think of it as a per-severity budget rather than the single --fail-on=<severity> threshold — useful when you’re gating high-volume, often AI-authored, pull requests.

The policy file

The gate is opt-in in the sense that nothing runs it until you call commitbrief guard. Once you do, a .commitbrief/policy.yml must exist: with no policy file guard fails with exit code 1 instead of passing. Create one to declare the budget:

# .commitbrief/policy.yml
version: 1
thresholds:        # max findings allowed per severity (omit or ~ = unlimited)
  critical: 0
  high: 0
  medium: 5
  low: ~
total: 20          # optional overall cap across all severities

A severity you omit (or set to ~) is unlimited. total is an optional cap on the combined count.

Two ways to run it

Run-mode — review, then evaluate

Run-mode reviews the diff (reusing the standard pipeline) and judges the result against the policy:

commitbrief guard                     # staged diff
commitbrief guard --unstaged
commitbrief guard --diff main...HEAD

Consume-mode — evaluate an existing review

--from-json evaluates a review you already produced, with no provider call — so an agent’s MCP self-review or a prior commitbrief --json run can be gated cheaply:

commitbrief --json --staged > review.json
commitbrief guard --from-json review.json

--from-json - reads the review from stdin — which is also how a credential audit gets gated, since leaks --json emits the same schema-v1 document:

commitbrief leaks --json --fail-on none | commitbrief guard --from-json -

There was no model call in that pipeline (meta.provider is "builtin", cost_usd is 0), and guard neither knows nor cares.

What it evaluates

guard judges the findings that survive baseline + suppression (signal control) — exactly the set --json shows. Baselined and inline-suppressed findings are already gone before the policy sees them.

Exit codes

The exit code is 0 (pass) or non-zero (blocked). Critically, a load or parse failure also blocks: a missing or malformed policy, or an unparseable review, fails the gate rather than passing it — a merge gate must not pass when it cannot prove the change is within policy.

--json emits a machine-readable verdict:

{
  "passed": false,
  "counts": { "critical": 0, "high": 2, "info": 0, "low": 0, "medium": 1 },
  "total": 3,
  "violations": [
    { "severity": "high", "allowed": 0, "actual": 2 }
  ]
}

counts always carries all five severities. Each entry in violations names the breached severity (or total for the overall cap), the allowed maximum, and the observed count; severity violations come in critical to info order, with total last.

guard vs. --fail-on

--fail-on=<severity> is the simple one-threshold gate — “fail if any finding meets or exceeds this severity.” guard is the per-severity budget — “allow up to N of each.” They complement each other; use either or both. A repo might run --fail-on=critical on a developer’s pre-commit hook and the richer guard policy on the CI merge gate.

Rule-id-scoped allow/deny lists are not yet supported — findings carry no stable rule id. The policy is severity- and total-count-based for now.

Flags

FlagNotes
--policy <path>Policy file location. Default .commitbrief/policy.yml, resolved relative to the repo root. An explicit --policy path is used as given, relative to the current working directory.
--from-json <file|->Consume-mode: evaluate a prior schema-v1 review (no provider call). - reads stdin.
--unstagedRun-mode: review the working tree instead of the staged diff.
--diff <range>Run-mode: review an arbitrary git diff range.
--jsonEmit the machine-readable verdict.

--provider / --model / --no-flaky carry over from the persistent flags in run-mode, as do the path filters (--file, --dir, --exclude-file, --exclude-dir) and the commit filters (--author, --committer, --start-date, --end-date, --text, --max-commits, --merges).

Sandbox-rerun never runs under guard. Even with review.sandbox_command configured, the gate will not execute your repository’s tests — unconditionally, with no toggle. Its flaky findings stay at the static-only confidence level. See Flaky-test detector.

See also