The Disposition Audit¶
Every abicheck compare run reports two totals, not one:
- detected — every change the detectors observed, before any policy ran;
- effective — the changes that actually contribute to this run's gate.
Between them sits a per-change disposition: the single reason each detected change is, or is not, in the effective set. The disposition audit is the block that reconciles the two, so a run that reports "no changes" can still tell you that 100 removals were detected and every one of them was withheld by a rule you wrote.
Why the two totals are separate¶
A compatibility check has one selector grammar for suppression but several places where a finding can stop counting: an explicit suppression rule, deduplication of two views of the same change, a contract that excludes the finding's surface, evidence that ran out before relevance could be decided, or a severity setting that scores the finding as a warning. Reporting only the survivors makes all of those look identical to "nothing happened".
The rule the audit makes checkable is that policy never changes what was observed — it only moves a finding between dispositions. Adding a suppression rule to a run must leave the detected total exactly where it was.
The six dispositions¶
Each detected change ends in exactly one of these, and the counts sum to the detected total:
| Disposition | What it means |
|---|---|
gating |
Contributes to this run's exit code. |
non_gating |
Evaluated, and scored as not gating — a compatible addition, or a category your severity settings rate below error. |
suppressed |
A --suppress rule matched it. The audit names the rule. |
out_of_contract |
Proven outside the contract the run was told to judge against (--contract). |
unresolved_relevance |
Relevance could not be decided, because the evidence for deciding it was absent. Not the same as "irrelevant". |
deduplicated |
A second view of a change already counted once — a grouped child, a collapsed versioned symbol, a redundant finding. |
out_of_contract and unresolved_relevance are deliberately distinct: the
first is a positive determination, the second is evidence running out. See
Contract Evaluation.
Where it appears¶
The one-line summary carries the counts inline:
$ abicheck compare old.so new.so --suppress suppressions.yaml -o oneline=-
NO_CHANGE: no changes (0 total) [audit: 100 detected, 0 gating, 100 suppressed]
The JSON report (-o json=...) carries a disposition_audit block with
the same counts plus the rules that produced
them; the review digest renders it as a table; the sticky PR comment carries a
counts row and rule attribution; SARIF, JUnit and HTML each carry the counts in
their own format's idiom. A view may collapse detail — the not-evaluated
detector list, the rule tail — but none of them drops the counts. See
Output Formats.
Detectors that did not run¶
A detector whose supporting evidence was absent is reported as
not_evaluated, not as a detector that ran and found nothing. "No DWARF on
either side, so no layout comparison happened" and "layouts were compared and
are identical" are different statements about a run, and the audit keeps them
apart. not_evaluated is a reporting distinction only: it never changes a
verdict, an exit code, or the run's reported confidence.
What it means for suppression¶
A suppression records that a finding was withheld; it is not evidence the finding was wrong. Two consequences follow, both visible in the audit:
- the withheld finding stays in the detected total and names the rule that hid
it, including the suppression document's path,
reason,labelandexpires; - the release recommendation reads the same conserved ledger, so a suppressed
ABI/API break is reported as a
major-class finding needing review rather than "no version bump required".
Full rule syntax and the audit trail a rule leaves behind: Suppressions.
What it means for acknowledgment¶
An acknowledgment records that a finding was seen and intentionally
accepted — the opposite intent from suppression. An acknowledged finding
keeps its own disposition from the six above (it is not a seventh state);
the audit additionally names which acknowledgment record covered it
(acknowledged_by), and a policy acknowledgment: block can separately
flag a public addition that carries no such record. Full record format and
the additions review gate: Change acknowledgment.