# CommitBrief 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

Canonical URL: https://commitbrief.com/changelog/v1.19.0/

---

## 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](/docs/1.x/rules/).
- **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](/docs/1.x/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](/docs/1.x/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.