Versioning and stability¶
Nothing is published
No version of atune exists on crates.io or PyPI. Every manifest in the
repository reads 0.1.0, and that number describes the tree, not a release.
This page therefore states what a version number will mean and what is
true today, and marks which is which.
What a version number means¶
Every crate in the workspace carries the same version, and the internal
dependencies are pinned to it exactly (atune_core = { path = …, version = "0.1.0" }). A release is therefore all of them at one number, not four
independently versioned crates. The Python wheel is built from the same tree and
carries the same version.
The numbers follow cargo's reading of semantic versioning, which before 1.0 is stricter than people expect:
| Change | Before 1.0 | After 1.0 |
|---|---|---|
| Breaking API change | a minor bump — 0.1 → 0.2 |
a major bump |
| New capability, nothing removed | a patch bump — 0.1.0 → 0.1.1 |
a minor bump |
| Bug fix | a patch bump | a patch bump |
So while atune is 0.x, treat every minor bump as breaking. A dependency
written as atune = "0.1" will not silently pick up 0.2.
What is stable today¶
Nothing. No API is frozen, and the pre-1.0 period exists precisely so that the seams can still move. What is already guaranteed is narrower and more useful than a stability promise:
- The four plugin seams are frozen in shape, not in signature: a
atune::Storage,atune::Sampler,atune::Scheduleroratune::Objectiveimplemented against today's traits is the shape they will keep, and the storage conformance suite is what an out-of-tree backend is held to. See Extending. - The on-disk journal has a version field and a compatibility rule. This build writes format version 5; a reader refuses a journal whose header names a higher version rather than guessing at it, and still opens a lower one. The format is documented field by field on the journal reference and pinned by a committed golden file.
- Optuna's journal format is a stable import and export target, because Optuna itself guarantees it. See Optuna interop.
- Determinism is asserted, within a version. See the section below, which is the one stability question that bites people who record results.
Determinism is a within-version promise¶
Given the same version, seed, closed search space, and stateless sampler, a study reproduces exactly across thread counts and across the Rust and Python surfaces. History-dependent samplers, schedulers, and open search spaces have the narrower replayability contract described in Determinism; a fixed-seed single-worker run remains fully reproducible.
Across versions it is deliberately not a promise. Improving a sampler changes which configuration it suggests, so the byte-for-byte outputs change with it; the repository's parity and journal goldens are re-blessed on purpose when that happens, and the diff is the record of the change. If a result has to be reproducible later, pin the exact version that produced it — a caret requirement is not enough.
An open search space stores its growth policy in the study. A build that predates open search spaces does not read that policy: it samples the declared seed range while earlier trials recorded wider distributions. The compatibility check accepts that bound drift, so such a study degrades — growth stops — rather than corrupting.
The surfaces, and what each one commits to¶
| Surface | What it is | Pre-1.0 expectation |
|---|---|---|
atune (Rust facade) |
The crate to depend on | The main API surface; anything may change with a minor bump |
atune_core |
The model layer and the four seams | Depend on it directly only when implementing a seam |
atune_derive |
#[derive(Space)] |
Generated code names the facade, so the two travel together |
atune_cli (binary atune) |
The command-line tool | Flags and subcommands may change; the CLI reference is generated from the code, so it cannot describe a flag that no longer exists |
atune on PyPI |
The Python package | Mirrors the facade's shape rather than its exact API |
| Cargo features | Part of the public API | Adding one is additive; removing or renaming one is breaking. The feature reference is generated from the manifests |
| The journal file | The on-disk study | Versioned, with the compatibility rule above |
Two details of the Python surface that are deliberate and will not surprise you twice:
- Sampler
seed=arguments raise. They exist in the signature for familiarity with Optuna's spelling, and passing one is answered with a message pointing atcreate_study(seed=…), because determinism belongs to the study seed. Keeping the keyword and rejecting its value is the loud version of a divergence; accepting and ignoring it, which is what these arguments used to do, was a silent one. - The wheels are
abi3-py310for GIL-enabled CPython, so one wheel per platform serves every GIL-enabled CPython from 3.10 upward. Free-threaded builds, includingcp314t, are not shipped. Raising that floor is a breaking change for whoever is below it.
Rust version¶
The workspace sets rust-version = 1.92 and edition 2024. An older toolchain
refuses the build outright rather than failing halfway through it. An MSRV
increase is recorded in the changelog as a breaking change,
because for a consumer pinned to an older toolchain it is one.
The publish order, and why it is not one command¶
The four published crates must go to crates.io bottom-up:
atune_core → atune_derive → atune → atune_cli
This is not a preference. The internal dependencies are path + version
entries, and a normal publish package resolves the version half against the
registry. Before the first release, an unpatched cargo package -p atune fails
with:
no matching package named atune_core found … location searched: crates.io index
The push gate uses cargo package --locked --list for a fast include/exclude
check. The dispatch-only release-staging rehearsal packages all four crates
bottom-up with temporary same-workspace patches, verifies each archive, and
compiles disposable external consumers from those archives. It also copies the
real atune_plugin_example unchanged into an isolated workspace, proves that its
only atune dependency is the extracted atune_core package with no features, and
runs the plugin's build and tests. The patches are runner-local and do not alter
publication order or registry state; none of this is registry-publication proof.
atune_bench, atune_oniro, atune_gui, atune_dev and
atune_plugin_example are publish = false and are never released. They are
internal tooling, a demo and a compile-checked example; their Rust API reference
is published on this site rather than on docs.rs, because they will never
appear there.
Staging, authorization, and rollback¶
The repository's release automation stops at a manual, read-only staging rehearsal. A staging run must build the supported crate, wheel, sdist, and documentation artifacts from one commit; consume each build in an isolated environment; run the current dependency-policy gate; and retain a sorted manifest, SHA-256 sums, a standard SBOM, and available hosted provenance. A successful workflow run is review evidence, not permission to publish.
Publication requires a maintainer to review that evidence, select and protect the release identity or signing mechanism, and authorize the exact version and destinations. Registry credentials, signing keys, GitHub Pages mutation, crate yanks, and PyPI uploads are intentionally absent from the staging workflow. Nothing should be published from a dirty worktree or from artifacts rebuilt after the reviewed staging run.
If a problem is found before publication completes, stop and leave every remaining destination untouched. If an already published artifact is unsafe, the maintainer follows the registry's supported withdrawal mechanism (for example, a crates.io yank), publishes a corrected version rather than replacing immutable bytes, and moves documentation aliases only after the corrected artifacts pass staging. PyPI and crates.io receipts, provenance, signatures, and the incident decision are retained with the release evidence. The local rollback rehearsal exercises only disposable indexes and aliases; it never writes a public registry or production documentation target.
Documentation versions¶
The site is versioned from the start: /latest/ moves with each release, each
release also keeps an immutable /0.1.0/-style snapshot, and /dev/ follows the
main branch. Retrofitting that later would rewrite every published URL, so the
mechanism is in place before there is anything to publish with it. So far only
a development snapshot is published, as /dev/ with /latest/ pointing at it;
no release has been deployed.
Where to go next¶
| If you want to | Go to |
|---|---|
| What changed, release by release | Changelog |
| To contribute, and the gates a change must pass | Contributing |
| What determinism actually guarantees | Determinism |
| Which feature carries which algorithm | Feature reference |
| To report a vulnerability | Security policy |