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.
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
| Flag | Notes |
|---|---|
--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. |
--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, 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 withreview.sandbox_commandconfigured, 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
- Gate CI on review findings — a guided
walkthrough of
--fail-onandguardin CI. - 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.