Versioning & Release Policy
voiage uses semantic versioning and tag-driven releases. The Cargo workspace
version is authoritative, Maturin exposes it as dynamic Python package
metadata, and release tags are validated fail-closed against it. Polyglot
manifests remain explicit and synchronized to the same version.
Stable compatibility contract
Section titled “Stable compatibility contract”The normative policy is published in specs/v1/compatibility-policy.json.
Breaking changes to stable Rust, Python, C ABI, binding, CLI, schema, or
serialized-output contracts require a major release. Minor releases may add
backward-compatible capabilities, while patch releases may only make
backward-compatible fixes.
Provisional and experimental surfaces are excluded from these guarantees until promotion. Promotion requires a normative contract, executable compatibility fixtures, and a migration assessment.
Deprecation window
Section titled “Deprecation window”A stable feature remains available for at least two minor releases and six
months, whichever is longer. At v1, Python emits FutureWarning; all surfaces
provide a stable diagnostic code, replacement path, and migration documentation.
Removal is permitted only in the next major release and requires updated
compatibility fixtures and release notes.
The 0.x raw-dictionary EVPPI compatibility alias emits FutureWarning with
the stable deprecated_raw_dict_parameter_samples diagnostic code and points
callers to ParameterSet. Its warning class, code, replacement, and migration
documentation are executable v1 compatibility contracts.
Canonical version source
Section titled “Canonical version source”The Python package declares a dynamic version in pyproject.toml. Maturin
reads the authoritative Cargo workspace version when building package
metadata. The version-sync validator compares external binding manifests to
that version, and release validation rejects a v* tag that does not match it
exactly.
Binding manifests are expected to match the canonical version exactly:
bindings/julia/Project.tomlrust/Cargo.tomlr-package/voiageR/DESCRIPTION
Release tags and package registries
Section titled “Release tags and package registries”The repository keeps ecosystem-specific tag and registry conventions:
- Python publishes from
v*tags - Julia publishes from
julia-v*tags - Four binding-independent Rust core crates publish to crates.io from signed
rust-v*tags through Trusted Publishing; FFI, PyO3, and test-support crates remain private - R publishes from
r-v*tags
The version numbers in package manifests must align with the latest released Python tag. Tag prefixes and registry targets remain ecosystem-specific; only the version value is shared.
For a Python release candidate, Cargo and Julia retain the canonical SemVer
identity (for example, 2.0.1-rc.1) while Python uses its normalized PEP 440
distribution identity (2.0.1rc1). R cannot represent an alphanumeric
prerelease in DESCRIPTION, so it uses a numeric development version below the
target stable release and records the canonical identity in
Config/voiage/Release-Version. Such a candidate is Python/TestPyPI-only: it
does not create r-v*, julia-v*, or rust-v* publication tags.
Validation
Section titled “Validation”The repo-local validator checks the canonical version against binding manifests:
tox -e version-syncOr equivalently:
uv run python scripts/validate_version_sync.pyRelease flow
Section titled “Release flow”- Update the Cargo workspace version and synchronized binding manifests
- Run the version-sync validator and fail-closed release-tag validation
- Cut the matching
v<version>tag - Let the tag workflow build and attest a private draft
- Review exact artifact digests, then dispatch TestPyPI publication
- Permit PyPI and the public GitHub Release only after the TestPyPI smoke gate