open-standards/joule-ui/conformance/lang/v1/l4-write.json
Transaction Science 8a0f6073f7 joule-ui: the line language (SPEC §11), a streaming ingest into validated widget trees
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]>
2026-10-27 04:46:19 -04:00

364 lines
9 KiB
JSON

{
"cases": [
{
"name": "page-of-cards",
"text": "root = Page([card1, card2], \"Home\")\ncard1 = Card(\"One\", [text1])\ntext1 = Text(\"a\")\ncard2 = Card(\"Two\", null, \"sub\")\n",
"tree": {
"children": [
{
"children": [
{
"name": "Text",
"props": {
"text": {
"type": "text",
"value": "a"
}
}
}
],
"name": "Card",
"props": {
"title": {
"type": "text",
"value": "One"
}
}
},
{
"name": "Card",
"props": {
"subtitle": {
"type": "text",
"value": "sub"
},
"title": {
"type": "text",
"value": "Two"
}
}
}
],
"name": "Page",
"props": {
"title": {
"type": "text",
"value": "Home"
}
}
}
},
{
"name": "middle-absent-is-null",
"text": "root = Page([card1])\ncard1 = Card(\"t\", null, \"s\")\n",
"tree": {
"children": [
{
"name": "Card",
"props": {
"subtitle": {
"type": "text",
"value": "s"
},
"title": {
"type": "text",
"value": "t"
}
}
}
],
"name": "Page",
"props": {}
}
},
{
"name": "numbers-and-strings",
"text": "root = Page([text1, text2, text3])\ntext1 = Text(\"quote \\\" back \\\\ line\\nfeed é \\u0001\", 0.1)\ntext2 = Text(\"neg\", -0)\ntext3 = Text(\"small\", 0.0000001)\n",
"tree": {
"children": [
{
"name": "Text",
"props": {
"size": {
"type": "number",
"value": 0.1
},
"text": {
"type": "text",
"value": "quote \" back \\ line\nfeed é \u0001"
}
}
},
{
"name": "Text",
"props": {
"size": {
"type": "number",
"value": -0.0
},
"text": {
"type": "text",
"value": "neg"
}
}
},
{
"name": "Text",
"props": {
"size": {
"type": "number",
"value": 1e-7
},
"text": {
"type": "text",
"value": "small"
}
}
}
],
"name": "Page",
"props": {}
}
},
{
"name": "data",
"text": "root = Page([chart1])\nchart1 = Chart([\"a\", null], [1, []], {\"max value\": 1000000000000000000000, \"null\": null, stacked: true})\n",
"tree": {
"children": [
{
"name": "Chart",
"props": {
"labels": {
"type": "list",
"value": [
{
"type": "text",
"value": "a"
},
{
"type": "null"
}
]
},
"options": {
"type": "object",
"value": {
"max value": {
"type": "number",
"value": 1e+21
},
"null": {
"type": "null"
},
"stacked": {
"type": "bool",
"value": true
}
}
},
"values": {
"type": "list",
"value": [
{
"type": "number",
"value": 1.0
},
{
"type": "list",
"value": []
}
]
}
}
}
],
"name": "Page",
"props": {}
}
},
{
"name": "actions",
"text": "root = Page([button1, button2, button3, button4, button5])\nbutton1 = Button(\"none\", @Go())\nbutton2 = Button(\"one\", @Open(\"x\"))\nbutton3 = Button(\"two\", @Send(\"a\", 2))\nbutton4 = Button(\"list of one\", @Pick([1]))\nbutton5 = Button(\"null\", @Clear(null), true)\n",
"tree": {
"children": [
{
"name": "Button",
"props": {
"action": {
"type": "action",
"value": {
"id": "Go",
"payload": null
}
},
"label": {
"type": "text",
"value": "none"
}
}
},
{
"name": "Button",
"props": {
"action": {
"type": "action",
"value": {
"id": "Open",
"payload": {
"type": "text",
"value": "x"
}
}
},
"label": {
"type": "text",
"value": "one"
}
}
},
{
"name": "Button",
"props": {
"action": {
"type": "action",
"value": {
"id": "Send",
"payload": {
"type": "list",
"value": [
{
"type": "text",
"value": "a"
},
{
"type": "number",
"value": 2.0
}
]
}
}
},
"label": {
"type": "text",
"value": "two"
}
}
},
{
"name": "Button",
"props": {
"action": {
"type": "action",
"value": {
"id": "Pick",
"payload": {
"type": "list",
"value": [
{
"type": "number",
"value": 1.0
}
]
}
}
},
"label": {
"type": "text",
"value": "list of one"
}
}
},
{
"name": "Button",
"props": {
"action": {
"type": "action",
"value": {
"id": "Clear",
"payload": {
"type": "null"
}
}
},
"label": {
"type": "text",
"value": "null"
},
"primary": {
"type": "bool",
"value": true
}
}
}
],
"name": "Page",
"props": {}
}
},
{
"name": "derived-order",
"text": "root = Page([note1])\nnote1 = Note(null, \"b\", [text1])\ntext1 = Text(\"in\")\n",
"tree": {
"children": [
{
"children": [
{
"name": "Text",
"props": {
"text": {
"type": "text",
"value": "in"
}
}
}
],
"name": "Note",
"props": {
"body": {
"type": "text",
"value": "b"
}
}
}
],
"name": "Page",
"props": {}
}
},
{
"name": "tabs",
"text": "root = Page([tabs1])\ntabs1 = Tabs([tab1, tab2])\ntab1 = Tab(\"x\")\ntab2 = Tab(\"y\")\n",
"tree": {
"children": [
{
"children": [
{
"name": "Tab",
"props": {
"title": {
"type": "text",
"value": "x"
}
}
},
{
"name": "Tab",
"props": {
"title": {
"type": "text",
"value": "y"
}
}
}
],
"name": "Tabs",
"props": {}
}
],
"name": "Page",
"props": {}
}
}
],
"class": "L4"
}