Some checks failed
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 21s
wai-fleet service / does this change touch it (push) Successful in 17s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 26s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 28s
wai-app and Create / wai-app · does this change touch it (push) Successful in 22s
wai-quantum energy-landscape jobs / does this change touch it (push) Successful in 15s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 50s
wai-quantum editors / does this change touch it (push) Successful in 31s
wai-quantum for JavaScript / does this change touch it (push) Successful in 29s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 40s
wai-audit collector and player integration / does this change touch it (push) Successful in 1m23s
wai-quantum studio and desktop / does this change touch it (push) Successful in 30s
wai-fleet service / service · macos (push) Successful in 59s
wai-quantum for Python / does this change touch it (push) Successful in 31s
wai-quantum docs, course and locales / does this change touch it (push) Successful in 1m27s
wai-quantum views in agent hosts / does this change touch it (push) Successful in 21s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 2m4s
wai-key-proxy / does this change touch it (push) Successful in 1m55s
WAI operation catalogue / does this change touch it (push) Successful in 1m56s
wai-quantum command line / does this change touch it (push) Successful in 1m40s
wai-ledger service / does this change touch it (push) Successful in 1m50s
wai-quantum contract / does this change touch it (push) Successful in 1m41s
WAI Studio / does this change touch it (push) Successful in 12s
wai-sink-swift native sink package / does this change touch it (push) Successful in 25s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 1m43s
wai-sink-android native sink library / does this change touch it (push) Successful in 42s
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 2m45s
wai-quantum editors / editors · macos (push) Successful in 2m2s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m21s
wai-fleet service / service · linux (push) Successful in 3m36s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Successful in 12s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Successful in 52s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 2m37s
wai-quantum for Python / python · macos (push) Successful in 2m57s
wai-ledger service / service · macos (push) Successful in 1m16s
wai-quantum editors / editors · linux (push) Successful in 3m46s
wai-audit collector and player integration / collector · linux (push) Successful in 3m39s
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Successful in 3m23s
wai-quantum for Python / python · linux (push) Successful in 4m26s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 6m38s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 5m7s
wai-quantum command line / command line · macos (push) Successful in 2m33s
wai-quantum for JavaScript / javascript · linux (push) Successful in 5m35s
wai-key-proxy / proxy · linux (push) Successful in 1m12s
joule-moq-room room service / joule-moq-room, every target (push) Successful in 7m3s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 7m40s
wai-quantum energy-landscape jobs / native against WebAssembly, over many seeds (push) Successful in 7m39s
wai-ledger service / service · linux (push) Successful in 2m5s
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Successful in 7s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Successful in 8m36s
wai-quantum energy-landscape jobs / the same bits · macos (push) Successful in 8m36s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m10s
wai-quantum views in agent hosts / views · a scripted host (push) Successful in 4m26s
wai-quantum views in agent hosts / views · the page and its engine (push) Successful in 6m33s
wai-quantum contract / API compatibility · linux (push) Successful in 4m44s
wai-quantum energy-landscape jobs / the same bits · linux-arm64 (push) Successful in 13m4s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 6m46s
wai-quantum energy-landscape jobs / reader, kernels, answers and the stated result · linux, release (push) Successful in 14m11s
wai-quantum energy-landscape jobs / the module under wasm32-wasip2 (wasmtime) (push) Successful in 14m12s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 13m18s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 10m49s
WAI Studio / Studio in Chromium and Firefox · macos (push) Successful in 11m36s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Successful in 12m10s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Successful in 16m36s
wai-quantum contract / schemas and the committed tool lists · linux (push) Successful in 9m58s
wai-quantum studio and desktop / studio · browser (push) Successful in 16m35s
WAI Studio / Studio in WebKit · linux (push) Successful in 12m22s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Successful in 22m0s
wai release binaries build on Windows / the seven release binaries · windows (push) Successful in 24m31s
joule-code conformance gate / joule-moq-ingest, every target (push) Successful in 28m51s
joule-code conformance gate / joule-moq-relay, every target (push) Successful in 28m59s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 29m41s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 11m58s
wai-quantum command line / command line · linux (push) Successful in 48m17s
Folds, each the program it folds run as itself, so what it prints and its exit status are the program's for the same arguments: wai audit report|check|verify (audit.create, audit.check, audit.verify) is wai-audit, --owner its WAI_AUDIT_OWNER; wai serve <role> [--config F] [--check] (service.start) starts wai-<role>: relay, room, ingest and key-release from a file, audit, fleet, ledger and quantum-service from their environment; wai quantum run|plan|lint|verify|methods (quantum.run, .inspect, .check, .verify, .list) is wai-quantum with that verb, and no other verb of it is reached. A program is its flag, WAI_<NAME>_BIN, beside wai, or on PATH; one not there is exit 5, program-not-found. report is not an N3 verb, so wai audit report is the operation audit.create. --check on the daemons: wai-relay, wai-room (its keys too) and wai-ingest --config F --check, and wai-key-release serve F --check, read the configuration as each starts from it and start nothing, exit 1 with the reason when it does not read. The proxy is installed as wai-key-release; wai-key-proxy is the same program under its earlier name. wai cmcd encode|decode|verify is wai_telemetry's tool compiled in (cmcd.rs, one module behind both; telemetry joins full). wai receipt create <file>... --from <input>... [--key] signs the operation receipt a toolchain write leaves, for files made elsewhere. wai verify reads every record by its kind: by name, and a JSON record by what it holds (a delivery receipt or claim as receipt_verify answers it, a room session, an audit bundle as wai-audit verify does with --owner/--channel, a sealed playlist by its mr/<blake3>.json as check-playlist does); a file of no kind is exit 2, unknown-record. wai mcp --toolset quantum starts wai-quantum mcp and answers each quantum_* tool with that server's own answer and schemas. wai media score build|render alias wai score. The quantum operations' SDK names are registered labels. Tests, each fold against what it folds: cli_folds (cmcd over the whole corpus, receipt create against wrap's receipt, verify on the claim, JWP, room and audit corpora and a sealed playlist, audit|serve|quantum against stand-ins); wai-audit tests/fold.rs, wai-quantum-cli tests/wai_fold.rs and joule-moq-room tests/cli_serve.rs against the real programs; cli_mcp's quantum toolset; the daemons' --check (config_check.rs, check.rs). ops.json, mcp.json, the registry export and Studio's actions regenerated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
199 lines
13 KiB
Markdown
199 lines
13 KiB
Markdown
# The operation catalogue
|
|
|
|
Every operation of the WAI toolchain, once. [`ops.json`](ops.json) is written by
|
|
`wai ops export` from the table in `wai-rs/src/catalogue.rs`, and CI fails when the two differ
|
|
(`.github/workflows/wai-catalogue.yml`). Do not edit it by hand: change the table, then
|
|
|
|
```bash
|
|
cd wai/wai-rs && cargo run -q --no-default-features --bin wai -- ops export --out ../catalogue/ops.json
|
|
```
|
|
|
|
[`mcp.json`](mcp.json) (format `wai.mcp-tools/1`) lists the tools `wai mcp` serves, each with its
|
|
name, its operation, its toolset and its input schema, in the order `tools/list` gives them. A test
|
|
of the binary holds it to the tools' table (`wai-rs/src/bin/wai_cli/mcp/tools.rs`), byte for byte;
|
|
change the table, then
|
|
|
|
```bash
|
|
cd wai/wai-rs && WAI_MCP_EXPORT_WRITE=1 cargo test --no-default-features --features mcp --bin wai the_committed_export_is_the_tables
|
|
```
|
|
|
|
`wai breaking` reads both files, the base's against the working tree's (surface `catalogue`,
|
|
category `api`): a change to a stable operation, its flags, its `--json` output or its tool is a
|
|
break; a change to a preview one is owed a changelog line that names it; an operation's id or a flag
|
|
renamed with the old one kept, deprecated, is no break, and removing that old one waits for its
|
|
deprecation window ([VERSIONING.md](../VERSIONING.md)).
|
|
|
|
## An operation
|
|
|
|
An operation is named `noun.verb`: lowercase ASCII, a singular noun, and a verb from naming
|
|
rule N3's closed list (create, list, show, update, delete, check, verify, run, build, export,
|
|
import, start, stop, join, leave, grant, invite, revoke, rotate, tail, search, test, load, encode,
|
|
decode, inspect, wrap, unwrap, fetch, generate, promote, rollback, lock, upgrade, setup, guide,
|
|
stream, upscale, tonemap, doctor), never a near-synonym (`get`, `describe` and `info` are `show`; `keygen`, `init` and
|
|
`new` are `create`; `up` is `start`, as in `wai dev`). A command a person already types keeps its spelling as the operation's
|
|
command line: `wai hello` is `toolchain.test`, `wai stage refine` is `stage.encode`.
|
|
|
|
The list as approved with WAI toolchain v1 ended at `stream`. Two verbs joined it after the wai
|
|
0.4.0 release, with `media.upscale` and `media.tonemap`: `upscale` and `tonemap`. Each names an
|
|
exact derivation, an output any verifier recomputes bit for bit from the input and the parameters
|
|
its record names (extensions/exact-upscale.md, extensions/exact-tonemap.md), and no approved verb
|
|
names that: `encode` and `decode` run a codec, and `generate` makes media from a description. One more joined
|
|
with `toolchain.doctor`: `doctor` says what state a machine is in and what to do about each thing
|
|
it finds, where `check` and `verify` hold something named on the command line to a rule. A verb
|
|
joins the list the same way: in `VERBS` (wai-rs/src/catalogue.rs), this paragraph and the
|
|
list above. The doors' check (`scripts/check-wai-ops-doors.py`) keeps no list of its own: it
|
|
reads `VERBS` and `NEAR_SYNONYMS` from that file, and a test of the catalogue holds this
|
|
paragraph's lists to them.
|
|
|
|
An entry (format `wai.ops/1`) carries:
|
|
|
|
| Member | Meaning |
|
|
|---|---|
|
|
| `id` | `noun.verb` |
|
|
| `summary` | One line, for help, docs and the search |
|
|
| `cli`, `aliases` | The command line today, and other spellings; every operation also answers to `wai <noun> <verb>` |
|
|
| `usage` | The synopsis |
|
|
| `placement` | `local`, `client` (on this machine, against a service it names), `service` or `both` |
|
|
| `effect` | `reads`, `runs`, `writes-project`, `writes-target` or `destructive` |
|
|
| `dry_run` | Whether it takes `--dry-run`: every operation whose effect is not `reads` |
|
|
| `confirm` | When it waits for `--yes`: `never`, `when-replacing-an-unnamed-file`, `when-replacing-a-file`, `when-changing-the-target-or-replacing-a-file` or `always` |
|
|
| `route` | Its HTTP method and path, for an operation that runs on a service |
|
|
| `toolset` | `core`, `dev`, `app`, `quantum` or `maintainer` |
|
|
| `stability` | `stable`, `preview` or `internal` |
|
|
| `input`, `output`, `stream` | JSON Schemas: its arguments (each with the flag or position that gives it), the `data` of its `--json` envelope, and each line of a streaming operation |
|
|
| `since`, `deprecated` | The toolchain version that first carries it; its replacement, once renamed |
|
|
| `receipt` | Whether it writes a signed receipt or record that a `verify` operation checks |
|
|
| `needs` | The build features it needs (`all` or `any` of them) |
|
|
| `names` | Its name in each door |
|
|
|
|
## One name in every door
|
|
|
|
| Door | `envelope.inspect` | Held by |
|
|
|---|---|---|
|
|
| CLI | `wai inspect`, `wai envelope inspect` | the `wai` binary's tests (`tests/cli_ops.rs`) |
|
|
| MCP | `envelope_inspect` | `scripts/check-wai-ops-doors.py` |
|
|
| HTTP API | `operationId: envelope.inspect` | `scripts/check-wai-ops-doors.py` |
|
|
| C | `wai_envelope_inspect` | `scripts/check-wai-ops-doors.py` |
|
|
| Rust | `wai::envelope::inspect` | |
|
|
| JavaScript, Swift, Kotlin | `wai.envelope.inspect` (Swift and Kotlin: `WaiEnvelope.inspect`) | `scripts/check-wai-ops-doors.py` (Swift, Kotlin) |
|
|
|
|
A door that does not carry an operation yet is reported as such by the check; a door that
|
|
names one differently fails it. In the C header and the native sinks, a name is an operation's
|
|
when its noun is a catalogue noun and its verb an operation verb; the codec, envelope and sink
|
|
functions that are not operations are library API.
|
|
|
|
## The service an operation acts on: `--target`
|
|
|
|
`--target` is one input wherever it is taken (`catalogue::TARGET`, which a test of the catalogue
|
|
holds every such input to), and only on an operation placed off this machine: the service the
|
|
operation acts on, named by a target's name or by its `http://` or `https://` address. An
|
|
operation that needs a service and is given none takes the target `wai target use` chose; one for
|
|
which a service is optional (`wai enrolment create`, which writes a file without one) never does.
|
|
|
|
| What | Command | Operation |
|
|
|---|---|---|
|
|
| Keep a name for an address, in the project's `wai.json` (`targets`) or in your own list; `--read-only` refuses every change | `wai target add <name> --url <URL> [--read-only] [--user]` | `target.create` |
|
|
| The target taken where none is named | `wai target use <name> \| --none` | `target.update` |
|
|
| Every target, where it is kept, and whether a key is kept for it | `wai target list` | `target.list` |
|
|
| Remove one | `wai target remove <name> [--user]` | `target.delete` |
|
|
| Keep the key a service takes, read from standard input, for its origin | `wai auth login --url <URL> [--store keychain\|file]` | `credential.create` |
|
|
| The origins a key is kept for, never a key | `wai auth status` | `credential.list` |
|
|
| Remove a kept key | `wai auth logout --url <URL>` | `credential.delete` |
|
|
|
|
`--target local` is the development room on this machine: the room service of the stack `wai dev`
|
|
runs from the directory a command runs in, found by its record (`.wai/dev/stack.json`) and asked
|
|
first whether it is that stack (exit 5, `stack-not-found`, when none is recorded; exit 6,
|
|
`stack-stale`, when the stack recorded there is not running). `wai room show --target local` reads
|
|
its room, and `wai room grant --target local` asks it for a grant, waiting for `--yes` as any change
|
|
does.
|
|
|
|
A target is never kept with a key, and `wai.json` refuses a target's member that is a key's by its
|
|
name. A key is kept outside the project, for its origin: in the login keychain on macOS, else in a
|
|
file of the configuration directory (`$WAI_CONFIG_DIR`, `$XDG_CONFIG_HOME/wai` or `~/.config/wai`)
|
|
that only its owner reads. `WAI_TOKEN`, when set, is sent instead of a kept key. A key goes as
|
|
`Authorization: Bearer`, over `https://` or over `http://` to this machine alone (exit 3,
|
|
`key-over-plaintext`, otherwise), and is never printed, put in a plan, a log or an error: what a
|
|
service answers is shown with any key it repeats replaced by `<key>`.
|
|
|
|
An operation of a service's API (one with a `route`) answers on the command line to its mechanical
|
|
form, which sends its request to its route under the target's address: `wai room show --target
|
|
staging` is `GET <staging's address>/room`. `--query <name>=<value>` adds a query parameter and
|
|
`--body <json>|@<file>|-` a request's body, as the service's API document states them. The
|
|
service's answer is the envelope's `data` (`target`, `request`, `status`, `body`, and `key`: where
|
|
the key came from, `WAI_TOKEN` or `kept`, or null), and a refusal is an exit: 401 or 403 is 3, 404 is 5,
|
|
400, 413, 415 or 422 is 2, 409 or 410 is 1, 429, 502, 503 or 504 is 6, any other 7. A change waits for
|
|
`--yes`, a dry run names the request and sends nothing, and a read-only target refuses it (exit 3,
|
|
`target-read-only`) before anything is sent. A name no list holds is exit 5, `target-not-found`.
|
|
|
|
`wai mcp --target <name|url>` serves the same operations as tools, each sent to that target alone:
|
|
those that read it always, those that change it where the server may (a target on this machine, or
|
|
another with `--allow-write`; never with `--read-only` or to a read-only target). They are the
|
|
target's tools, not a toolset's: an entry's `mcp` (and the export's `doors.mcp`) says whether a
|
|
toolset serves it. The catalogue itself is two of the `core` tools: `ops_search` (`ops.search`),
|
|
the operations that match a task, and `ops_show` (`ops.show`), one operation's entry, with whether
|
|
the server's build holds it.
|
|
|
|
**A build that holds every operation.** `--features full` (wai-rs/Cargo.toml) names each feature an
|
|
operation's `needs` names, and where an operation needs any one of several, the one that needs no
|
|
system library: `cargo install --features full` holds every command. The catalogue's tests hold the
|
|
list to the table both ways (an operation a build with it does not hold, and a feature in it that no
|
|
operation needs, each fail them), and wai-catalogue.yml runs the command line's tests in that build.
|
|
|
|
**Folds: another program of the toolchain, through `wai`.** An operation whose behaviour is a program
|
|
of the toolchain with a command line of its own runs that program as itself: `audit.create`,
|
|
`audit.check` and `audit.verify` are `wai-audit report|check|verify`, `service.start` (`wai serve <role>`) is the role's
|
|
program `wai-<role>` started from its configuration (with `--check`, the program reads it and starts
|
|
nothing), and the `quantum` operations are `wai-quantum`'s verbs, which are also the tools of the
|
|
`quantum` toolset, each answered by `wai-quantum mcp`. What such an operation prints and its exit
|
|
status are the program's; the program is the flag its entry names, its `WAI_<NAME>_BIN` variable,
|
|
the program beside `wai`, or on `PATH`, and one that is not there is exit 5, `program-not-found`.
|
|
`wai quantum` reaches only the verbs the catalogue lists: any other is exit 5,
|
|
`operation-not-found`. `cmcd.encode`, `cmcd.decode` and `cmcd.verify` are the delivery-telemetry
|
|
corpus's tool compiled into `wai`, the same code `wai_telemetry` runs; `score.build` and
|
|
`score.decode` also answer to `wai media score build|render`.
|
|
|
|
## Agent rules
|
|
|
|
Every command of the catalogue keeps them.
|
|
|
|
| Exit | Meaning |
|
|
|---|---|
|
|
| 0 | Done; every check held |
|
|
| 1 | Ran, and a check failed |
|
|
| 2 | Usage error or invalid input |
|
|
| 3 | Authentication or permission |
|
|
| 4 | Confirmation required; nothing changed |
|
|
| 5 | Not found (file, target, room, operation, or a build feature) |
|
|
| 6 | Target unavailable; safe to retry |
|
|
| 7 | Internal error |
|
|
|
|
With `--json`, stdout holds one envelope and logs stay on stderr; without it the output is text,
|
|
on a terminal or not. One module holds these rules for every command
|
|
(`wai-rs/src/bin/wai_cli/dx/envelope.rs`).
|
|
|
|
```json
|
|
{ "wai": "envelope/1", "op": "envelope.wrap", "ok": false, "exit": 4,
|
|
"error": { "code": "confirmation-required", "message": "out.wai exists, and the command line did not name it as the output (-o); nothing was changed",
|
|
"hint": "read the proposed changes, then run the confirming command", "retryable": false },
|
|
"proposed": [ { "replace": "out.wai" } ],
|
|
"confirm": "wai wrap wai.text.zstd p.bin --yes" }
|
|
```
|
|
|
|
A success carries `data`: the command's own JSON where it has one, `{"text": ...}` otherwise.
|
|
A failure carries its `exit`; a check that failed (exit 1) carries both `error` and `data`. A dry run adds `"dry_run": true`
|
|
and the `plan` of what it would write, and of each request it would send to a service it names
|
|
(a fleet service), none of them sent. A check an operation could not run, because a tool, a checkout
|
|
or a build feature it needs was not found, says `not checked` and is never counted as holding: with
|
|
no check failed the exit is 5, with `error.code` `not-checked` and the report in `data`. `--yes` is never implied; off a terminal, or with
|
|
`--no-input`, a change that waits for it exits 4. `--confirm` is a deprecated spelling of `--yes`
|
|
that does the same; the export lists the agent flags (`agent_flags`) with it as a deprecated
|
|
alias.
|
|
|
|
`--fields a,b.c`, with `--json`, keeps only those members of `data`: each a member's name, or a
|
|
dotted path to a member within one (`body.room`; a path may begin `data.`), of each item when
|
|
`data` is a list. A member that is not there is left out. The envelope's own members, `wai`, `op`,
|
|
`ok`, `error`, `exit`, `dry_run`, `plan`, `proposed` and `confirm`, are always kept, whatever is
|
|
named: `--fields` never hides whether an operation held or why it did not. A stream's lines are
|
|
written as the operation writes them. Without `--json`, or without a value, it is a usage error.
|
|
|
|
`wai` sends nothing off your machine unless you name a remote service.
|