open-standards/joule-ui/README.md
Transaction Science 9f7566927c
All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no comparison (pull_request) Successful in 4s
no-vanity-metrics / WAI public text names no company or product (pull_request) Successful in 4s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m13s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m58s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m30s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m11s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m11s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m19s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m7s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m50s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 28m1s
standards workspaces build + test / aac-rs (pull_request) Successful in 5m42s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 10m13s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 5m35s
standards workspaces build + test / map-rs (pull_request) Successful in 7m25s
standards workspaces build + test / mesh-rs (pull_request) Successful in 4m18s
standards workspaces build + test / openpay (pull_request) Successful in 16m8s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 3m15s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m53s
licences: ship the Apache-2.0 text the code already declares
arl-rs, eoc-rs, smart-byte-rs and joule-ui-rs declare license = "Apache-2.0"
in every crate, but each standard carried only its CC-BY-4.0 LICENSE for the
specification text. Each Rust workspace now carries the Apache-2.0 text, and
each README names both licences and where they live. jouleclaw's README pointed
spec text at a spec/LICENSE that does not exist; it now points at LICENSE-SPEC.

No licence changes: every file already declared these terms.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 17:22:32 -04:00

68 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# joule-ui
A typed declarative protocol for **agent-emitted user interfaces**.
joule-ui is the sibling to [JouleClaw](../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 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.
## What ships in v1
- `joule-ui-rs/crates/joule-ui-core/` — the protocol types (`Widget`,
`PropValue`, `WidgetSchema`, `Registry`) and the recursive validator.
Pure Rust, no IO, JSON-serialisable.
- `joule-ui-rs/crates/joule-ui-interaction/` (**v0.2**) — the layer no
other UI protocol carries: when a human *or an agent* fires an
`Action`, the invocation is an **accountable event**. Every fire names
the principal that made it — a `did:key`, the same whether a person or
an agent (the protocol draws no distinction; both are traced).
`run_interaction` authorizes it against a capability *before it runs*
(a denied action's handler never executes), meters it in joules,
charges its cost (a reading or an estimate, and which), and an
`InteractionLog` seals it as the next
link of a **hash-chained** receipt. The actor is bound into the signed
core, so an interaction cannot be re-attributed without breaking the
chain. A joule-ui session becomes a tamper-evident ledger of *who fired
it, what it computed, and what it cost* — verifiable by anyone holding
the host's key. The metering (Sandbox `PowerMeter`) and
the capability (JCP grant) are **recognized edges**; the receipt, the
chain, and the lifecycle are joule-ui's. See [`SPEC.md`](SPEC.md) §5–§7
and `examples/metered_surface.rs` for the full loop.
The surface layer makes joule-ui a peer of the declarative-UI protocols
(A2UI, MCP Apps). The interaction layer makes it the only one you can
hand to an auditor: a UI whose every interaction is energy-accounted and
sealed, by construction.
What is **not** here:
- A renderer. The renderer is owned by the host (browser app, native
shell, terminal UI). joule-ui validates the surface and seals the
interaction; it does not paint pixels.
- A transport. The validated spec and the interaction stream ride MCP,
REST, SSE, gRPC, Web MoQ — any bytes-out protocol. Transport-agnostic.
- A "model emits React" path. The agent emits a declarative tree against
the registry; arbitrary code emission is out of scope.
## Why a sibling, not inside JouleClaw
The spec layer is protocol — small, stable, conformant. The renderer
registry is product surface — many of them, evolving fast. Splitting
them protects the *tools for use* line: JouleClaw stays the runtime
substrate; joule-ui is the UI protocol; consumers ship their own
widgets.
## Licence
Specification text and protocol document: CC-BY-4.0 (see [`LICENSE`](LICENSE)).
Reference implementation in `joule-ui-rs/`: Apache-2.0 (see [`joule-ui-rs/LICENSE`](joule-ui-rs/LICENSE)).