Create on the toolchain's names: wai-app (a library), wai create --from app.oui, wai app check, wai mcp --toolset app, wai dev --show #508

Merged
dcharlot merged 14 commits from wai/create-2 into main 2026-10-27 10:15:14 -04:00
Owner

Replaces #501. Create on the toolchain names approved on 2026-10-27. It is stacked linearly on #505 (wai/dx-agent-mcp-2), so #505 merges first.

What is in it

Commits 1 to 9 are #501's nine commits cherry-picked unchanged. The one conflict was the CHANGELOG. Commits 10 to 12 adopt the names.

wai-ui becomes the library wai-app, with no binary. wai/wai-app, lib wai_app, has no [[bin]] and no cli feature. wai, built with its new feature app, is its command line and its MCP server. Its files are served as wai-app-*, and the WebAssembly package is wai_app.

Create's export is wai create <dir> --from app.oui (app.export):

  • It writes an ordinary WAI project. wai.json comes from project::render, the one writer of project files, which DX-A's minimal now calls; a test holds render to three templates' own files byte for byte. The file names the program ("app": "app.oui") and the room wai dev runs for it: dev.mode is room, watch or show, with dev.watch for a watch room and dev.audience for a show.
  • The app's files come from wai_app::export: app.oui in canonical form, index.html, README.md, AGENTS.md, .gitignore, vendor.json, and vendor/.
  • The runtime is copied from a Create runtime, given by --runtime DIR, $WAI_APP_RUNTIME, or share/wai/app beside wai. Each file is checked against the runtime's listing.
  • The export no longer writes app.json, room.toml, relay.toml, package.json, check.mjs or serve.mjs. wai dev runs the project, wai app check checks it, and no Node is needed.
  • A template's project and an exported one share their shape. tests/cli_app.rs holds both to it.

Templates and exports are Apache-2.0.

  • Every project wai create writes, from a template or from an app, carries LICENSE, the Apache-2.0 text held in the binary. --list --json lists it.
  • Every example's README ends with a licence line, and the export's README has one.

wai app guide and wai app check [<dir> | <app.oui>] [--json] (app.guide, app.check):

  • They check the program against the registry. In a project they also check the room wai.json names against the app's own, and vendor/ against vendor.json.
  • On failure they exit 1 and name each failure. Off a terminal they answer in the JSON envelope.

wai mcp --toolset app:

  • Tools: app_guide, app_check, app_stream and app_export.
  • The bridge on 127.0.0.1 starts when the toolset is served and the server is not read-only.
  • app_export writes inside the project directory alone, through the same code as wai create --from.
  • setup-agent --toolset takes app in a build that serves it.

wai dev --show [--audience N] (or "mode": "show" in wai.json): a room with co-performance. The room gets its [co] block, and the relay gets [floor] with the room's clock key, read from the relay lines.

wai dev's front never serves a dot-path. It now refuses every path segment that starts with a dot. Before this change, a project served at / ("site": ".", as every room template has) exposed /.wai/dev/room-keys.toml. .oui is now served as text.

The page. Export hands over app.oui and the command that makes it a project. The ZIP writer and the page's in-WebAssembly export are gone. For the coding agent, the page names wai mcp --toolset app.

The browser end-to-end test (wai/wai-app/e2e/run.sh, on the macOS host):

  • The Create page is served by wai dev --show.
  • wai create --from builds the exported project, and wai app check checks it, including the negative controls.
  • wai dev runs the exported project's own room. There a host joins, chats and opens a poll; a viewer reads the chat and votes; both pages show the result the room's clock signed.
  • The visitor's own model is called with their key alone.
  • wai mcp --toolset app streams into the page through its bridge, and app_export writes the project.

Checks

Each check ran on the Studio (macOS, plain rb). The Framework box's disk was below rb's 40 GiB floor for the whole of this branch, and only the Studio could host the browser test anyway.

