Compatibility and deprecation promises
What is committed, per surface, and how a breaking change is announced.
Written By Dustin
Last updated 35 minutes ago
TOVIO publishes a normative compatibility policy covering thirteen independently versioned surfaces: the storage format, the wire protocol, capability tokens, the MCP and agent API, the conformance corpus, the CLI surface, Forge routes, the native binding interface, the plugin contract, the cryptographic domain-separation constants, request proof, Forge operational records, and audit records. The reasoning behind the breadth is blunt: a contract someone can build against but that carries no stated promise is a contract that gets broken by accident.
Two caveats worth having up front. The policy document is itself still a Draft, and no release has been tagged, so these are commitments on the record rather than obligations already running against a shipped line. They are written down so you can hold the project to them, and so you can see what is not yet promised.
The backward window
Every surface commits to N-1: at any time, the current major and the one immediately before it are supported, and a reader that supports version N+1 must continue to accept version N. TOVIO 1.0's storage format, wire protocol, and capability-token schema get a longer commitment — a minimum of 24 months from the 1.0 release, independent of later major releases.
Minimum deprecation periods
Measured from the release that announces the deprecation to the earliest release that may remove the surface.
Throughout the period both versions stay supported, and the deprecated path emits a migration notice naming the replacement and the earliest release in which removal may occur. That notice goes to standard error for the CLI — never to standard output and never inside a --json document, so it cannot corrupt a machine-readable pipeline.
What counts as breaking, by class
- Content-addressed surfaces. Any change that alters how an existing object, record, or signed payload encodes — and therefore its address or signature — is breaking. A domain-separation constant or tag is never reused for another purpose, ever, including across major versions; retired ones are permanently burned.
- Negotiated surfaces. A minor bump may only add capabilities an older peer can decline, and both peers interoperate at the highest mutually supported set. Inferring capability from a version string rather than from the negotiation is treated as a defect.
- Rejecting surfaces. An unknown version string is rejected outright rather than parsed on a best-effort basis, so a new schema always takes a new version string.
- Consumed surfaces. For the CLI: removing or renaming a command or flag; changing a flag's default so an existing invocation behaves differently; removing a key from a
--jsondocument or changing its type or meaning; changing an exit code for an existing condition; changing which error code an existing condition raises; and retiring an error code. Adding a command, an optional flag, a--jsonkey, or a new code for a genuinely new condition is additive. A retiredTVOerror code is permanently burned, exactly like a domain tag.
The command-surface governance rule — to add a command, remove or merge one — deliberately produces removals. Those removals are breaking changes and take the full deprecation period. Keeping the surface small is not a licence to break consumers quickly.
Platform support floors
The published platform matrix is part of the contract. Dropping a target or raising a minimum operating-system version is a breaking change and follows the same deprecation path — it will not happen quietly in a patch release. The same rule covers the native binding prebuilds: dropping a cell from the published operating-system, architecture, and runtime-major matrix is breaking.
Every declared target currently carries its minimum and a certification flag that is not yet set. A floor cannot be certified against an undeclared minimum, which is why the declaration exists first; treat the current entries as declared support, not as verified support.
Downgrades, which most policies leave out
Every release publishes a rollback boundary: the oldest release it can be downgraded to without data loss, and an explicit list of features that, once used, prevent downgrade. A feature belongs on that list when using it writes bytes, records, or refs an older supported reader cannot interpret. Such features are introduced behind a default-off gate that emits a one-time notice naming the rollback consequence when you enable it.
Boundaries are verified rather than asserted: the upgrade matrix includes a downgrade leg for every packaged platform, and a downgrade that succeeds when the boundary says it should fail — or fails when it says it should succeed — is a release-blocking defect.
Mixed-version fleets
Objects a replica receives but does not recognise are preserved verbatim and never reinterpreted during sync. This holds across every version boundary, so a fleet running several versions at once cannot corrupt history through a relay.
How a breaking change is announced
Never silently. Each one is proposed as a public decision record with its rationale and migration design, reflected in the owning specification, recorded in the changelog under an explicit "Breaking changes" heading naming the version it lands in and when the window closes, given its full deprecation period, and reflected in the surface register in the same change that lands it. Its migration ships in the same release, and for content-addressed surfaces that means a tested migration with conformance vectors for both versions. Old conformance corpora are frozen and never deleted, so regression coverage only grows.
A Stable contract is not broken faster than this allows, even to fix a cosmetic wart. A change required to fix a security defect may take an accelerated path, but it must still ship a migration, be disclosed under the security policy, and record the shortened window and its justification in the release notes.
The full policy
The compatibility and deprecation specification on the documentation site is normative and complete; the versioning page there is the reader-friendly version. This article summarises both.