wai toolchain: wai.json's schema and version, MCP 2026-07-28, AGENTS.md in every template, WAI Studio in the quickstart archive, and one port table #634

Merged
dcharlot merged 1 commit from wai/toolchain-fixes into main 2026-11-05 07:01:59 -05:00
Owner

What this is

Fixes to the WAI toolchain: the project file, the agent door, the templates, the quickstart archive, the local stack's ports and the catalogue's verb list.

Merge order. This branch sits on #632's commit, 946f3beda, which moves changelog entries into wai/changes/ and the conformance workflow's lists into step files. Merge #632 first; until it merges, this pull request's diff also shows #632's change. The pull request of wai/conform-output is stacked on this one: the two rewrite the same text in wai-release.yml, scripts/check-wai-ops-doors.py and wai/catalogue/README.md, and that one carries the reconciliation.

What it carries. One commit, 1f0ab6ebf: the change of wai/toolchain-fixes (69f88e62f..074658780) in #632's layout. Its message lists the source commits. Compared with the source branch:

  • its six changelog entries are six files of wai/changes/. Its one edit to an existing entry, the WHD1 line of the holdings entry, stays an edit of wai/CHANGELOG.md;
  • its one edit to wai-conformance.yml, the wai/schema/** trigger path beside wai/examples/**, stays in the workflow as it was;
  • in codecs/registry.rs the HOLDINGS doc constant sits beside JWP_RECEIPTS and the WHD1 row beside the JWP rows, instead of at the end of their lists.

Every other file is as the source branch has it.

What it defines or fixes

wai.json names its schema, its version and its project, and the schema is committed.

  • Three members: $schema, the URL of the file's JSON Schema; wai, the file's version, 1; and name, the project's machine name, a DNS label.
  • The reader refuses a file of a later version by name (upgrade wai) before it reads any other member, so a member a later version adds is never refused as unknown in its place. It refuses a $schema of another schema and a name that breaks the rule. A file without the three reads as before, as version 1.
  • The schema, wai/schema/wai-json-1.schema.json (JSON Schema 2020-12), states every member and every rule the reader holds. A whole number is read however it is written (4.0 and 4e0 are 4), and none above 2^53 − 1.
  • The release waits for the schema to be served: the tag build's first job fetches each schema's $id and fails unless it answers with the committed schema.
  • wai create writes the three members, naming the project for its directory when that is a project name, else for its template. Every template's wai.json carries them.

wai mcp speaks MCP 2026-07-28, the stateless revision, beside the revisions initialize negotiates.

  • A request whose _meta names its revision is served from what it carries alone. Its client capabilities are required (-32602 without them). A revision the server does not serve per request is refused -32022, with the revisions a request may name, the one requested, and the ones initialize negotiates. The supported list never holds the revision asked for, so a client that retries with one of them is served.
  • server/discover gives the revisions the server speaks, newest first, its capabilities and its instructions. Every result of that revision carries resultType and the server's name and version; server/discover and tools/list carry ttlMs and cacheScope. ping, which that revision removed, is -32601 under it.
  • initialize now negotiates 2025-11-25, the last revision with a handshake, and still opens a session in 2025-06-18, 2025-03-26 or 2024-11-05. One process serves both eras, and the tools are the same in both.

Every template carries an AGENTS.md. The templates of wai create each carry the instructions a coding agent reads: what the project is, and how to build, run, test and conform it, with what never to do to make a check pass, and that no secret belongs in the repository. wai create writes it, and wai setup-agent adds its own block to it. The remote desktop template's .gitignore keeps out host.key, the private key host.sh makes in the project.

The quickstart archive carries WAI Studio, wai-ingest and wai-quantum.

  • share/wai/studio/ holds WAI Studio, built once by the new quickstart/build-studio.sh, so wai dev from an installed archive serves it at /_wai/. Before, /_wai/ answered that Studio's files were not there. build.sh takes it as --studio <dir>.
  • bin/wai-ingest, the ingest gateway, and bin/wai-quantum, the quantum command line, join the archive's binaries; build.sh runs each before it packages it, where it can.
  • The release builds the room client and Studio once, into one attachment, and every platform's archive carries both.
  • wai-quantum stays its own package: the release's two package-manager files install every binary of the archive but wai-quantum, and depend on its own package instead, so installing wai and wai-quantum, in either order, gives one copy of wai-quantum. quickstart/test/formulae_test.py, in the examples workflow, runs formulae.py against a stand-in release and holds both files to build.sh.

The local stack's ports, in one table. wai/quickstart/README.md has a port table: what wai dev, the relay, the room service, the ingest gateway, the audit collector, the ledger, the fleet service, the quantum job service, the worlds' relay, the stitched presentation verifier and wai http origin listen on by default, and which setting moves each; no two share a port. The room service's example now names the relay's WebSocket port, 4480, where it named 9681, on which nothing listens.

The verbs upscale and tonemap are recorded in naming rule N3's list. They joined the closed verb list with media.upscale and media.tonemap after the list was approved; the catalogue's README now says so and why. The doors' check, scripts/check-wai-ops-doors.py, gains both, so a door named with either is held to the catalogue. The near-synonym up (start, as in wai dev) is named in the README and the check, where both had left it out.

The registry lists WHD1, the holdings record's magic (holdings §4.1), and holdings::MAGIC is held to that one row.

What the checks hold

  • The project file. The reader's tests, in the wai binary, hold the reader and the schema together: the same members, modes and name rule, and the same verdict on every template's file and on files that each break one rule. The schema is read as a validator reads it, with its name pattern run as a regular expression and numbers compared by value. wai-catalogue.yml and wai-conformance.yml now run on a change to wai/schema/**.
  • The agent door. tests/cli_mcp.rs covers the stateless revision, server/discover, the refusals and their data, and the earlier revisions' handshake.
  • The templates. A test of wai create holds every template to carrying an AGENTS.md with each of its sections.
  • The archive. quickstart/test/clean-machine.sh refuses an archive that lacks any of its binaries, the room client, or Studio's page and core. It runs wai-quantum and wai-ingest from the archive and requires wai dev --check to have served Studio at /_wai/. The examples workflow's archive job builds Studio as the release does, runs clean-machine.sh on the archive it built, and fails when the builds leave a file in the checkout.
  • The ports. joule-moq-room's tests/ports.rs holds every row of the port table to the program that serves it and to the example configurations that reach it. It reads the gateway's example with the gateway's own reader and starts the gateway and the room service from their examples. joule-moq-room.yml runs on a change to each file the test reads.
  • The verb list. A test of the catalogue holds the README's list and the doors' check's to VERBS, and the near-synonyms the two state to NEAR_SYNONYMS. The doors' check's self-test fails a door that names an operation with upscale or tonemap that the catalogue does not hold.

How it was verified

This commit, 1f0ab6ebf.

  • Locally (git and Python checks only): scripts/wai-conformance-lists.py selftest and check, scripts/wai-conformance-lists-selftest.sh, scripts/check-changelog-fragment.py against main, scripts/changelog-assemble.py --check, scripts/changelog-fragments-selftest.sh, and the ops doors' check with its self-test all pass.

  • The layout changes only the layout. A comparison of trees shows that the change is the source branch's change except for the differences listed above. The entry files hold exactly the lines the source branch added to wai/CHANGELOG.md, and its WHD1 lines stay in wai/CHANGELOG.md byte for byte at the same place. The workflow edit is unchanged, and the registry change is the same rows, reordered. That comparison was made on the conversion's first base, #632's earlier tip 14f1abb7c; rebasing onto 946f3beda left every file's change the same.

  • On a Linux x86_64 build host:

    • in wai/wai-rs, cargo check --locked --no-default-features --tests with each of the feature lists holdings, quickstart and quickstart,app;
    • cargo test --locked --no-default-features --lib catalogue;
    • in joule-moq-room's own workspace, cargo check --locked --tests and cargo test --locked --test ports.

    All pass.

  • On the stack above it. On the checkout of wai/conform-output's pull request, which holds this commit beneath its own, the wai binary's unit tests and the cli_mcp tests pass too (that pull request lists the runs).

  • With the other converted branches. This branch merges without conflict with each of the other branches converted to #632's layout, with wai/conform-output stacked on it (by git merge-tree). Merging all of them in forward, reverse and a mixed order gives one tree. On the build host, that tree passes these runs: cargo check --tests under the derived WAI_FEATURES and under WAI_PQ_FEATURES; cargo check --tests of quickstart,app; the catalogue's library tests; and the wai binary's unit tests.

On the CI hosts. Results on the CI runners come from this pull request's own CI run. None of the runs above is a CI result.

🤖 Generated with Claude Code

## What this is Fixes to the WAI toolchain: the project file, the agent door, the templates, the quickstart archive, the local stack's ports and the catalogue's verb list. **Merge order.** This branch sits on #632's commit, 946f3beda, which moves changelog entries into `wai/changes/` and the conformance workflow's lists into step files. Merge #632 first; until it merges, this pull request's diff also shows #632's change. The pull request of `wai/conform-output` is stacked on this one: the two rewrite the same text in `wai-release.yml`, `scripts/check-wai-ops-doors.py` and `wai/catalogue/README.md`, and that one carries the reconciliation. **What it carries.** One commit, 1f0ab6ebf: the change of `wai/toolchain-fixes` (69f88e62f..074658780) in #632's layout. Its message lists the source commits. Compared with the source branch: - its six changelog entries are six files of `wai/changes/`. Its one edit to an existing entry, the `WHD1` line of the holdings entry, stays an edit of `wai/CHANGELOG.md`; - its one edit to `wai-conformance.yml`, the `wai/schema/**` trigger path beside `wai/examples/**`, stays in the workflow as it was; - in `codecs/registry.rs` the `HOLDINGS` doc constant sits beside `JWP_RECEIPTS` and the `WHD1` row beside the JWP rows, instead of at the end of their lists. Every other file is as the source branch has it. ## What it defines or fixes **`wai.json` names its schema, its version and its project, and the schema is committed.** - Three members: `$schema`, the URL of the file's JSON Schema; `wai`, the file's version, `1`; and `name`, the project's machine name, a DNS label. - The reader refuses a file of a later version by name (`upgrade wai`) before it reads any other member, so a member a later version adds is never refused as unknown in its place. It refuses a `$schema` of another schema and a name that breaks the rule. A file without the three reads as before, as version 1. - The schema, `wai/schema/wai-json-1.schema.json` (JSON Schema 2020-12), states every member and every rule the reader holds. A whole number is read however it is written (`4.0` and `4e0` are `4`), and none above 2^53 − 1. - The release waits for the schema to be served: the tag build's first job fetches each schema's `$id` and fails unless it answers with the committed schema. - `wai create` writes the three members, naming the project for its directory when that is a project name, else for its template. Every template's `wai.json` carries them. **`wai mcp` speaks MCP 2026-07-28, the stateless revision, beside the revisions `initialize` negotiates.** - A request whose `_meta` names its revision is served from what it carries alone. Its client capabilities are required (`-32602` without them). A revision the server does not serve per request is refused `-32022`, with the revisions a request may name, the one requested, and the ones `initialize` negotiates. The supported list never holds the revision asked for, so a client that retries with one of them is served. - `server/discover` gives the revisions the server speaks, newest first, its capabilities and its instructions. Every result of that revision carries `resultType` and the server's name and version; `server/discover` and `tools/list` carry `ttlMs` and `cacheScope`. `ping`, which that revision removed, is `-32601` under it. - `initialize` now negotiates 2025-11-25, the last revision with a handshake, and still opens a session in 2025-06-18, 2025-03-26 or 2024-11-05. One process serves both eras, and the tools are the same in both. **Every template carries an `AGENTS.md`.** The templates of `wai create` each carry the instructions a coding agent reads: what the project is, and how to build, run, test and conform it, with what never to do to make a check pass, and that no secret belongs in the repository. `wai create` writes it, and `wai setup-agent` adds its own block to it. The remote desktop template's `.gitignore` keeps out `host.key`, the private key `host.sh` makes in the project. **The quickstart archive carries WAI Studio, `wai-ingest` and `wai-quantum`.** - `share/wai/studio/` holds WAI Studio, built once by the new `quickstart/build-studio.sh`, so `wai dev` from an installed archive serves it at `/_wai/`. Before, `/_wai/` answered that Studio's files were not there. `build.sh` takes it as `--studio <dir>`. - `bin/wai-ingest`, the ingest gateway, and `bin/wai-quantum`, the quantum command line, join the archive's binaries; `build.sh` runs each before it packages it, where it can. - The release builds the room client and Studio once, into one attachment, and every platform's archive carries both. - `wai-quantum` stays its own package: the release's two package-manager files install every binary of the archive but `wai-quantum`, and depend on its own package instead, so installing `wai` and `wai-quantum`, in either order, gives one copy of `wai-quantum`. `quickstart/test/formulae_test.py`, in the examples workflow, runs `formulae.py` against a stand-in release and holds both files to `build.sh`. **The local stack's ports, in one table.** `wai/quickstart/README.md` has a port table: what `wai dev`, the relay, the room service, the ingest gateway, the audit collector, the ledger, the fleet service, the quantum job service, the worlds' relay, the stitched presentation verifier and `wai http origin` listen on by default, and which setting moves each; no two share a port. The room service's example now names the relay's WebSocket port, 4480, where it named 9681, on which nothing listens. **The verbs `upscale` and `tonemap` are recorded in naming rule N3's list.** They joined the closed verb list with `media.upscale` and `media.tonemap` after the list was approved; the catalogue's README now says so and why. The doors' check, `scripts/check-wai-ops-doors.py`, gains both, so a door named with either is held to the catalogue. The near-synonym `up` (`start`, as in `wai dev`) is named in the README and the check, where both had left it out. **The registry lists `WHD1`**, the holdings record's magic (holdings §4.1), and `holdings::MAGIC` is held to that one row. ## What the checks hold - **The project file.** The reader's tests, in the `wai` binary, hold the reader and the schema together: the same members, modes and name rule, and the same verdict on every template's file and on files that each break one rule. The schema is read as a validator reads it, with its name pattern run as a regular expression and numbers compared by value. `wai-catalogue.yml` and `wai-conformance.yml` now run on a change to `wai/schema/**`. - **The agent door.** `tests/cli_mcp.rs` covers the stateless revision, `server/discover`, the refusals and their `data`, and the earlier revisions' handshake. - **The templates.** A test of `wai create` holds every template to carrying an `AGENTS.md` with each of its sections. - **The archive.** `quickstart/test/clean-machine.sh` refuses an archive that lacks any of its binaries, the room client, or Studio's page and core. It runs `wai-quantum` and `wai-ingest` from the archive and requires `wai dev --check` to have served Studio at `/_wai/`. The examples workflow's archive job builds Studio as the release does, runs `clean-machine.sh` on the archive it built, and fails when the builds leave a file in the checkout. - **The ports.** joule-moq-room's `tests/ports.rs` holds every row of the port table to the program that serves it and to the example configurations that reach it. It reads the gateway's example with the gateway's own reader and starts the gateway and the room service from their examples. `joule-moq-room.yml` runs on a change to each file the test reads. - **The verb list.** A test of the catalogue holds the README's list and the doors' check's to `VERBS`, and the near-synonyms the two state to `NEAR_SYNONYMS`. The doors' check's self-test fails a door that names an operation with `upscale` or `tonemap` that the catalogue does not hold. ## How it was verified **This commit, 1f0ab6ebf.** - **Locally** (git and Python checks only): `scripts/wai-conformance-lists.py selftest` and `check`, `scripts/wai-conformance-lists-selftest.sh`, `scripts/check-changelog-fragment.py` against main, `scripts/changelog-assemble.py --check`, `scripts/changelog-fragments-selftest.sh`, and the ops doors' check with its self-test all pass. - **The layout changes only the layout.** A comparison of trees shows that the change is the source branch's change except for the differences listed above. The entry files hold exactly the lines the source branch added to `wai/CHANGELOG.md`, and its `WHD1` lines stay in `wai/CHANGELOG.md` byte for byte at the same place. The workflow edit is unchanged, and the registry change is the same rows, reordered. That comparison was made on the conversion's first base, #632's earlier tip 14f1abb7c; rebasing onto 946f3beda left every file's change the same. - **On a Linux x86_64 build host:** - in `wai/wai-rs`, `cargo check --locked --no-default-features --tests` with each of the feature lists `holdings`, `quickstart` and `quickstart,app`; - `cargo test --locked --no-default-features --lib catalogue`; - in joule-moq-room's own workspace, `cargo check --locked --tests` and `cargo test --locked --test ports`. All pass. - **On the stack above it.** On the checkout of `wai/conform-output`'s pull request, which holds this commit beneath its own, the `wai` binary's unit tests and the `cli_mcp` tests pass too (that pull request lists the runs). - **With the other converted branches.** This branch merges without conflict with each of the other branches converted to #632's layout, with `wai/conform-output` stacked on it (by `git merge-tree`). Merging all of them in forward, reverse and a mixed order gives one tree. On the build host, that tree passes these runs: `cargo check --tests` under the derived `WAI_FEATURES` and under `WAI_PQ_FEATURES`; `cargo check --tests` of `quickstart,app`; the catalogue's library tests; and the `wai` binary's unit tests. **On the CI hosts.** Results on the CI runners come from this pull request's own CI run. None of the runs above is a CI result. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wai/toolchain-fixes, converted to the layout of the fix: no shared append point
All checks were successful
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 3m54s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 7m52s
wai-fleet service / service · macos (pull_request) Successful in 43s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 30s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m52s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 9m7s
wai-ledger service / service · macos (pull_request) Successful in 1m26s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 17s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 20m26s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 43s
wai-pack / wai-pack · macos (pull_request) Successful in 4m19s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m38s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m34s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 3m26s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 19m27s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 2m5s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 23m32s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m27s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 7m32s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 37s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 19s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 11m58s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 5m11s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 7m35s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 3m25s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m20s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 12m0s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 10m54s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 17m29s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h30m12s
1f0ab6ebf1
The change of wai/toolchain-fixes (69f88e62f..074658780, 21 commits), on the fix branch: its
changelog entries as files of wai/changes/, its wai-conformance.yml edits as step files,
corpus files and test tags, and every other file as the branch has it.

- b04013914 holdings: the registry lists WHD1, the record's magic (§4.1)
- a184abb87 catalogue: upscale and tonemap are recorded in N3's verb list, and the doors' check knows them
- 8db31a778 wai mcp: MCP 2026-07-28, the stateless revision, beside the three initialize negotiates
- 052830194 wai.json: $schema, wai and name, and the schema of version 1 committed beside the reader
- 163fc2017 wai create: every template carries an AGENTS.md
- fe9b26fbc joule-moq-room: the example names the relay's WebSocket port, 4480, and one test holds every port
- 359b5ba9d quickstart: the archive carries WAI Studio, wai-ingest and wai-quantum
- 6334d88c8 joule-moq-room: the port table holds every daemon's default, and the listeners off until set
- d38610de6 wai.json: the two workflows that hold the schema to its reader run when the schema changes
- 179df52b7 catalogue: the two verbs joined the list after wai 0.4.0, not in toolchain 0.3.0
- 971cf5862 wai.json: a file of a later version is refused as that version before any member it adds
- 1a59a39f7 wai.json: the reader takes a whole number however it is written, and the tests run the name pattern
- d752fd9b4 wai.json: the release waits for the schema to be served, and version 1 is fixed by the first release that writes it
- c213ed9db wai mcp: -32022 names as supported only the revisions a request may name, never the one asked for
- 99b800f29 wai mcp: initialize negotiates 2025-11-25, the last revision with a handshake
- e33021c3f catalogue: the near-synonym list is held in every text that states it, and the doors' check knows up
- b99bb70be catalogue: the changelog records the near-synonym list held with the verb list
- a0beb2163 quickstart: the wai formula and manifest depend on wai-quantum's own instead of installing a second copy
- 0e5084031 quickstart: Studio's build leaves the checkout as it found it, and the examples workflow runs clean-machine.sh
- 4cc4ae3d7 joule-moq-room: the port test reads the gateway's example with the gateway's own reader, and starts the gateway from it
- 074658780 quickstart: the changelog names where Studio's build goes, not where it went before it shipped

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!634
No description provided.