Check Result
wai/wai-app: cargo test --locked 15 passed
wai/wai-app: cargo clippy --locked --all-targets -- -D warnings clean
wai/wai-app: the same clippy for wasm32 (--no-default-features --features web) clean
wai/wai-rs, feature app: --bin wai --test cli_app --test cli_mcp --test cli_setup_agent 19 + 5 + 10 + 6 passed
wai/wai-rs, feature mcp: --bin wai --test cli_mcp --test cli_setup_agent 19 + 10 + 6 passed
wai/wai-rs, feature quickstart: --bin wai --test floor --test cli_dx (templates with LICENSE, held byte for byte to the examples) 20 + 2 + 3 passed
wai/wai-rs: --lib ops:: 1 passed
wai/wai-rs clippy (--bin wai --tests with app, with mcp, with quickstart, with no feature), filtered to the touched files none left
scripts/check-lockfiles.sh 54 lockfiles, all current (the wai-rs lock gains wai-app and three joule-ui crates; nothing else)
node --test web/web.test.mjs 5 passed
python3 -I joule-ui/conformance/lang_verify.py (local); --mutations 0 disagreements; 13 mutations, 0 not refused
The browser end-to-end: wai/wai-app/e2e/run.sh, in Chrome 156 under memguard 36 passed, 0 failed (scenarios create, built, refused, own, agent)
The repo checks (check-tests-in-ci, check-workflow-concurrency, check-spec-refs, check-wai-section-refs, check-no-vanity-metrics, test-public-text-checks, check-comparative-prose, check-orphan-sources) local; all pass
check-public-names.sh on the changed files; the commit messages and this body local; clean
wfsteps.py HEAD origin/main <#501 head> <#505 head> <this branch's CI commit>; YAML parse 0 problems; parses

Falsifications

Each was run with the branch committed: break one thing, run the guard on the Studio, then restore with git checkout --.

Broken Guard Result
tool app.export named create.export (the old create_export) cli_app::create_through_the_app_toolset failed: left: [..., "create_export"] right: [..., "app_export"]
wai create writes no LICENSE --bin wai (every_template_writes_a_project_that_reads) failed
wai app check stops holding dev.mode to the app's room cli_app::the_check_refuses_a_project_that_is_not_whole failed
wai dev's front serves dot-paths again --bin wai (the_origin_serves_the_page_and_nothing_outside_its_roots) failed: /.wai/dev/room-keys.toml: 200

The misnamed MCP tool and misnamed operationId of the core and dev toolsets are #505's.

