// 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.

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. New in v1.10.0 (ADR-0029).

The policy file

The gate is opt-in: with no .commitbrief/policy.yml there is no gate. 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.

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, "medium": 1 },
  "total": 3,
  "violations": ["high: 2 > 0"]
}

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

Flag Notes
--policy <path> Policy file location. Default .commitbrief/policy.yml, resolved relative to the repo root.
--from-json <file|-> Consume-mode: evaluate a prior schema-v1 review (no provider call). - reads stdin.
--unstaged Run-mode: review the working tree instead of the staged diff.
--diff <range> Run-mode: review an arbitrary git diff range.
--json Emit the machine-readable verdict.

--provider / --model / --no-flaky carry over from the persistent flags in run-mode.

See also

  • Severity and CI gating--fail-on, the simpler one-threshold gate guard complements.
  • Signal control — baseline + suppression, the filters applied before guard evaluates.
  • MCP server — produce a review an agent can feed to guard --from-json.
  • Output formats — the JSON schema v1 that consume-mode reads.