// changelog

v1.19.0

Every finding now carries a stable rule id and fingerprint, baselines and policies can target rules, reviews can be exported as SARIF for GitHub Code Scanning, and any OpenAI-compatible endpoint works as a provider through config alone.

Released October 18, 2026

Added

  • Finding identity: rule_id and fingerprint on every structured finding in --json output (schema stays 1; both fields are additive and omitted when unset). rule_id comes from a closed taxonomy of 30 ids (sec.injection, correctness.error-handling, test.flaky, …, general.other); an empty or unknown value from the model is normalised to general.other. fingerprint is a local hash of the file, the rule id and the symbol, so it survives rewording and unrelated edits above the finding. See Rule taxonomy.
  • Baseline v2. .commitbrief/baseline.json now stores finding fingerprints, so a reworded title no longer unhides a baselined finding. --update-baseline always writes v2; an existing v1 file keeps matching the old way and prints a one-time warning.
  • Policy rules. .commitbrief/policy.yml accepts rules.deny (a single finding of that rule blocks) and rules.allow (findings of that rule are waived from thresholds and total). Entries are taxonomy ids or <category>.*. The guard verdict gains an additive waived count. Policies without rules behave as before.
  • Inline [rule_id] markers. commitbrief-ignore[sec.injection]: reason silences only that rule’s findings; [high] works as before. An unknown token is treated as an unscoped marker and warned about.
  • --sarif on the root review and on commitbrief diff writes findings as a SARIF 2.1.0 log for GitHub Code Scanning (commitbrief diff <range> --sarif -o commitbrief.sarif). Each result carries the rule id, level, location and a partial fingerprint. --sarif cannot be combined with --json, --markdown, --suggest-commit, --cli or --show-prompt, and is refused with a CLI-backed provider. It fails closed: a response that never parsed into structured findings produces an error and no file. A diff that is empty after filtering is not a failure: it writes a valid log with results: []. See SARIF.
  • openai-compatible provider points CommitBrief at any OpenAI-compatible chat-completions endpoint (vLLM, LM Studio, OpenRouter, …) through config alone. providers.openai-compatible.base_url and model are required; the key is optional, for auth-less local servers. Without a declared price the cost shows as unknown. A plain http:// base_url to a non-loopback host prints a one-line warning on stderr (the request is still sent), and doctor reports an api_key_env that points at an empty variable as a failure. See Providers.
  • providers.<name>.api_key_env on every API provider reads the credential from the named environment variable and takes precedence over the provider’s fixed variable and api_key. Set but empty is an error.
  • providers.<name>.context_window on every API provider overrides the built-in context window used by the token preflight and dry-run.

Changed

  • Migrating a v1 baseline to v2 is lossy; re-run --update-baseline to adopt v2.
  • The review prompt now includes the rule taxonomy. The cache key includes the system prompt, so existing cache entries miss once after upgrading.
  • Any commitbrief-ignore[token]: line is now a marker, including tokens that were not recognised before (for example [todo-1]); such lines now suppress findings on that line, as an unscoped marker, and print a warning.
  • dry-run prints a Provider unavailable: <reason> line on stderr when the configured provider cannot be built, instead of silently estimating without it. The estimate is still printed.
  • --verbose now also prints debug logs on stderr.

Fixed

  • Inline suppression leaked across files. A commitbrief-ignore marker at line N of one file also suppressed a finding at line N of another file in the same diff. Markers are now keyed by file and line, so findings that were wrongly suppressed before reappear after upgrading.
  • deepseek, mistral, cohere no longer send OpenAI-Organization and OpenAI-Project headers derived from OPENAI_ORG_ID / OPENAI_PROJECT_ID to those third-party endpoints. The API key was never affected.