Not done

  • The quickstart's wai is built without app, and the archive carries no Create runtime (share/wai/app). So wai create --from needs a source build of wai with --features app and --runtime DIR (a runtime laid out by web/runtime.mjs). Adding both to the archive is a follow-up for the release pipeline.
  • No wai build and no dist/. check.mjs used to write dist/; nothing replaces that yet.
  • No test/ directory in the export. Template projects carry none either; spec conflict 15 lists one.
  • wai.json has no room member yet. The room lives in dev, which is what wai dev reads.
  • The quantum toolset is not mounted (see #505).

🤖 Generated with Claude Code

Replaces #501. Create on the toolchain names approved on 2026-10-27. It is stacked linearly on #505 (`wai/dx-agent-mcp-2`), so #505 merges first. ## What is in it Commits 1 to 9 are #501's nine commits cherry-picked unchanged. The one conflict was the CHANGELOG. Commits 10 to 12 adopt the names. **`wai-ui` becomes the library `wai-app`, with no binary.** `wai/wai-app`, lib `wai_app`, has no `[[bin]]` and no `cli` feature. `wai`, built with its new feature `app`, is its command line and its MCP server. Its files are served as `wai-app-*`, and the WebAssembly package is `wai_app`. **Create's export is `wai create <dir> --from app.oui`** (`app.export`): - It writes an ordinary WAI project. `wai.json` comes from `project::render`, the one writer of project files, which DX-A's `minimal` now calls; a test holds `render` to three templates' own files byte for byte. The file names the program (`"app": "app.oui"`) and the room `wai dev` runs for it: `dev.mode` is `room`, `watch` or `show`, with `dev.watch` for a watch room and `dev.audience` for a show. - The app's files come from `wai_app::export`: `app.oui` in canonical form, `index.html`, `README.md`, `AGENTS.md`, `.gitignore`, `vendor.json`, and `vendor/`. - The runtime is copied from a Create runtime, given by `--runtime DIR`, `$WAI_APP_RUNTIME`, or `share/wai/app` beside `wai`. Each file is checked against the runtime's listing. - The export no longer writes `app.json`, `room.toml`, `relay.toml`, `package.json`, `check.mjs` or `serve.mjs`. `wai dev` runs the project, `wai app check` checks it, and no Node is needed. - A template's project and an exported one share their shape. `tests/cli_app.rs` holds both to it. **Templates and exports are Apache-2.0.** - Every project `wai create` writes, from a template or from an app, carries `LICENSE`, the Apache-2.0 text held in the binary. `--list --json` lists it. - Every example's README ends with a licence line, and the export's README has one. **`wai app guide` and `wai app check [<dir> | <app.oui>] [--json]`** (`app.guide`, `app.check`): - They check the program against the registry. In a project they also check the room `wai.json` names against the app's own, and `vendor/` against `vendor.json`. - On failure they exit 1 and name each failure. Off a terminal they answer in the JSON envelope. **`wai mcp --toolset app`:** - Tools: `app_guide`, `app_check`, `app_stream` and `app_export`. - The bridge on 127.0.0.1 starts when the toolset is served and the server is not read-only. - `app_export` writes inside the project directory alone, through the same code as `wai create --from`. - `setup-agent --toolset` takes `app` in a build that serves it. **`wai dev --show [--audience N]`** (or `"mode": "show"` in `wai.json`): a room with co-performance. The room gets its `[co]` block, and the relay gets `[floor]` with the room's clock key, read from the relay lines. **`wai dev`'s front never serves a dot-path.** It now refuses every path segment that starts with a dot. Before this change, a project served at `/` (`"site": "."`, as every room template has) exposed `/.wai/dev/room-keys.toml`. `.oui` is now served as text. **The page.** Export hands over `app.oui` and the command that makes it a project. The ZIP writer and the page's in-WebAssembly export are gone. For the coding agent, the page names `wai mcp --toolset app`. **The browser end-to-end test** (`wai/wai-app/e2e/run.sh`, on the macOS host): - The Create page is served by `wai dev --show`. - `wai create --from` builds the exported project, and `wai app check` checks it, including the negative controls. - `wai dev` runs the exported project's own room. There a host joins, chats and opens a poll; a viewer reads the chat and votes; both pages show the result the room's clock signed. - The visitor's own model is called with their key alone. - `wai mcp --toolset app` streams into the page through its bridge, and `app_export` writes the project. ## Checks Each check ran on the Studio (macOS, plain `rb`). The Framework box's disk was below rb's 40 GiB floor for the whole of this branch, and only the Studio could host the browser test anyway. | Check | Result | |---|---| | `wai/wai-app`: `cargo test --locked` | 15 passed | | `wai/wai-app`: `cargo clippy --locked --all-targets -- -D warnings` | clean | | `wai/wai-app`: the same clippy for wasm32 (`--no-default-features --features web`) | clean | | `wai/wai-rs`, feature `app`: `--bin wai --test cli_app --test cli_mcp --test cli_setup_agent` | 19 + 5 + 10 + 6 passed | | `wai/wai-rs`, feature `mcp`: `--bin wai --test cli_mcp --test cli_setup_agent` | 19 + 10 + 6 passed | | `wai/wai-rs`, feature `quickstart`: `--bin wai --test floor --test cli_dx` (templates with `LICENSE`, held byte for byte to the examples) | 20 + 2 + 3 passed | | `wai/wai-rs`: `--lib ops::` | 1 passed | | `wai/wai-rs` clippy (`--bin wai --tests` with `app`, with `mcp`, with `quickstart`, with no feature), filtered to the touched files | none left | | `scripts/check-lockfiles.sh` | 54 lockfiles, all current (the wai-rs lock gains wai-app and three joule-ui crates; nothing else) | | `node --test web/web.test.mjs` | 5 passed | | `python3 -I joule-ui/conformance/lang_verify.py` (local); `--mutations` | 0 disagreements; 13 mutations, 0 not refused | | **The browser end-to-end**: `wai/wai-app/e2e/run.sh`, in Chrome 156 under memguard | **36 passed, 0 failed** (scenarios create, built, refused, own, agent) | | The repo checks (`check-tests-in-ci`, `check-workflow-concurrency`, `check-spec-refs`, `check-wai-section-refs`, `check-no-vanity-metrics`, `test-public-text-checks`, `check-comparative-prose`, `check-orphan-sources`) | local; all pass | | `check-public-names.sh` on the changed files; the commit messages and this body | local; clean | | `wfsteps.py HEAD origin/main <#501 head> <#505 head> <this branch's CI commit>`; YAML parse | 0 problems; parses | ## Falsifications Each was run with the branch committed: break one thing, run the guard on the Studio, then restore with `git checkout --`. | Broken | Guard | Result | |---|---|---| | tool `app.export` named `create.export` (the old `create_export`) | `cli_app::create_through_the_app_toolset` | failed: `left: [..., "create_export"] right: [..., "app_export"]` | | `wai create` writes no `LICENSE` | `--bin wai` (`every_template_writes_a_project_that_reads`) | failed | | `wai app check` stops holding `dev.mode` to the app's room | `cli_app::the_check_refuses_a_project_that_is_not_whole` | failed | | `wai dev`'s front serves dot-paths again | `--bin wai` (`the_origin_serves_the_page_and_nothing_outside_its_roots`) | failed: `/.wai/dev/room-keys.toml: 200` | The misnamed MCP tool and misnamed `operationId` of the core and dev toolsets are #505's. ## Not done - **The quickstart's `wai` is built without `app`, and the archive carries no Create runtime (`share/wai/app`).** So `wai create --from` needs a source build of `wai` with `--features app` and `--runtime DIR` (a runtime laid out by `web/runtime.mjs`). Adding both to the archive is a follow-up for the release pipeline. - **No `wai build` and no `dist/`.** `check.mjs` used to write `dist/`; nothing replaces that yet. - **No `test/` directory in the export.** Template projects carry none either; spec conflict 15 lists one. - **`wai.json` has no `room` member yet.** The room lives in `dev`, which is what `wai dev` reads. - **The `quantum` toolset is not mounted** (see #505). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
`wai mcp` (the feature `mcp`) is a Model Context Protocol server (2025-06-18) on
standard input and output. Its tools, in one table (src/bin/wai_cli/mcp/tools.rs):
inspect an envelope or a package; list and describe registered capabilities; verify a
delivery receipt, a claim with the context the tool takes, a live-room session and a
stream audit bundle, each answering with the verifier's verdict and reason code;
package a media file under `wai wrap`'s rules, inside the project directory only; list
and run a conformance corpus's independent verifier; search the specification; and,
marked development only, drive a development room on loopback (`joule-moq-room dev`):
start it, mint grants for test principals (any service whose address is not a loopback
address is refused before a connection is made), join and publish as them, read the
session, stop it. Each tool carries safety hints; `--read-only` offers only those that
read or run a verifier.

`wai setup-agent` writes AGENTS.md and CLAUDE.md (which imports it) and registers the
server in the project's MCP configuration files by their documented formats. A file
that exists is changed only after its diff is shown and confirmed (asked on a terminal,
or --confirm; otherwise exit 4 with every diff and the confirming command), --dry-run
writes nothing, nothing outside the project directory is written, and its output is
JSON off a terminal.

Both are reached through one table of verbs in wai.rs, so a name is one line. `wrap`
returns its printed lines and its facts, which the packaging tool reads.

tests/cli_mcp.rs drives the binary with an MCP client: every tool, and the verifiers
agreeing vector by vector with jwp-conformance, claim-conformance,
live-conformance/rooms and live-conformance/audit. tests/cli_setup_agent.rs runs the
command in scratch projects, fresh and with files that exist.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
`joule-moq-room dev` (src/dev.rs) runs the relay and the room service in one process
on loopback, with keys made at start and kept only in memory, media held to no
receipts and rate limits open, and says on standard error that it is for development
only. It answers JSON control lines: join (a test principal enters with its grant and
a proof, publishes audio and video, and the answer waits for the clock's join and
publishes), leave, session (the room as live-rooms §9 gives it to a verifier) and
stop. Its log goes to standard error. tokio's io-std feature, for its standard input
and output.

openapi.json describes every route of the service in each of its modes: requests,
answers and statuses. tests/openapi_contract.rs holds it to the code: the routes the
routers match are exactly its operations; each status it lists for an operation is one
the operation's handlers return, and each status they return is listed; and the
service, run beside a relay in each mode (a plain room, end-to-end encryption,
admission by age, co-performance, a watch room, a remote desktop room, a conversation,
calls, and without its relay), answers every operation with a status it lists.

tests/mcp_dev_room.rs builds `wai` with the feature `mcp` in a target directory of its
own and drives `wai mcp` with an MCP client: a development room started, two test
principals granted, joined and publishing, the session verified, a changed record
refused, a leave verified, and a grant from a service off the machine refused.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-conformance runs tests/cli_mcp.rs and tests/cli_setup_agent.rs, with the binary's
unit tests, under the feature `mcp` on each leg. The room service's workflow runs every
target, and now says what tests/openapi_contract.rs and tests/mcp_dev_room.rs hold.
wai/README.md says how a project is set up for a coding agent and what `wai mcp`
offers; CHANGELOG records both commands and the API description.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The two verbs join the one table, dx::VERBS, beside hello, create, dev and
verify; wai.rs keeps no second command table. A verb ends either as a check
(0 held, 1 did not, 2 usage) or with an exit status of the toolchain's table,
which setup-agent uses.

wai mcp (agent.mcp): each tool is an operation of the catalogue, named by it
with `_` for the dot, and nothing else names it. The tools come in toolsets,
chosen with --toolset (core when none is named):
- core: envelope_inspect, registry_list, registry_show, receipt_verify,
  package_build, conformance_list, conformance_run, docs_search;
- dev: dev_start, dev_stop, room_grant, room_join, room_leave, room_session,
  on the target local alone (a target named must be it).
receipt_verify takes the four kinds the verify tools took one each (delivery,
claim, room_session, audit_bundle), by `kind` or read from the arguments, and
answers with the kind beside the verifier's verdict. tools/list gives each
tool's operation and toolset in its _meta. The development room's program is
found as wai dev finds it: beside wai, then on PATH. envelope_inspect counts
what this build decodes as wai inspect does, the floor included.

wai setup-agent (agent.setup): AGENTS.md always; a CLAUDE.md only where the
project has one, which gains an import of AGENTS.md. --toolset registers the
server with those toolsets. Off a terminal it answers in the toolchain's JSON
envelope (envelope/1: op, ok, error {code, message, hint, retryable}, result,
and on exit 4 the proposed changes and the confirming command), with the
table's exit statuses: 2 usage, 3 permission, 4 confirmation required, 5 not
found, 7 another I/O error.

wai::ops holds the rule operation names keep: noun.verb, lowercase letters,
the verb from a closed list, and the few names the catalogue gives as they are
(room.session among them). The quickstart's wai holds `mcp`, so the server
setup-agent registers is in the archive's binary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
openapi.json names its 40 operations as the toolchain's catalogue does,
noun.verb: room.show (GET /room) and room.grant (POST /grant) as the catalogue
gives them, and the rest by its rule (service.show and service.check, the
health; admission.show; mls.tail, mls.import, mls.update; performance.list
and .show, schedule.create, handover.create, window.create, fidelity.create;
time.show, source.fetch, watchchallenge.create, watch.tail, watch.show,
watch.join, watch.update; control.grant, remote.show, remote.verify;
conversation.show, .join, .tail, .import, .update, .leave,
conversationchallenge.create, message.create, acknowledgement.create,
member.delete; callchallenge.create, call.create, call.invite, inbox.show,
answer.create, call.show). The paths stay as the service serves them. The
description lists the service behind wai dev's front (/room-api) as a server.

tests/openapi_contract.rs gives each operation its name beside its handlers and
checks that the description names it so, that each name keeps wai::ops's rule
and names one operation, and that room.show and room.grant are the routes the
catalogue gives them. tests/mcp_dev_room.rs drives `wai mcp --toolset core,dev`
under the new tool names and checks that the tool room_grant and POST /grant
are the one operation room.grant, and that no other tool shares an API
operation's name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-conformance runs `--lib ops::` beside the mcp and setup-agent tests, and
its comment says what they now hold (the tool list as operations, toolsets,
the dev tools' target, setup-agent's envelope and exit statuses). The room
service's workflow comment says the contract test checks every operationId.
wai/README.md gives the toolsets and their tools, and setup-agent's CLAUDE.md
and --toolset; the room service's README the operationIds; the CHANGELOG
entry is rewritten for the names.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai mcp: the tools table's test module after every item (clippy items_after_test_module)
All checks were successful
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 8m42s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 27s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 38s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m52s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m5s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m13s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 7s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m46s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m55s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 7m0s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m16s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 24s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m35s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m21s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m24s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m54s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 1m41s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m37s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 36s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m11s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 9m20s
wai-ledger service / service · macos (pull_request) Successful in 1m28s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 27m49s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h9m8s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 15m28s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 18m18s
wai-pack / wai-pack · macos (pull_request) Successful in 4m44s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 4m52s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 10m38s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 20m17s
bff1736e36
Co-Authored-By: Claude Opus 5.5 <[email protected]>
joule-ui takes in OpenUI Lang 1.0 the way it takes in A2UI: a model writes a
surface as a program, one widget a line, and joule-ui-lang builds a widget tree
against the host's registry as the program streams. After every chunk a snapshot
holds the tree as far as it can be built, each widget checked by joule-ui's own
validate, and every error with its source line and reason code. State, queries,
operators, conditionals, built-in functions and sequences of actions are parsed
and refused not-declarative. A canonical writer turns a tree back into the
language; it parses back to the same tree.

- joule-ui-core: WidgetSchema::positional, the order a positional call passes
  props in (SPEC §3); absent from the wire form when undeclared.
- joule-ui-interaction: begin_interaction and Pending::finish, the lifecycle's
  three phases in two steps for a host whose handler is asynchronous (SPEC §6);
  run_interaction is built on them and seals what it sealed before.
- conformance/lang/v1: L1 statements, L2 ingest, L3 streaming, L4 the canonical
  form, L5 refusals, with an independent Python verifier written from §11.
- docs/create.md: the design of Create.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- a joule-ui registry of WAI widgets: App, Room, WatchTogether, Show, Player, Chat,
  Poll, Participants, Receipts, EnergyMeter, Text; each room kind accepts only the
  widgets its room service keeps (a watch room holds no Chat and no Poll), so a line
  that asks for more is refused disallowed-child at its line;
- WAI's own rules on an app (one room, a poll's options, a show's audience, a watch
  room's source) and the room an app needs;
- the guide a model writes against, made from the registry;
- export: the one writer of a starter project (the program, its tree, the room
  service's configuration, the page, a check that is its build, a development front,
  README, AGENTS.md, the runtime under vendor/; no key);
- the page's WebAssembly surface: the program streamed into snapshots, and every
  action sealed into the page's hash-chained log through joule-ui-interaction;
- wai-ui mcp: an MCP server and a loopback bridge, so a person's own coding agent
  drives Create;
- web/: the streaming renderer (keyed, so a joined room survives the next chunk), the
  components over the room client in a same-origin frame, the Create page with its
  three model sources (the visitor's own model and key, their coding agent, a recorded
  stream), the exported app's page, and the runtime layout;
- e2e/: Create in a browser against a real room service and relay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- runtime.mjs gives every runtime file a unique served name (wai-ui-<name>,
  wai-ui-room-<name>.js, wai_ui_room_moq, wai_ui_room_live): the WAI site fingerprints
  assets keyed by basename, and an export's vendor/ carries the same layout;
- a room widget takes the room service for its kind (data-service-live, -watch,
  -show) when the page names one;
- WAI's value rules (a poll's options and seconds, a show's audience, a watch room's
  source) wait for a pending statement to complete, as the line language's own errors
  do: a poll's `seconds` reads 2 before 20, and the poll no longer leaves the page for
  that chunk (found by the end-to-end run; a unit test now streams every recording a
  character at a time and requires that no widget, once shown, goes);
