wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 7m22s
--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]>
- .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]>
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]>
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]>
- 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]>
- 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]>
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]>