open-standards/wai/VERSIONING.md
Transaction Science 8430d3e523
Some checks failed
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 45s
wai-audit collector and player integration / does this change touch it (push) Successful in 1m1s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 1m34s
wai-ledger service / does this change touch it (push) Successful in 1m31s
wai-fleet service / does this change touch it (push) Successful in 1m33s
WAI operation catalogue / does this change touch it (push) Successful in 1m33s
wai-app and Create / wai-app · does this change touch it (push) Successful in 1m40s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 1m48s
wai-quantum for JavaScript / does this change touch it (push) Successful in 1m8s
wai-quantum studio and desktop / does this change touch it (push) Successful in 35s
wai-sink-android native sink library / does this change touch it (push) Successful in 38s
WAI Studio / does this change touch it (push) Successful in 33s
wai-sink-swift native sink package / does this change touch it (push) Successful in 35s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Has been cancelled
wai-audit collector and player integration / collector · linux (push) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Has been cancelled
WAI operation catalogue / the catalogue and every door · linux (push) Has been cancelled
wai-fleet service / service · linux (push) Has been cancelled
wai-fleet service / service · macos (push) Has been cancelled
wai-ledger service / service · linux (push) Has been cancelled
wai-ledger service / service · macos (push) Has been cancelled
wai-quantum for JavaScript / javascript · linux (push) Has been cancelled
wai-quantum studio and desktop / studio · browser (push) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (push) Has been cancelled
wai-quantum studio and desktop / desktop app · linux (push) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (push) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been cancelled
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been cancelled
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been cancelled
WAI Studio / Studio in WebKit · linux (push) Has been cancelled
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 10s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 2m6s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 7m46s
wai breaking reads the catalogue, the MCP tools, the JavaScript, Swift and Kotlin APIs, and any project
The catalogue (wai/catalogue/ops.json) and the MCP door's tools (wai/catalogue/mcp.json, new,
held to the tools' table by a test of the binary) are a surface of category api: each
operation's id, command line, doors, effect, confirmation and stability; its flags and
arguments; the schema of its --json data and streamed lines, read as a reader reads them; the
envelope, the exit codes and the agent flags; each tool's name and input schema. A stable
operation's change is a break. A preview operation's change is no break and is owed a
changelog line that names it. An id, a flag or an agent flag renamed with the old name kept,
deprecated, is no break; removing the old name is acknowledged only once its window (two minor
releases and six months, from the export's version and the release tag's date) has closed, and
a stable name removed without that is a break no line acknowledges.

The JavaScript surface is the browser packages' #[wasm_bindgen] items by their JavaScript
names (and any committed .d.ts); Swift and Kotlin are the native sinks' public declarations,
each with its parameters, labels, defaults and result.

In a project (a directory with wai.json, or --project), wai breaking compares the project with
itself at a git ref or as published (--baseline: the project, or its package alone): the
package wai build wrote, class by class as sinks are configured for it (the sink-class check),
and the API named under breaking.api. With wai 0.5.0 released, wai.json's version 1 is
published, so breaking (api, and allow: each accepted break with its reason) is version 2's
(wai/schema/wai-json-2.schema.json): a file that names it says "wai": 2, a reader of version 1
alone refuses it as a later version, and wai create still writes version 1. An accepted break
with no reason is refused with the file. A run with no package to compare with stops with exit 5.

Planted faults, each caught: a stable operation renamed; a preview change unsaid; an accepted
break with no reason; a version-1 file naming breaking; a sink class gone; a Swift label and a
Kotlin required parameter; an MCP tool's required argument; a confirmation compared on a door
that is new.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-08 16:16:51 -05:00

9 KiB

The WAI toolchain: versions, stability and deprecations

This page says what anyone building on the wai command line can rely on: which parts are public, what a version number promises about each, and how a change is announced before it happens. It covers the wai binary, the operation catalogue and the doors the catalogue names. WAI Quantum's packages have their own page, wai-quantum/VERSIONING.md.

The deprecated items, each with the version that deprecated it and its replacement, are listed in DEPRECATIONS.md.

One version

wai, the standard's text and the reference implementation are released together, under one version: the wai crate's (wai-rs/Cargo.toml). The newest release heading of CHANGELOG.md names it, the catalogue's export carries it, and a test holds the three equal, so a version can be read from the binary and never has to be read from a page:

wai --version --json
Member What it says
toolchain This binary's version
catalogue The export's format, its operations, and the SHA-256 of wai ops export, which is catalogue/ops.json byte for byte
envelope The version of the JSON envelope --json prints
registry The registered capabilities, and the SHA-256 of registry/capabilities.json
specification The release of the standard this binary implements, and the envelope formats it reads
features The build features the catalogue names that this binary was built with, which decide the operations it holds

What is public

