# `Excessibility.DigestCompare`
[🔗](https://github.com/lessthanseventy/excessibility/blob/v0.20.0/lib/excessibility/digest_compare.ex#L1)

Pure, deterministic structural diff of two `excessibility.digest/v1` maps.

Given a `base` and `head` digest (as produced by `Excessibility.Digest`,
whether reloaded via `Jason.decode!(..., keys: :atoms)`, decoded with string
keys, or a raw Elixir map), `diff/2` returns a stable, sorted structural
delta. It emits **no verdict, no severity beyond advisory, and no merge
decision** — only the observed structural differences plus measurement-scope
notes.

## The measurement-scope guard

A signal delta is asserted **only when both digests measured that signal**:

- Queries/plans are diffed only when both `capture.ecto_configured` are true.
  Otherwise the queries/plans lists stay empty and a `coverage.notes` entry
  explains that one side did not measure queries.
- Plans are diffed only when both `capture.plan_capture` modes match. A
  difference is scope-noted, never reported as a plan change.
- The plan-variant set per SQL fingerprint is bounded by the digest, so a side
  can drop structures it never emitted. When either side omitted variants the
  incompleteness is made explicit — a forced `plans` entry carrying per-side
  `base_variants_omitted` / `head_variants_omitted` counts, plus a
  `coverage.notes` entry — so a bounded comparison never renders "no change"
  for a structure it could not see (issue #183).
- Assign deltas are diffed only when the `assign_sizes` enricher ran on both
  sides; other enricher differences are scope-noted.
- A `schema` mismatch adds a prominent note.

This keeps compare honest: a change in *what was measured* can never
masquerade as a real regression.

## Key tolerance

Every field read goes through `get/3`, which tries the atom key then the
string key, so atom-keyed and string-keyed digests behave identically.

## Determinism

All output lists are sorted by a stable key (`fingerprint`,
`{view, callback}`, or `name`) and all set math is order-independent, so the
diff of a given pair is byte-for-byte reproducible regardless of input event
order.

# `diff`

Diff two decoded digest maps. Returns the structural delta described in the
module docs. Never raises for well-formed digest maps; missing fields fall
back to empty defaults.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
