open-standards/joule-ui/LICENSE
Transaction Science eb12cbb2c8 joule-ui: typed declarative protocol for agent-emitted user interfaces
A sibling to JouleClaw for the moment when an agent's resolution has to
become something a human can see and interact with. The agent emits a
widget tree — (name, props, children), recursively — against a widget
registry the host has published. The host renders. No React in the
spec, no HTML over the wire, no agent holding the renderer.

The shape the field has converged on for this (A2UI, MCP Apps SEP-1865,
CopilotKit's declarative middle) is declarative components against a
registry: agents are far more reliable emitting structured data than
emitting code, and renderers are far easier to harden when they own
their own widgets. joule-ui pins that shape as a protocol; the
renderer is product surface, owned by the consumer.

Sibling, not inside jouleclaw, because the spec layer is protocol (small,
stable, conformant) and the renderer registry is product surface (many
of them, evolving fast). Splitting them protects the tools-for-use line.

Ships in v1 (joule-ui-rs/crates/joule-ui-core):

- Widget — recursive (name, props, children) with builder API
  (leaf, prop, child, children).
- PropValue — typed JSON-subset (Null / Bool / Number / Text / List /
  Object) plus an explicit Action { id, payload } variant the host
  binds at render time. No closures, no expressions, no code emission.
  From-impls for bool/i64/f64/&str/String.
- PropType — discriminator for schemas, plus Any for free-form slots.
- WidgetSchema — props (BTreeMap with PropSchema { ty, required }),
  children policy (AllowedChildren::{None, Any, OnlyOf}), strict-or-
  relaxed extra-props mode.
- Registry — host's published catalog of WidgetSchemas.
- validate / is_valid — recursive pre-order traversal that collects
  EVERY ValidationError in the tree (not just the first), so an
  authoring loop fixes them in one pass. Five error kinds: unknown
  widget, missing required prop, wrong prop type, extra prop in strict
  mode, disallowed child. Paths are human-readable JSONPath-style
  ($.children[0].children[2]).

Honest scope (v1):
- No renderer (host owns it).
- No transport (validated tree round-trips through serde_json;
  consumer chooses MCP / REST / SSE / gRPC).
- No "model emits React" path; arbitrary code emission is out.
- Whole-tree, not streaming; deltas slot in later without changing
  protocol shape.

15 tests cover: well-formed validation, unknown-widget-stops-descent,
required/extra/wrong-type props, allow_extra_props relaxation,
disallowed-child + descent-still-reports-child-errors, the Any escape
hatch, multi-error one-pass collection, Widget + Registry JSON
round-trip, leaf-widget empty-children wire shape, JSONPath in error
messages, Action payload serialization shape.

Licence: spec text and README CC-BY-4.0; reference impl Apache-2.0.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-30 09:43:56 -04:00

30 lines
1.3 KiB
Text

Creative Commons Attribution 4.0 International
Copyright (c) 2026 Transaction Science, Inc.
This specification text and accompanying documents are licensed under the
Creative Commons Attribution 4.0 International License (CC BY 4.0).
You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material for any purpose,
even commercially
Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the
license, and indicate if changes were made. You may do so in any
reasonable manner, but not in any way that suggests the licensor
endorses you or your use.
No additional restrictions — You may not apply legal terms or technological
measures that legally restrict others from doing anything the license
permits.
Full licence text: https://creativecommons.org/licenses/by/4.0/legalcode
────────────────────────────────────────────────────────────────────────
Reference implementations and software accompanying this specification, if
and when published in this directory, may be released under a separate
licence (typically Apache-2.0). Refer to the licence file alongside each
artefact.