Surface What is public What holds it in CI
The operation catalogue Each operation's id, its command line and declared aliases, its flags and arguments, its effect, when it waits for confirmation, its stability and the schema of its --json data: catalogue/ops.json, which wai ops schema <id> prints one entry of wai ops export --check, and the catalogue's rules (wai-catalogue.yml); wai breaking, category api (surface catalogue, wai-breaking.yml)
The agent rules The exit codes, the envelope envelope/1, its error.code strings, --json, --dry-run, --yes and --no-input wai-rs/tests/cli_ops.rs
The MCP door Each tool's name, the operation of the catalogue it is, and its input schema: catalogue/mcp.json, which the binary's tests hold to the tools wai mcp serves wai-rs/tests/cli_mcp.rs and the binary's tests, in wai-conformance.yml; scripts/check-wai-ops-doors.py; wai breaking, category api (surface catalogue)
The project file wai.json, as schema/wai-json-1.schema.json and, for version 2 (version 1 and breaking), schema/wai-json-2.schema.json state it The reader's tests, which hold the reader to both
The lock and the build record wai.lock and wai-build.json, as schema/wai-lock-1.schema.json and schema/wai-build-1.schema.json state them, and the lock's bytes in project-conformance/ wai-rs/tests/cli_project.rs and the second reader, project_verify.py, in wai-conformance.yml
The C ABI, the Rust API of the library crates, the JavaScript, Swift and Kotlin APIs and the HTTP services' OpenAPI documents wai.h, what the crates document, the browser packages' bindings (wai-web, wai-live-web), the native sinks' public declarations (wai-sink-swift, wai-sink-android), and each document's operations wai breaking, category api (wai-breaking.yml)
The wire and the signed records The registry's capabilities and wire identifiers, the conformance corpora, the signing domains and the published JSON Schemas wai breaking, categories wire and record, and the corpora's generators and verifiers

What is not public: the text a command prints without --json, which is for people and may change in any release; an operation marked internal, which is never published; and the keystore's own files (wai.key/1), which only wai key reads and writes.

An operation's stability says how far its entry is promised. A stable operation changes only with a deprecation window. A preview operation is published and works, and its shape may still change: a change to one is in the changelog, and the window below is not owed.

What a version number promises

The toolchain follows Semantic Versioning 2.0. Every release so far is 0.y.z, for which that promises nothing, so this page does: the first non-zero component is the major.

  • A change of y (0.4.0 to 0.5.0) may break a public surface. Every break is in the changelog with what to do instead, and the deprecation rule below holds for a stable operation.
  • A change of z adds or fixes, and breaks nothing a public surface promised.

The wire format is the exception the standard states: until v1.0 freezes, it may change, and such a change is recorded in the changelog.

Deprecation

A renamed command, flag, route or tool stays as an alias for at least two minor releases and six months, and says it is deprecated when used. Removing it after that is a break, in the changelog with what to do instead.

Where it is used How a deprecated item says so
A flag on the command line It still works, and prints one line on standard error: wai: deprecated: --confirm, use --yes instead
An operation's id or spelling Its catalogue entry's deprecated member (since, use_instead)
Help and the catalogue's export wai --help and each operation's help name it, and agent_flags lists it with deprecated
The list DEPRECATIONS.md, from the release that deprecates it

A test holds DEPRECATIONS.md to the catalogue: every flag and operation the catalogue marks deprecated is listed there, and every item listed there is marked in the catalogue or has its removal named.

How a break is acknowledged

wai breaking --against <git-ref> reports what the working tree breaks, by category, and exits 1 on a break the changelog does not acknowledge. A change acknowledges one with a **Breaking:** line naming the finding's id in backticks, in its entry under changes/. CI runs it on every pull request that touches WAI, and on every push to main that does.

The catalogue is read as this page promises it:

  • A change to a stable operation, its flags, its --json output or its MCP tool is a break.
  • A change to a preview operation is no break, and is owed a line: the change's entry names the finding's id in backticks, with or without the word "breaking". Without one the run fails.
  • A stable name the catalogue can keep under its old spelling (an operation's id, kept as a deprecated operation; a flag, kept as a deprecated alias; --confirm) renamed with the old one kept, deprecated, is no break. Removing the old one is a break a line acknowledges only once its window has closed: two minor releases after the release that deprecated it, read from the export's version, and six months after that release's tag (wai-v<version>). Removing it before then, or removing a stable name that was never deprecated, is a break no line acknowledges, and the run says so: keep the old name, deprecated, until its window closes.

A project's breaking changes

wai breaking runs on any project, in its directory (one with wai.json) or with --project <dir>, against the project at a git ref (--against <ref>) or as it was published (--baseline <dir>: the project's directory, or its package alone, as served). It compares:

  • The package wai build wrote under dist/, as the sinks that play it are configured for it (category wire): a class of the packaging policy that is gone, or whose playlists or stage view are gone, or whose objects need a capability they did not, is a break for the sinks set up with that class; so is a floor codec the classical presentation no longer offers, and a MoQ track a subscriber named that is gone or changed. A class that now takes the floor alone is no break: its sinks still play. A run with no package to compare with on either side stops (exit 5); it does not pass what it did not compare.
  • The API the project names under breaking.api in wai.json: JavaScript and TypeScript modules, Swift and Kotlin sources, OpenAPI documents and JSON Schemas, each read by its kind.

A project accepts a break in wai.json, with the reason it is accepted, which the report gives beside the finding; an entry with no reason is refused with the file. breaking is a member of the project file's version 2, which says so, so that a wai that reads version 1 alone refuses the file as a later version:

{ "$schema": "https://wai.transaction.science/schema/wai.json/2", "wai": 2,
  "breaking": { "api": ["sdk/index.d.ts"],
                "allow": [{ "id": "api:js:sdk/index.d.ts:play", "reason": "renamed start in 2.0; call start" }] } }