Research / Distribution and placement

P34 · full · draft

Version Numbers as Measurements: Derived Semantic Versioning and Compiler-Verified Consumer-Driven Contracts

shipped evidence full Distribution and placement

State of the work. The drift predicate, version derivation, contract check and registry publish gate are shipped with tests; there is no empirical study on real package histories and no formal soundness statement.

This is a draft, not peer reviewed. Repository references link to revl at commit 45bec431f.

Planned to be combined with P35 (Install Is Admission: truc, a Package Manager and Git-Backed Registry Where Search Reuses the Admission Predicate) into a single paper.

Pitch

The version bump a release needs is computed from the interface diff of two compiled compositions, where interfaces carry effects, and a consumer's pinned surface is checked in the provider's CI by the same predicate that the runtime admission gate uses.

Abstract

Semantic versioning is a promise made by the author, and consumer-driven contract testing is a body of test code written by the consumer. We show both can be replaced by one measurement when the language's compiled interfaces carry effects. In revl, a service interface carries parameter and return types and whether each operation is an emission that crosses an audited boundary, together with its capability scope. One drift predicate is used three ways: at runtime admission to decide whether a hot-swapped service may replace a running one (strict when a running provider is retained, consumer-subtype otherwise); by revl version --against to compute the required semver bump (consumer regime); and by revl contract check to decide whether a provider still satisfies a consumer's pinned surface (consumer regime). Gaining an emission or widening a capability scope is a major change even when the type shape is compatible, because every consumer's boundary audit changes meaning; losing one is minor. The registry refuses a publish whose declared version is below the computed bump and refuses to publish when the bump cannot be computed, unless the publisher declares an opaque scheme, which is then marked unverified. The evidence is 21 version, 23 federation and 16 admission-relation test functions, plus 30 registry-release and 13 truc-ship test functions for the publish gate (def test_ counts; parametrised cases not expanded). We have not measured the approach on real package histories; we describe the evaluation that would.

Problem and claim

A hand-picked version number cannot be checked, and a changed effect profile is invisible to the version systems that track only type shape. Elm derives versions from API diffs, but its interfaces carry no effects; Pact-style contract tests need code per consumer and per provider and run against behaviour, not interface semantics.

The claim: (a) one drift predicate, defined for admission, suffices to compute the bump and to check consumer contracts, so that the version and contract verdicts are the predicate's own verdicts (two agreement tests check this on their fixtures; the admission use runs in a different regime, so the claim covers the consumer-regime uses); (b) making emission gain and capability widening major is the right extension for effect-carrying interfaces; (c) turning the computed bump into a registry rule is cheap once the measurement exists.

The paper claims no more than a mechanism, its soundness argument for the consumer regime, and its tests. It does not claim reduced breakage in practice.

Contributions

  1. A bump derivation as a join over per-operation changes, reading the admission predicate rather than re-implementing it (src/revl/version.py:100-108, derive at src/revl/version.py:204; docs/derived-versioning.md rule table).
  2. An effect-aware compatibility relation replacing exact service equality at admission, relative to which running components touch the service (consumer, retained provider, none), with a conservative fallback when a key cannot be resolved (src/revl/admission.py:161, src/revl/admission.py:328, src/revl/admission.py:358; docs/service-compat.md).
  3. Consumer-driven contracts without test code: revl contract export projects a consumer's external requirements, revl contract check runs the same predicate in the provider's CI, exit 1 on break (src/revl/federation.py:73, src/revl/federation.py:227; docs/federation.md).
  4. A registry publish gate: under-bump refused by name, uncheckable bump refused unless the scheme is declared opaque, then marked unverified (src/revl/registry.py:1181-1235; tests/test_registry_releases.py:347).
  5. Agreement tests tying version derivation and contract checking to the drift predicate (tests/test_derived_version.py:276, tests/test_federation.py:338); admission is not covered by either test.

Evidence on main

claimpath:line or teststatusnote
Rule table: added is minor, removed is major, param narrowed major, return widened major, emission gained major, emission lost minordocs/derived-versioning.md table; tests/test_derived_version.py:70-185shipped
Capability scope widened is major, narrowed minortests/test_derived_version.py:200, tests/test_derived_version.py:215shipped
Service commutative flip and arity change are majortests/test_derived_version.py:230, tests/test_derived_version.py:245shipped
Bump is the real predicate's verdict, not a copytests/test_derived_version.py:276; src/revl/version.py:108shipped
Next version is computed from a current versiontests/test_derived_version.py:269 (parametrised)shipped
Audit documents rejected as --against inputtests/test_derived_version.py:365shipped
Consumer regime (providers_retained=False)src/revl/version.py:100; docs/derived-versioning.md "The consumer regime"shipped
Admission relation replaces exact equality; touchers identified; conservative fallbacksrc/revl/admission.py:161, src/revl/admission.py:328, src/revl/admission.py:358; tests/test_service_compat.py (16 tests); docs/service-compat.mdshipped
Registry refuses under-bump by name, leaves registry untouchedtests/test_registry_releases.py:347; src/revl/registry.py:1229shippeddocs/derived-versioning.md ("Relationship to the registry", lines 104-111) describes the phase-2 gate as where the measurement "becomes a rule", not as shipped. The doc is stale relative to the code
Over-bump is not a contradictiontests/test_registry_releases.py:312shipped
Uncheckable bump refused under the default schemetests/test_registry_releases.py:411shippedopaque scheme marks the release "cannot verify"
Same gate reached from truc shiptests/test_truc_ship.py:351shipped
Consumer surface pins only external requirementstests/test_federation.py:84shipped
Contract break and pass cases, CLI exit behaviourtests/test_federation.py:118-200, tests/test_federation.py:410-479shipped23 tests in file
Contract verdict agrees with drift predicatetests/test_federation.py:338shipped
Adapter probe for a break (satisfied-via-adapter)src/revl/federation.py:122; tests/test_federation.py:230-326shipped, extracould be a section or a separate paper
The provider's CI enumerates registered consumers automaticallydocs/federation.md "Where it sits" says the surface "is the artifact a registry would hold"designedno registry storage of consumer surfaces found in src/revl/registry.py; the CI loop is left to the user
"Split-brain safe"not found for this mechanismnot supportedsplit-brain handling is in the deploy work (docs/design/118-revl-deploy.md, federation section), not in contract check; the claim is dropped

Numbers that exist

Paper outline

  1. Introduction: versions as promises; effects as the missing dimension.
  2. Interfaces that carry effects: emission, capability scope, async, commutative.
  3. One predicate, three uses: admission (strict or consumer regime, depending on whether a provider is retained), version derivation and contract check (consumer regime); why the consumer regime is independent of current wiring.
  4. Bump rules and why emission gain is major.
  5. Consumer-driven contracts without tests: surface projection, check, adapter probe.
  6. Registry enforcement and the opaque-scheme escape.
  7. Evaluation: agreement tests, then the empirical study (to be done).
  8. Limits and related work.

Threats to validity and limits

Fact-check

Claims in this draft were checked against revl main at commit 45bec431f: 18 checked, 4 corrected.

Cite this draft

@misc{revlp34,
  author       = {Thomas Moussajee},
  title        = {Version Numbers as Measurements: Derived Semantic Versioning and Compiler-Verified Consumer-Driven Contracts},
  year         = {2026},
  howpublished = {\url{https://inso1337.github.io/revl/research/P34.html}},
  note         = {Research draft, not peer reviewed. Written against revl commit 45bec431f. Licensed CC BY 4.0.}
}

Text licensed CC BY 4.0, author Thomas Moussajee.

← All research drafts