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]>
34 lines
2 KiB
Markdown
34 lines
2 KiB
Markdown
# joule-ui line language conformance — v1
|
|
|
|
The pack of SPEC §11.9: the line language (OpenUI Lang 1.0, taken in as joule-ui
|
|
widget trees) against the pack's own library. Regenerate with:
|
|
|
|
```
|
|
cargo run -p joule-ui-lang --bin gen_lang_vectors
|
|
```
|
|
|
|
and verify, from the specification alone, with the independent verifier:
|
|
|
|
```
|
|
python3 -I conformance/lang_verify.py # every case recomputed and compared
|
|
python3 -I conformance/lang_verify.py --mutations # changed vectors are refused
|
|
```
|
|
|
|
`cargo test -p joule-ui-lang --test pack` checks that the committed files are exactly
|
|
what the reference implementation gives.
|
|
|
|
| File | Class | What a conforming ingest reproduces |
|
|
|---|---|---|
|
|
| `library.json` | — | the library: each widget's props, children rule and positional order (written out), and the root widget |
|
|
| `l1-statements.json` | **L1** | each text's statements (name, source line, kind, complete) and whether it ended open |
|
|
| `l2-ingest.json` | **L2** | each text's snapshot at the end of the stream: the tree, its nodes (key, line, statement), the errors (line, statement, code, widget, prop, warning), the unresolved names, the orphans, whether it ended open |
|
|
| `l3-stream.json` | **L3** | each case's snapshot after every chunk and at the end; the end equals the batch parse of the joined chunks |
|
|
| `l4-write.json` | **L4** | each tree's canonical text, which parses back to the tree |
|
|
| `l5-refusals.json` | **L5** | negative controls: each refused with its code at its line, and its whole snapshot |
|
|
| `MANIFEST.json` | — | each file's SHA-256 |
|
|
|
|
The tree and its values are in joule-ui's wire form (§2): a widget is
|
|
`{"name", "props", "children"}` (`children` absent when empty); a prop value is
|
|
`{"type": "text" | "number" | "bool" | "list" | "object", "value": ...}`, `{"type": "null"}`,
|
|
or `{"type": "action", "value": {"id", "payload"}}` with `payload` null or a prop value.
|
|
Errors carry no message: messages are for a person or a model, and not normative.
|