### One catalogue of operations, the agent rules on every command, and the service binaries named `wai-*`

- **The operation catalogue** (`wai::catalogue`): every operation the toolchain offers, once,
  named `noun.verb` (`envelope.inspect`, `project.create`, `receipt.verify`), the verb from
  naming rule N3's closed list, with its summary, command line, placement, input and output
  JSON Schemas, effect, toolset, stability and the build features it needs. It lists the
  operations that work today, `wai breaking` (`compat.check`), `wai conform`
  (`conformance.run`, `conformance.list`) and the fleet's `wai enrolment create|list` and
  `wai report create|export` (`enrolment.create`, `enrolment.list`, `report.create`,
  `report.export`, each placed on the client, against a fleet service) among them. Each entry
  says when it waits for confirmation (`confirm`). A command a person already types keeps
  its spelling (`wai hello` is `toolchain.test`, `wai stage refine` is `stage.encode`,
  `wai http seal-playlist` is `playlist.lock`). **`wai ops list`**, **`wai ops search
  "<task>"`** (offline, up to five ranked matches), **`wai ops show <id>`** and **`wai ops
  export`**, whose output is [`catalogue/ops.json`](catalogue/ops.json).
- **The command line through it.** A command resolves through the catalogue alone, by the
  spelling it has today (`wai inspect`) or by its id's words (`wai envelope inspect`); help and
  usage come from the catalogue's entries.
- **The agent rules on every command.** Exit codes 0 to 7 (0 done, 1 a check failed, 2 usage,
  3 permission, 4 confirmation required, 5 not found, 6 target unavailable, 7 internal);
  `--json` prints one envelope, `{"wai": "envelope/1", "op", "ok", "data" | "error", "exit"}`,
  from one module that `wai breaking` and `wai conform` share; a command's own JSON (`wai create
  --list`, `wai generate`, `wai score`, `wai stage apply`, `wai dev --check`, `wai breaking`,
  `wai conform`) is now that envelope's `data`. Without `--json` the output is text, on a
  terminal or not. `--dry-run` on every operation that is not
  read-only writes nothing and says what it would write. An operation that would replace a
  file the command line did not name (`out.wai` when `-o` is not given, an earlier
  `wai hello`'s files) asks at a terminal and otherwise exits 4 until `--yes` is given. An
  unknown command exits 5, not 2.
- **One confirmation flag, `--yes`.** `--confirm`, which `wai conform`, `wai setup-agent` and
  the fleet's operations took, is its deprecated spelling: it still works and does the same,
  and `wai --help`, each operation's help and the export (`agent_flags`) say it is deprecated.
  Every confirming command a run prints names `--yes`. The fleet's operations, `wai conform`
  and `wai setup-agent` wait as their entries say: a fleet service changed, or a file that
  exists replaced.
- **The fleet's operations on the same rules**: their JSON is the envelope with `--json` (it was
  also printed whenever standard output was not a terminal), a dry run's `plan` names each file
  and each request to the fleet service, none of them sent, and a confirmation is exit 4 with
  `proposed` and the confirming command. `wai conform` and `wai breaking` print text unless
  `--json` is given, as every command does.
- **The doors held to it** (`.github/workflows/wai-catalogue.yml`): the export is the table;
  `scripts/check-wai-ops-doors.py` holds MCP tool names, the services' OpenAPI operationIds,
  the C header and the Swift and Kotlin sinks' public names to the catalogue. `wai mcp`'s tool
  table is held to it both ways (every tool an operation the catalogue says it serves, in that
  toolset, and every such operation a tool), and so is the room service's OpenAPI document
  (every `operationId` at the catalogue's route, every routed operation described).
- **Renamed to the verb rule (N3)**: the MCP tool `package_build`, which carries a file in an
  envelope as `wai wrap` does, is `envelope_wrap`; `room_session` is `session_show`; the room
  service's challenges are `watch.setup`, `conversation.setup` and `call.setup` (they were
  `watchchallenge.create`, `conversationchallenge.create` and `callchallenge.create`);
  `wai mcp` is the operation `mcp.start`. Create's export is also `wai app export`.
- **Breaking**, intended: the module that held the naming rule is replaced by the catalogue,
  which holds the rule and every name. `api:rust:wai::ops`, `api:rust:wai::ops::VERBS`,
  `api:rust:wai::ops::NAMED_AS_IS`, `api:rust:wai::ops::check_id` and
  `api:rust:wai::ops::mcp_tool_name` are gone; use `wai::catalogue`, its `VERBS`, its rule
  (`findings_of`) and each operation's name in every door (`Op::names`). The names the rule
  once let stand are held to it now, so `NAMED_AS_IS` has no replacement.
- **Breaking**, intended: the room service's three challenges keep their routes and take the
  names the rule gives them, `watch.setup`, `conversation.setup` and `call.setup`, as their
  `operationId`s: `api:openapi:joule-moq-room:GET /watch/challenge`,
  `api:openapi:joule-moq-room:GET /msg/challenge` and
  `api:openapi:joule-moq-room:GET /call/challenge`. A client generated from the document calls
  them by those names; the requests and answers are unchanged.
- **The service binaries are `wai-relay`, `wai-room` and `wai-ingest`**; their crates keep
  their names (`joule-moq-relay`, `joule-moq-room`, `joule-moq-ingest`). `wai dev` and the
  quickstart archive use the new names.
- **Every example is Apache-2.0** and carries `LICENSE`, which `wai create` writes into the
  project.
- `wai` sends nothing off your machine unless you name a remote service.

