open-standards/wai/schema
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science 0fe1976f50 wai lock, wai check and wai build: an integer tone, a fix for every stale lock, and a lock from wai create
The watch room's sample sound is made in integer arithmetic: each half cycle
by the rational form of Bhaskara I, at most 10 of 6000 from the sine, every
harmonic under -59 dB, peak, pitches and rate as before. Its bytes, and the
digest of the template a lock pins, are the same on every host by
construction. The corpus pins its digest, the second reader makes it by the
same rule, and a test refuses a floating-point value in its path, reading
the source as written whatever line ends a checkout gave it.

Every finding about a lock that is stale, was edited by hand or is not there
carries its fix, run wai lock, with the directory and the --root and
--packer the check was given: in the text under the finding, and as the
finding's fix and the error's hint in the envelope. A lock another wai wrote
says which version wrote it. A later version's lock says upgrade wai.

wai create writes the lock of the project it makes, so a new project passes
wai check and wai build as it is. A project that states nothing for wai to
build gets a dist/ with its build record alone.

wai/catalogue/ops.json is never converted on a checkout either: a lock pins
its digest. project.sh builds wai-pack in a target directory of its own when
CARGO_TARGET_DIR is shared. The tests run on Windows from a checkout with
core.autocrlf=true: they take their Python from $PYTHON, pass plain paths
rather than verbatim ones, and give git check-attr its paths on standard
input; the second reader takes a verbatim path as well.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 17:28:40 -05:00
..
README.md wai lock, wai check and wai build: an integer tone, a fix for every stale lock, and a lock from wai create 2026-11-06 17:28:40 -05:00
wai-build-1.schema.json wai lock, wai check and wai build: a project pinned, validated and built 2026-11-06 17:28:16 -05:00
wai-json-1.schema.json wai lock, wai check and wai build: a project pinned, validated and built 2026-11-06 17:28:16 -05:00
wai-lock-1.schema.json wai lock, wai check and wai build: a project pinned, validated and built 2026-11-06 17:28:16 -05:00

Project schemas

Three JSON Schemas (2020-12), each with its $id the address it is to be served from, which the files it describes name in their $schema member:

Schema Describes $id Reader
wai-json-1.schema.json wai.json, a project file, version 1 https://wai.transaction.science/schema/wai.json/1 dx/project.rs
wai-lock-1.schema.json wai.lock, what wai lock writes https://wai.transaction.science/schema/wai.lock/1 dx/lock.rs
wai-build-1.schema.json wai-build.json, what wai build writes last into dist/ https://wai.transaction.science/schema/wai-build.json/1 dx/build.rs writes it

The readers are under wai/wai-rs/src/bin/wai_cli/. The release of wai waits for the schemas: the tag build (.github/workflows/wai-release.yml) fails while an address does not serve its file, so no release writes a file that names a schema an editor or an agent cannot fetch.

dx/project.rs's tests hold wai.json's schema to the reader: the same members in the file and in each block, the same modes, the same name rule, and the same verdict, accept or refuse, on every template's project file and on a set of files each breaking one rule. dx/lock.rs's and dx/build.rs's tests do the same for theirs. A change to either is a change to both.

wai.lock

The lock pins everything whose bytes change a project's results, as far as the toolchain can resolve it. The file is RFC 8785 over one object, on one line, with no line ending: it holds no time and no path, so the same inputs give the same bytes on any host, and a checkout that converts line endings (core.autocrlf=true) has none to convert. Its digest is the SHA-256 of the file.

Member Required What it pins
$schema, wai yes This schema, and the lock's version, 1
toolchain yes version, wai's, and catalogue.sha256, the SHA-256 of wai ops export (catalogue/ops.json)
registry yes sha256, the SHA-256 of wai registry export (registry/capabilities.json)
template when wai.json names one name, and sha256 where the wai that wrote the lock holds it: the SHA-256 of the template's listing, one line a file, sorted by path as bytes, each the file's SHA-256, two spaces, its path and a line feed. The files wai create makes are in it
priors when wai.json names any Each parameter set's pin, by its name in wai.json (SPEC.md §3.1): a directory is form wai.prior.set with the sha256 of its listing, one file has no form and the sha256 of the file
policy when wai.json names one schema, the policy's version, and blake3, its canonical digest as wai-pack policy prints it (packaging §3)
conformance when wai.json names any Each corpus, by <kind>/<suite>: digest, the corpus digest a conformance result names (conformance-results §2.1)

wai lock writes it, and wai create writes it for the project it makes, so a new project passes wai check and wai build as it is. A finding about a lock that is stale, was edited by hand or is not there carries the fix run wai lock.

A member with nothing to pin is absent, never null, never empty and never made up. wai lock refuses when it cannot compute something the project states (no wai-pack, no checkout of the standard): another host's lock would differ. A template that wai does not hold is the exception: it pins the name, and wai check says the digest is not checked.

A reader refuses a later version as that version (upgrade wai), before it reads anything else, by its wai or its $schema; every member it does not know; and bytes that are not the canonical form of what they say, which is how an edit by hand that changes no value shows. The bytes are project-conformance/'s, whose second reader, project_verify.py, recomputes every digest with the standard library alone.

A digest over a file's bytes is over the bytes a checkout holds. A corpus and a template keep theirs (* -text, a test holds each to it). A parameter set is the project's: where a checkout converts line endings it needs the same, in the project's own .gitattributes, or the lock says it is stale. The project file and the policy do not need it, since each is pinned by its canonical form.

wai-build.json

What wai build writes last into dist/, so a built tree says what it came from. It is RFC 8785 on one line, as the lock is: project, the project's name and the sha256 of wai.json's canonical form (RFC 8785 over what the file says, a whole number however it is written, so a line ending or a layout does not change it); lock, the sha256 of wai.lock; toolchain, as the lock pins it; and files, every other file of the tree, sorted by path as bytes, each with its sha256 and bytes. It holds no time and no path outside dist/, so two builds of one project and lock give one record, and its SHA-256 is the tree's digest. A package's receipt is signed, so the tree is the same for the same key.

Versions

The lock and the build record follow the project file's rule: a later version is a new schema beside this one, refused as that version. Below, of the project file.

Version 1 stays open until the first release of wai that writes it. From that release on, its readers are in use, and a reader refuses any member it does not know, so version 1 does not change: a member added to it would be refused, as unknown, by every reader of that release. A later version is a new schema at …/schema/wai.json/<version>, beside this one. A reader refuses a file of a later version as that version (upgrade wai), by its wai member or by its $schema, before it reads any other member, so the members the later version adds never stop it first.

Every member has its reader. requires.capabilities is wai check's; priors, package and conform are wai lock's, wai check's and, for package, wai build's. The project file's other members in the toolchain's design (room, breaking, targets, receipts, requires.toolchain, requires.fallbacks, and port in dev) join the file with the operation that reads it; a member accepted with nothing to read it would be one the strict reader ignores, which is what it refuses to do.