- .github/workflows/wai-ui.yml: tests, clippy and the wasm32 surface, the line
  language's verifier and its mutations, the page modules (linux); Create in the
  browser (macos);
- the e2e drives a WAI site build with --site;
- wai-ui cites joule-ui's spec by its file (joule-ui/SPEC.md §N).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai/wai-ui becomes wai/wai-app, the library `wai_app`, with no binary and no `cli`
feature: `wai`, built with its feature `app`, is its command line and its MCP
server. Its served files are named wai-app-* (the WebAssembly package wai_app),
the recordings wai-app-*.json.

- export.rs gives the files of a starter project for a program and the facts its
  project file holds (title, summary, `wai dev`'s mode for the app's room, a watch
  room's file, a show's audience); `wai create --from app.oui` writes them, the
  project file and the licence. The export no longer writes app.json, room.toml,
  relay.toml, package.json, check.mjs or serve.mjs: wai.json names the room, `wai
  dev` runs it and `wai app check` checks the project. Its README and AGENTS.md
  say so, and the README its licence.
- runtime.rs reads a Create runtime by its listing (create/wai-app-runtime.json),
  checking each file's SHA-256.
- bridge.rs keeps the bridge on 127.0.0.1 a coding agent streams a program into
  the page through, with a stream helper; the stdio server, its tools and the
  binary's test go (`wai mcp --toolset app` serves them).
