Package-level declarations

Types

Link copied to clipboard
data class AcceptedBreak(val type: String, val rule: String, val direction: CompatibilityDirection? = null, val reason: String = "", val acceptedBy: String = "")

A break the team has explicitly sanctioned, mirroring one stanza of the committed serialkompat-exceptions.yaml (design §7). A Finding matching an accepted break is downgraded to acknowledged: logged, but not failing the gate. The diff to this list in a PR is exactly the breakage it sanctions.

Link copied to clipboard
sealed interface 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.

Link copied to clipboard
class Classifier(profile: CompatibilityProfile = CompatibilityProfile())

Turns structural Changes into severity-ranked Findings by applying the rule matrix (design §7) under a CompatibilityProfile and the reader/writer SnapshotConfigs.

Link copied to clipboard

Direction(s) of compatibility a check enforces.

Link copied to clipboard

The end-to-end compatibility engine (design §3): the single entry point that ties the pure pipeline together — restrict to Scope, diff, classify under a CompatibilityProfile, and fold declared renames and accepted breaks into a Report. Every front end (Gradle task, CLI) feeds it two snapshots plus policy and shares this one implementation, regardless of where the snapshots came from.

Link copied to clipboard
data class CompatibilityProfile(val direction: CompatibilityDirection = CompatibilityDirection.FULL, val readerTolerance: ReaderTolerance = ReaderTolerance.FROM_CONFIG)

The policy a scope is checked under (design §7): which direction of compatibility to enforce, and how tolerant the reader is assumed to be. This is policy that cannot be inferred from code, so it stays declared.

Link copied to clipboard

Renders a Report as human-readable console text. Pure: it returns a string and performs no I/O (the Gradle layer prints it).

Link copied to clipboard
class Contract(val serialName: String, val kind: ContractKind, elements: List<Element> = emptyList(), enumValues: List<String> = emptyList(), val discriminator: String? = null, subtypes: List<Subtype> = emptyList(), val hasPolymorphicDefault: Boolean = false, val base: String? = null)

The wire contract of a single @Serializable type, identified by its serialName and, for a sealed/polymorphic subtype, the base it was reached through (#200). Collections are normalized to sorted order so that equality and the canonical text form are independent of declaration order.

Link copied to clipboard

The structural kind of a Contract, mirroring the subset of kotlinx-serialization's SerialKind taxonomy that matters for wire compatibility.

Link copied to clipboard
data class Coverage(val inScope: Snapshot, val excluded: List<String>)

The result of applying a Scope: the inScope snapshot that will be checked, and the qualified names (Contract.qualifiedName) excluded from checking (surfaced, never silently lost).

Link copied to clipboard
class Element(val name: String, val type: String, val optional: Boolean = false, val nullable: Boolean = false, jsonNames: List<String> = emptyList(), val encodeDefault: EncodeDefaultMode? = null)

A single element (field) of a ContractKind.CLASS contract, recording the compatibility-bearing facts about how it appears on the JSON wire.

Link copied to clipboard

How a defaulted field is written, per its @EncodeDefault annotation. ALWAYS and NEVER mirror kotlinx.serialization.EncodeDefault.Mode; ABSENT records that the field was inspected and carries no @EncodeDefault, so the encoder's global encodeDefaults applies.

Link copied to clipboard
data class Finding(val rule: String, val direction: CompatibilityDirection, val severity: Severity, val contract: String, val detail: String, val message: String, val fixHint: String?, val change: Change)

A classified compatibility judgment about a single Change in a single direction: the rule it triggered, its severity, and human-facing text.

Link copied to clipboard

Renders a Report as GitHub Actions workflow-command annotations (::error / ::warning) for the active findings (design §9). Pure — no I/O.

Link copied to clipboard

Renders a Report as machine-readable JSON for tooling and PR comments (design §7, §9). Pure and dependency-free: the JSON is emitted by hand so the core module stays free of the kotlinx-serialization runtime.

Link copied to clipboard

How much unknown-key tolerance to assume for the reader when classifying (design §7). Reading the real Json config describes the sides you own; a non-Kotlin peer's tolerance is unknown, so externally-facing scopes can pin STRICT to override "what my own Json does".

Link copied to clipboard
data class Report(val findings: List<Finding>, val accepted: List<AcceptedBreak> = emptyList())

The outcome of a compatibility check: the classified findings plus the accepted breaks that sanction some of them. Splits findings into active (which count against the gate) and acknowledged (sanctioned), and decides whether the gate should fail for a given severity floor.

Link copied to clipboard
object Rules

Named compatibility rules. Each maps a kind of Change to a greppable, individually-suppressible identifier used in findings and the exceptions file (design §7).

Link copied to clipboard

Renders a Report as a SARIF 2.1.0 log for IDEs and third-party SARIF dashboards (design §9). Pure and dependency-free (hand-rolled JSON via JsonStrings), so core stays free of the kotlinx-serialization runtime.

Link copied to clipboard
data class Scope(val include: List<String> = listOf(""), val exclude: List<String> = emptyList())

Restricts which contracts are checked, by serial-name prefix (design §7, §9). A type is in scope when it matches any include prefix and no exclude prefix (exclude wins). A sealed/polymorphic subtype (#200) matches an entry that prefixes its bare serial name, its base, or its qualified Base/sub name. The default scope — empty-string include, no excludes — includes everything.

Link copied to clipboard

Severity of a detected schema change, ordered from least to most severe.

Link copied to clipboard
class Snapshot(contracts: List<Contract> = emptyList(), val config: SnapshotConfig = SnapshotConfig())

The canonical, comparable representation of a JSON wire contract: the set of serializable contracts plus the relevant config.

Link copied to clipboard
data class SnapshotConfig(val namingStrategy: String = "none", val classDiscriminator: String = "type", val classDiscriminatorMode: String = "POLYMORPHIC", val ignoreUnknownKeys: Boolean = false, val encodeDefaults: Boolean = false, val explicitNulls: Boolean = true, val coerceInputValues: Boolean = false, val useAlternativeNames: Boolean = true, val useArrayPolymorphism: Boolean = false, val allowStructuredMapKeys: Boolean = false, val allowSpecialFloatingPointValues: Boolean = false, val isLenient: Boolean = false, val decodeEnumsCaseInsensitive: Boolean = false, val allowTrailingComma: Boolean = false, val allowComments: Boolean = false)

The subset of a kotlinx.serialization.json.Json configuration that affects the wire shape or decode behavior, captured as part of a Snapshot so that config changes are diffed and classified like any other change (design §6).

Link copied to clipboard

Computes the structural Changes between two Snapshots. This is the pure heart of the engine (design §3): it reads two snapshots, never knowing where they came from (git ref, file, live), and emits direction-neutral deltas for the classifier to judge.

Link copied to clipboard

The canonical text codec for a Snapshot — the deterministic, human-readable, diffable artifact (BCV's lesson: a sorted golden text reviewers can read).

Link copied to clipboard
data class Subtype(val discriminatorValue: String, val serialName: String)

One entry in a ContractKind.SEALED or ContractKind.POLYMORPHIC contract's subtype map: the discriminator value written to the wire, and the serial name of the concrete subtype it selects.

Link copied to clipboard

Transitive compatibility over an append-only published history (design §5).

Functions

Link copied to clipboard

Partitions this snapshot's contracts by scope into checked vs excluded.

Link copied to clipboard

The first entry in accepted that sanctions this finding, or null if none does.

Link copied to clipboard

Whether this finding is sanctioned by any entry in accepted.