UI Dialect Schema Projection v1
September 10, 2026 · View on GitHub
Status: versioned bounded reference; the completion matrix owns product status.
Audience: integration tool authors and compiler contributors.
semaprax ui-schema <file.spx> is a deterministic, read-only projection that
turns one verified module into one canonical compact JSON envelope
(semaprax.ui-dialect-schema.v1) describing its typed application schema. It
is the first executable slice of the completion-matrix row "First-class
application/state/UI dialect". It performs no rendering, provides no runtime,
touches no DOM, adds no typed update/view language constructs, no semantic
controls, no accessibility, navigation, localization, assets, platform blocks,
or custom rendering, executes nothing, and changes no source.
Command
semaprax ui-schema <file> [--max-bytes N]
- There is no selection flag: the whole verified module is projected.
--max-bytes(default 64 KiB, bounds follow the Agent Context byte limits) bounds the whole envelope. Overflow fails closed withSPX-U102; output is never truncated or repaired. Malformed or out-of-bounds values fail withSPX-U101.- The output is one canonical compact JSON envelope plus one trailing newline.
Admission model
Every top-level type declaration and function is classified; nothing is left implicit.
A record becomes a state-shape descriptor only when it has an explicit stable
identity, no type parameters, and fields that are all direct i64/bool
scalars. Every other declaration is recorded as an exclusion with one closed
reason: automatic_identity, generic_type, resource_type,
variant_type, or mixed_field_types.
A function becomes an action descriptor under exactly the Canonical ABI Report
v1 profile: explicit stable identity, monomorphic, effect-free, by-value
direct i64/bool parameters, direct i64/bool result. Every other
function gets one of the shared reasons automatic_identity,
generic_function, declared_effects, unsupported_parameter_mode,
unsupported_parameter_type, or unsupported_result_type. Exclusions never
abort generation.
State-shape offsets, sizes, and alignments come exclusively from the checked
Native64 compiler layouts (aggregate_layout); any missing layout entry fails
the whole command closed with SPX-U103. State shapes, actions, and
exclusions are ordered bytewise by stable identity.
Envelope content
Payload members in fixed order:
schema,source(path,revision, domain-separated source digest),limits;module(name,records_total,functions_total) andinventory(state_shapes_admitted,actions_admitted,excluded);state_shapes, each carryingstable_id,name, the embeddedlayoutobject (per-fieldindex,name,type,offset,size_bytes,align_bytes, plus record-levelsize_bytes/align_bytes), and a domain-separatedlayout_sha256over the exact canonical layout bytes;actions, each carryingstable_id,name,role: "action", the embeddedsignatureobject (parameter name/type list plus result type), and a domain-separatedsignature_sha256over the exact canonical signature bytes;exclusionswithkind(record/function),stable_id,name, andreason;- the explicit empty-by-default reserved UI section
controls,accessibility,navigation— always empty arrays in this schema version, present as nonclaim fields so downstream consumers can detect their absence of meaning rather than infer it; - fixed
nonclaims: schema projection only, no typed update/view language constructs, no semantic controls, no accessibility, navigation, localization, assets, platform blocks, or custom rendering, no target execution, read-only/no source changes.
The outer wrapper is {"schema","digest","bytes","payload"} where digest
is the domain-separated SHA-256 (semaprax.ui-dialect-schema.payload.v1) of
the exact payload bytes and bytes is their length.
Verification
ui_schema::verify_envelope independently replays one envelope: exact outer
key set and schema, declared byte count, recomputed payload digest, presence
and emptiness of every reserved UI section, and re-authentication of every
embedded state-shape layout digest and action signature digest by rebuilding
the canonical bytes from the parsed payload values. Any mutation anywhere —
including forgeries whose outer digest was consistently re-minted — fails
closed with SPX-U103. All diagnostics use the previously unused SPX-U1xx
family: SPX-U101 options, SPX-U102 budget exhaustion, SPX-U103
consistency/replay.
Source bytes are snapshotted before parsing and re-checked after rendering; drift fails the whole command closed. The embedded source digest binds the envelope to its exact input bytes.
Evidence
Executable evidence lives in tests/projections/ui_schema.rs plus module tests in
src/ui_schema.rs: pinned golden envelope digests over
examples/meaning.spx, examples/calculator.spx, and examples/records.spx,
the pinned Point state shape equal to the checked Native64 layout (fields at
offsets 0/8/16, sizes 8/8/1, record 24/8) with in-crate cross-consistency
against aggregate_layout itself, action descriptors agreeing with Canonical
ABI Report v1 signatures for the same program, determinism double runs, every
record and function exclusion reason exercised against real programs, per-
digest-field tamper rejection including re-minted forgeries, budget
exhaustion, and CLI exit-code contracts. No rendering, runtime, DOM, or target
execution is claimed; release regression evidence is HOSTED GREEN for v0.4.0.
See also ABI-REPORT-V1.md for the sibling read-only projection tranche whose function admission profile this slice mirrors.
Widened scalar profile (2026-08-24)
Schema Scalar Widening v1 admits state-shape records whose fields are any mix
of the full Copy-scalar surface — i64, i32, u8, f32, f64, char,
bool — and action descriptors whose parameters/results use the same
widened profile, mirroring the widened package-report/openapi admission
style. Field offsets, sizes, and alignments continue to come exclusively from
the checked Native64 compiler layouts (aggregate_layout), which already
define every widened scalar (4/4 for i32, f32, and char; 1/1 for u8 and bool;
8/8 for i64 and f64), and a missing layout entry still fails closed with
SPX-U103. The envelope schema stays semaprax.ui-dialect-schema.v1: no
additive bump was required because verification rebuilds canonical layout and
signature bytes from the parsed values and replays digests rather than
checking any closed type vocabulary, so pre-widening envelopes replay
unchanged and all prior pinned KATs remain green untouched. Record exclusion
reasons (including mixed_field_types) and function exclusion reasons are
unchanged and still closed.
Remaining nonclaims: strings, nested/named field types, variants, resources,
and generics stay outside the widened record profile; reserved UI sections
remain explicitly empty; no rendering, runtime, DOM, typed update/view
constructs, semantic controls, accessibility, navigation, localization,
assets, platform blocks, custom rendering, or target execution; read-only
with no source changes. Widened-type evidence lives in
tests/language/schema_scalar_widen.rs, with in-crate unit tests comparing widened
state shapes directly against aggregate_layout.