- The page's Export hands over app.oui, the program in its canonical form, and the
  command that makes it a project; the ZIP writer and the page's export in
  WebAssembly go. The page names `wai mcp --toolset app` for the coding agent.
- joule-ui/docs/create.md §4 and §5: the export as `wai create --from app.oui`, and
  the agent's tools app_guide, app_check, app_stream and app_export.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The feature `app` links wai-app (with `mcp`):

- `wai create <dir> --from app.oui [--runtime DIR]` (app.export): the app's files
  from wai_app::export, its runtime copied from a Create runtime (the flag,
  $WAI_APP_RUNTIME, or share/wai/app beside wai) and checked against its listing,
  and its wai.json from project::render, the one writer every project file now
  has (`minimal` is a call of it, and a test holds it to three templates' own
  files byte for byte). The project file names the program (`app`) and the room
  `wai dev` runs (`dev.mode` room, watch or show; `dev.watch`; `dev.audience`).
- Every project `wai create` writes, from a template or an app, carries LICENSE
  (Apache-2.0, wai/LICENSE held in the binary); `--list --json` lists it, and each
  example's README names the licence.
- `wai app guide` and `wai app check [<dir> | <app.oui>] [--json]` (app.guide,
  app.check): the program against the registry, and in a project the room wai.json
  names against the app's own and vendor/ against vendor.json; exit 1 with each
  failure named, the JSON envelope off a terminal.
