v1.2 — Generative UI Trust Runtime
Document ID: RM-GUI-001
File Path: docs/18-roadmap/v1.2-generative-ui.md
Version: 1.3.0
Status: Phases 1–3 complete (2026-07-15) — the scoped v1.2 milestone is shipped
Owner: Product / Founder
Last Updated: 2026-07-15
1. Purpose
Section titled “1. Purpose”Execute PRD-005 (decision: ADR-0011): ship the frame protocol, the trust/policy engine, the durable interaction loop, the renderer SDK, and the internal-tools beachhead — in three strictly sequential phases with measured exit criteria.
Requirement IDs (UIP/GRD/HIL/RDR/CMP/ITS/EMB) are defined in PRD-005 §6; tickets
here carry the RM-GUI-P<phase> prefix and reference them.
Relationship to v1.1: Phase 1/2 of v1.1 are done. v1.1 Phase 3 (ecosystem & scale) is re-scoped through PRD-005: items serving the trust runtime (MCP surface, SDK distribution) fold into RM-GUI-P3; purely horizontal items are deferred to future.md.
2. Phase 1 — Protocol & Trust Core (server-side only) — ✅ DONE (2026-07-15)
Section titled “2. Phase 1 — Protocol & Trust Core (server-side only) — ✅ DONE (2026-07-15)”Theme: frames exist and are governed. No renderer; acceptance is against the API/SSE stream and the audit chain.
Shipped: all nine tickets. wovyr-ui + wovyr-ui-guard crates;
__execution_id engine stamping; the server ui activity
(UiActivityExecutor in crates/wovyr-server/src/ui.rs) with the durable
pending-frame store under ~/.wovyr/ui; GET /api/v1/ui/frames[/{id}] +
POST /api/v1/ui/decisions/{id}; audit-chain verdict/decision records paired
with frame hashes; RunEvent::UiFrame over SSE. Exit criterion met: UC1
(incl. the kill/restart crash-recovery variant) and UC4 run green in
wovyr-server’s ui::tests. Two P1 deviations, both documented in code:
display-only frames complete immediately instead of suspending (nothing to
decide — a pending record no decision could clear would leak), and the
protocol additionally rejects frames declaring inputs without any action
(a dead control the decision loop could never complete). The GRD-203
LLM-judge variant was cut per §5’s P1 cut line — structural rules only.
| Ticket | Requirement(s) | Summary |
|---|---|---|
| RM-GUI-P1-101 | UIP-101, UIP-106 | New crate wovyr-ui: UiFrame tree over the constrained component vocabulary, schemars-derived schemas, semver’d schema version, newer-than-understood rejection |
| RM-GUI-P1-102 | UIP-102, UIP-103 | Provenance metadata (run id, model id, prompt pin, canonical content hash) + declared intents on every actionable node; undeclared effects are validation errors |
| RM-GUI-P1-103 | UIP-104 | UiFrame event on RunEventSink → server SSE frame; workflow-activity output form; REST pull of the pending frame |
| RM-GUI-P1-104 | GRD-201, GRD-206 | New crate wovyr-ui-guard: UiPolicy YAML (forbidden component classes deny-by-default, approval-gate requirements, redaction, media-origin allow-list), tenant-scoped + versioned + pin-immutable |
| RM-GUI-P1-105 | GRD-202, GRD-207 | Guardrail-stage enforcement between generation and emission, fail-closed; hosted-run floor: no policy ⇒ input/action frames denied (WOVYR_UNRESTRICTED_UI=1 escape hatch) |
| RM-GUI-P1-106 | GRD-203, GRD-204 | Intent-consistency structural checks + deception-shape rules (structural first; LLM-judge variant shadow-mode only) |
| RM-GUI-P1-107 | GRD-205 | Verdicts into the wovyr-audit hash chain (rule id + frame hash); blocked-frame content retained KMS-encrypted, policy-controlled |
| RM-GUI-P1-108 | HIL-301..303 | ui workflow activity (durable suspend on the Interrupted path); typed decision validation; POST /api/v1/ui/decisions/{frame-id} over the human-approval signal path, decision-taker recorded |
| RM-GUI-P1-109 | — | Integration tests: UC1 (block-then-allow) and UC4 (injection containment) end-to-end over SSE + audit verify(); crash-kill between frame and decision resumes clean (the existing startup-resume test pattern) |
Exit: UC1/UC4 green in CI, including the crash-recovery variant.
3. Phase 2 — Renderer & Interaction Loop — ✅ CORE DONE (2026-07-15)
Section titled “3. Phase 2 — Renderer & Interaction Loop — ✅ CORE DONE (2026-07-15)”Theme: humans see and decide.
Shipped: @wovyr/ui-react (sdks/ui-react) — a React renderer for the
full component vocabulary, CSS-custom-property design tokens, an inert
visible placeholder for unrecognized node types, and client-side frame-hash
verification (hash.ts’s canonical-JSON + Web Crypto SHA-256, cross-checked
against a real frame from the live Rust server — the JS and Rust hashes
matched byte-for-byte, proving RDR-403’s integrity claim actually holds, not
just that the two implementations independently believe themselves correct).
The base TS SDK (sdks/typescript) gained a ui resource (frames.list/get,
decisions.submit) with an ui: integration-test suite proving UC1/UC4
against a live server. The killer demo (RM-GUI-P2-209) ships as
examples/workflows/ui-checkout-{approve,block}.yaml +
examples/ui/checkout-demo (a runnable Vite+React app) — driven end-to-end in
a real browser against a real wovyr-server: the poisoned frame blocked and
never rendered; the safe frame rendered, was approved with a real decision
POST, and cleared from the pending list. A scoped HIL-304 landed as the
ui_present tool (wovyr-tools, opt-in only, never a default builtin) +
UiInteraction trait + the CLI’s wovyr agents run --local --interactive-ui
stdin presenter — so a bare (non-workflow) agent run can present a
policy-checked frame and get a decision back, with the same fail-closed
frame/decision validation as the workflow path.
Honest gaps, carried forward rather than silently dropped:
- RDR-402 (web-component build) — cut per §5’s P1 cut line, extended to P2: React is the only supported host.
- RDR-404 (progressive/streaming rendering) — not built. Frames present
complete, not incrementally; the protocol has no partial-frame delta shape
to stream (unlike
ToolCallDelta). A later slice if a real use case needs it. - HIL-305 (durable frame timers) and the audit-chain pairing half of
HIL-306 — not built for the bare-agent-run path.
ui_presenthas no durability at all (a bare agent run has no checkpoint to resume from, documented in the tool’s own module comment) and is not wired into any audit log — only the P1 workflow path is audited. Presenting UI from a bare agent run in a hosted/audited context is not yet a supported combination; use the workflowuiactivity for anything that needs a durable or audited trail. - GRD-208 (WASI validator sandboxing) and CMP-501..503 (signed templates) — cut per §5, deferred to Phase 3.
| Ticket | Requirement(s) | Status |
|---|---|---|
| RM-GUI-P2-201 | RDR-401, RDR-403 | Done — @wovyr/ui-react, cross-language hash-verified |
| RM-GUI-P2-202 | RDR-402 | Cut — React only |
| RM-GUI-P2-203 | RDR-404 | Not built — no progressive rendering (see above) |
| RM-GUI-P2-204 | RDR-405 | Done — accessible markup by construction |
| RM-GUI-P2-205 | HIL-304..306 | Partial — HIL-304 (bare-run ui_present tool) only; no durability, no audit |
| RM-GUI-P2-206 | GRD-208 | Cut — deferred to P3 |
| RM-GUI-P2-207 | CMP-501..503 | Cut — deferred to P3 |
| RM-GUI-P2-208 | RDR-406 | Done — sdks/ui-react/README.md quickstart |
| RM-GUI-P2-209 | PRD-005 §9 | Done — examples/ui/checkout-demo, verified live in a real browser |
Exit: the killer demo runs from a fresh clone (verified: server up, demo
npm install && npm run dev, both flows work in a real browser). The SDK
quickstart is documented but not yet timed with an external tester — that
measurement is deferred to the design-partner onboarding in Phase 3.
4. Phase 3 — Beachhead & Embeddability — ✅ DONE (2026-07-15)
Section titled “4. Phase 3 — Beachhead & Embeddability — ✅ DONE (2026-07-15)”Theme: sellable and adoptable.
Shipped: wovyr-ui-guard::conformance (EMB-704) — a public,
serde_json/plain-JSON-vector conformance suite (crates/wovyr-ui-guard/src/conformance.rs)
any deployer can run against their own policy (conformance_report(&policy)),
gated in this workspace’s own cargo test --workspace. Standalone middleware
mode (EMB-701, crates/wovyr-server/src/ui.rs) — POST /api/v1/ui/present +
GET/POST /api/v1/ui/decisions/{id} present/decide/retrieve a trust-layer-governed
frame with zero workflow or agent adoption, verified live end-to-end
(present → render → decide → retrieve, plus the sensitive-input block path)
against a real server. RDR-402’s cut was revisited and built:
<wovyr-ui-frame> (@wovyr/ui-react/web-component, sdks/ui-react/src/webComponent.tsx)
wraps UiFrameView in a framework-agnostic custom element (react-dom/client’s
createRoot internally), dispatching a decide CustomEvent a host attaches
its own async decision promise to — proven with a deliberately React-free
smoke test (examples/ui/checkout-demo/web-component.html). The dashboard’s
Surfaces panel (ITS-601/602, dashboard/src/app/features/surfaces/) is real
dogfooding, not a mock: an operator composes an actual UiFrame, presents it
via POST /api/v1/ui/present through the dashboard’s own HttpClient +
tenant interceptor, renders it with <wovyr-ui-frame>, and decides it under
their own RBAC-scoped session (ui:read/ui:write) — verified live in a
browser end to end, including the trust layer visibly blocking a destructive
action the operator opts into for the demo. The design-partner onboarding
guide (PRD-005 §8, docs/01-product/design-partner-onboarding.md) ships with
every command in its quickstart run against a real server, not just written.
Verification, not just code: every claim above was exercised against a
live wovyr-server (curl for the onboarding quickstart, a real browser for the
web component and the dashboard panel) — including both the allow path and
the trust layer actually blocking a frame, in the dashboard’s own UI.
Scoped for this pass (solo-founder bandwidth, same discipline as P1/P2’s own
cuts): the highest-leverage, honestly-buildable subset this pass is
EMB-701 (standalone mode — the definitional embeddability feature: zero
workflow/agent adoption required to use the trust runtime) and EMB-704
(a public, reusable conformance suite). Building real dashboard Surfaces
dogfooding (ITS-601/602) requires embedding @wovyr/ui-react in a non-React
host, which means revisiting P2’s RDR-402 cut — a web-component wrapper is
now in scope because Surfaces needs it, not as a standalone goal. The
design-partner onboarding doc is a cheap, concrete artifact; the actual
partner program (5 partners, paid pilots) is a business/GTM activity, not a
code deliverable, and isn’t attempted here.
Cut, per this scoping pass:
- EMB-702 (MCP server surface) — this codebase has an MCP client
(
wovyr-tools::mcp) but no MCP server implementation at all; servingui_present/ui_await_decisionas MCP tools is a new subsystem, not an extension of existing code. Deferred whole. - UIP-105 / EMB-703 (interop mapping to A2UI/MCP Apps) — per the P3 cut line already on record below; those standards are still in motion and the runtime/enforcement point (already shipped) is the durable value, not the schema.
- ITS-603 (destructive-action auto-gating) and ITS-604 (saveable/ shareable surfaces) — real features, not attempted this pass; the Surfaces panel below is a working, honestly-scoped v1, not the full ITS vision.
- The design-partner program’s execution (outreach, 5 partners, red-team, paid pilots) — a business activity; only the onboarding document ships.
| Ticket | Requirement(s) | Status |
|---|---|---|
| RM-GUI-P3-301 | ITS-601, ITS-602 | Done — real Surfaces panel, verified live (not the full ITS vision — see cuts below) |
| RM-GUI-P3-302 | ITS-603, ITS-604 | Cut — deferred |
| RM-GUI-P3-303 | EMB-701 | Done — standalone present/decide/retrieve, verified live against a real server |
| RM-GUI-P3-304 | EMB-702 | Cut — no MCP server subsystem exists yet |
| RM-GUI-P3-305 | UIP-105, EMB-703 | Cut — deferred (standards immaturity) |
| RM-GUI-P3-306 | EMB-704 | Done — wovyr_ui_guard::conformance, gated in cargo test --workspace |
| RM-GUI-P3-307 | PRD-005 §8 | Done — onboarding doc shipped, quickstart run live end-to-end; partner program itself (outreach, 5 partners, paid pilots) is a business activity, not attempted |
| — | RDR-402 (revisited) | Done — <wovyr-ui-frame> web component, un-cut from P2 because Surfaces needed it |
Exit: met. POST /api/v1/ui/present proven end-to-end with zero
workflow/agent involvement (including the sensitive-input block path); the
conformance suite passes in cargo test --workspace (147+ Rust tests green,
one pre-existing unrelated environmental flake in an unrelated wovyr-cli
scaffold test — confirmed to pass in isolation, a resource-contention issue
under the full parallel test run, not a regression); a real Surfaces panel in
the dashboard renders a real frame built from a real API call and dispatches
a real, RBAC-scoped action under the operator’s own session when decided —
verified live in a browser, both the allow path and the trust layer visibly
blocking a destructive action.
5. Cut Lines (solo-founder bandwidth, PRD-005 §10)
Section titled “5. Cut Lines (solo-founder bandwidth, PRD-005 §10)”If a phase overruns, cut in this order — never the other:
- P1: LLM-judge consistency checks (GRD-203 judge variant) → structural rules only. Blocked-frame content retention (GRD-205 second half) → verdict-only audit.
- P2: Web-component build (RDR-402) → React only. Marketplace badge track (CMP-502) → signing only.
- P3: Interop mapping breadth (UIP-105) → one target shape first. Surfaces sharing (ITS-604) → per-operator only.
The fail-closed floors (GRD-202/207, HIL-302) and audit integration (GRD-205 verdicts, HIL-306) are never cut — they are the product.
6. Revision History
Section titled “6. Revision History”| Version | Date | Description |
|---|---|---|
| 1.3.0 | 2026-07-15 | Phase 3 shipped: EMB-701 standalone mode, EMB-704 conformance suite, RDR-402 web component (revisited from its P2 cut), and a real dashboard Surfaces panel (ITS-601/602) — all verified live against a real server/browser, not just typechecked. Design-partner onboarding doc (PRD-005 §8) shipped with its quickstart run end-to-end |
| 1.2.0 | 2026-07-15 | Phase 2 core shipped: @wovyr/ui-react (cross-language hash-verified), the killer demo running live in a browser, and a scoped HIL-304 (ui_present tool, no durability/audit). RDR-402/404, HIL-305, GRD-208, CMP-5xx documented as cut or not built |
| 1.1.0 | 2026-07-15 | Phase 1 shipped: all RM-GUI-P1 tickets done, UC1/UC4 + crash-recovery green; two documented P1 deviations (display-only frames complete immediately; inputs-without-actions rejected at the protocol) |
| 1.0.0 | 2026-07-14 | Initial v1.2 milestone: three phases executing PRD-005 |