Change
A single structural, direction-neutral delta between two Snapshots, as produced by SnapshotDiffer. A Change states what differs, never whether it is safe or breaking — that judgment (rule name + Severity + direction) is the classifier's job (design §7). Keeping changes neutral lets one differ feed backward, forward, and config-aware classification without re-diffing.
Inheritors
Types
A Json configuration field that affects the wire contract changed.
A @Serializable type present in the new snapshot but not the old.
A type whose serial name changed via a declared rename/move (design §8): wire-neutral for a plain type, a discriminator break for a polymorphic one.
A @Serializable type present in the old snapshot but not the new.
A current contract that could not be paired with a baseline one (#200): no baseline contract has the same (serialName, base) identity, and its bare serial name is shared by several contracts on at least one side (e.g. a pre-base-identity baseline recorded one bare created while the current snapshot has OrderEvent/created and UserEvent/created). Pairing by guess could diff the wrong bodies, and calling it added/removed would be false, so — like a CoverageGap — it is surfaced as unverified. contract is the qualified display name.
An unanalysable (OPAQUE) contract in the current snapshot: the extractor could not derive its wire shape (e.g. a custom serializer), so the gate cannot verify it. Surfaced on every diff so an unanalysable type is never silently treated as compatible ("unanalysable ≠ safe", design §10).
The polymorphic discriminator key of an existing contract changed.
A sealed/polymorphic contract whose class discriminator key collides with a property of its subtype of the same name. Such a model is unserializable — kotlinx-serialization refuses to encode it — so, like a CoverageGap, it is a defect of a single snapshot surfaced on every diff (not a delta between two), letting the gate catch it statically before the first encode throws (#132).
A new element (field) on an existing contract.
An existing element's @JsonNames alias set changed. Aliases are a wire fact (they widen what keys a reader accepts) and are §7's mitigation for a key rename, so adding/removing one must not be silently dropped.
An existing element became optional or required.
An element removed from an existing contract.
An enum value added to an existing enum contract.
An enum value removed from an existing enum contract.
A subtype added to an existing sealed/polymorphic contract.
A subtype removed from an existing sealed/polymorphic contract.