- `wai mcp --toolset app`: app_guide, app_check, app_stream and app_export, a bridge
  on 127.0.0.1 started when the toolset is served and not read-only;
  setup-agent's --toolset takes app.
- project.rs reads `app` and `dev.audience` (a show's alone, 1 to 255) and the mode
  show. `wai dev --show [--audience N]`: the room's [co] block, and the relay's
  [floor] holding the floor to the room's clock (its key read from the relay
  lines). The front refuses any path segment that starts with a dot, so a
  project's .wai/, where the room's keys are, is never served; .oui is served as
  text.
- tests/cli_app.rs (required-features app); the lock gains wai-app and the
  joule-ui crates it builds on, additions only.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- .github/workflows/wai-ui.yml becomes wai-app.yml: the unit job runs wai-app's
  tests, its clippy (native and wasm32) and the line language's verifier; the e2e
  job runs wai/wai-app/e2e/run.sh, which now also reads wai/quickstart/build-web.sh.
- wai-conformance runs tests/cli_app.rs with the feature `app`, and fires on
  wai/wai-app and the joule-ui crates it builds on.
- The e2e (run.sh builds `wai` with `app` in a target directory of its own, and
  the room client `wai dev` serves): the Create page served by `wai dev --show`; the
  show recording renders as it streams; the host joins, chats and opens the poll;
  the sealed log verifies; Export hands over app.oui and the command; `wai create
  --from app.oui` writes the project; `wai app check` passes on it and refuses it
  with its room not its app's, another audience, no room named, a runtime file
  changed or a refused line; `wai dev` in the project runs its own room, its keys in
  .wai/ that the front never serves, where a host and a viewer answer a poll the
  room's clock signs; the refused lines never render; the visitor's own model gets
  their key alone; `wai mcp --toolset app` streams into the page through its bridge
  and app_export writes the same project.
- CHANGELOG: Create as wai-app, `wai create --from app.oui`, `wai app`, the app
  toolset, LICENSE in every project, `wai dev --show`. wai/README.md: the app
  toolset and Create.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
--toolset takes app, and AGENTS.md mentions the app toolset, only in a build with
the feature `app`: a project set up from a build without it is never pointed at a
toolset its wai cannot serve.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-app e2e: the show's audience is the recording's (1)
All checks were successful
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m43s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 32s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m34s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 6s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m27s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m36s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m35s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m21s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m26s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m14s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m38s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 50s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m45s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m26s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m48s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 28m15s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 7m29s
wai-ledger service / service · macos (pull_request) Successful in 1m13s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 22m51s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 8m50s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 22m55s
wai-pack / wai-pack · macos (pull_request) Successful in 3m15s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 17m38s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 11m40s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m55s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 3m10s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m59s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 7m22s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 18m16s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h3m2s
3363058002
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!508
No description provided.