Canonical ABI Report 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 abi-report <file.spx> is a deterministic, read-only projection that
describes, for explicitly selected public monomorphic scalar functions, both
the native fast ABI and the portable canonical ABI of the same declaration. It
is the first executable slice of the completion-matrix row "Portable canonical
ABI and native fast ABI" under Ecosystem interoperability. It is a report and
descriptor only: it maps no interface semantics beyond the selected scalar
exports, performs no borrowing (the slice is copy-only), runs no
cross-language conformance suite, compiles nothing, executes nothing, and
changes no source.
Command
semaprax abi-report <file> --function name|stable-id[,...] [--function ...] [--max-bytes N]
--functionis required at least once; selections may be display names or explicit stable IDs, may repeat the flag, and may use comma lists. Between 1 and 64 unique targets are accepted; duplicates and unknown targets fail closed (SPX-A201,SPX-A202). Two tokens that resolve to the same declaration are rejected.--max-bytes(default 64 KiB, bounds follow the Agent Context byte limits) bounds the whole envelope. Overflow fails closed withSPX-A203; output is never truncated or repaired.- The default output is one canonical compact JSON envelope plus one trailing newline.
Admission model
The admission profile mirrors C Header Emission v1 exactly: a selected
function is admitted only when it has an explicit stable identity, is
monomorphic, declares no effects, has only by-value direct parameters over
the full Copy-scalar surface (i64, i32, u8, bool, f32, f64,
char; mixed signatures allowed), and returns a direct scalar from that same
surface. Every other selected function is recorded as an exclusion with one
closed reason: automatic_identity,
generic_function, declared_effects, unsupported_parameter_mode,
unsupported_parameter_type, or unsupported_result_type. Exclusions never
abort generation; an all-excluded invocation yields a valid empty report. If
at least one function is admitted, both production backends must succeed; any
native or HIR diagnostic fails the whole command closed.
Reported facts
Each admitted function entry carries two sections:
native— the fast ABI facts for the Native64 lane.signatureis the exact prototype line extracted verbatim from the production native C11 projection (codegen::emit_c); exactly one must exist per admitted symbol or the command fails withSPX-A204, so every reported signature matches the ABI the backend really emits.parametersandresultcarry the language type, the exact C type (int64_t,int32_t,uint8_t,uint32_tforchar,float,double, orbool), and the size and alignment taken from the checked compiler layouts (aggregate_layout::scalar_size_alignonNative64:i648/8,i324/4,char4/4,u81/1,f324/4,f648/8,bool1/1), each withmode: value.parameter_passingrecords by-value copy semantics, andstatus_out_contractrecords that the lane returnsspx_status_token, receives a leadingstruct spx_context *spx_ctx, writes<c_type> *spx_result_out, and publishes the result only at the final success commit.canonical— the portable mapping used by the Public Scalar Export Profile v1 Core-Wasm lane undersemaprax.wasm-scalar.v1: every admitted scalar is rendered exactly as the backend's Core-Wasm value-type lowering renders it (i64staysi64,f32staysf32,f64staysf64, whilebool,i32,u8, andcharall ride thei32lane).exportis the injective raw symbolspx_scalar_plus the lowercase hex encoding of the stable ID.bool_boundarydocuments the real adapter behavior — everyboolparameter and theboolresult trap unless they are canonical Wasm booleans (0or1).copy_behavioris fixed tocopyfor this slice; nothing here describes borrowing.
Functions are ordered bytewise by stable identity.
Envelope and verification
abi_report::generate returns canonical compact JSON with fixed key order:
- outer wrapper
{"schema","digest","bytes","payload"}wheredigestis the domain-separated SHA-256 of the exact payload bytes (semaprax.abi-report.payload.v1) andbytesis their length; - payload members in order:
schema,source(path,revision, domain-separated source digest),limits,selection(requested,functions_total,admitted,excluded),functions(each embedding the verbatim nativesignatureunder its own domain-separated digest plus the rebuilt-and-digested canonical object text),exclusions, and fixednonclaims.
abi_report::verify_envelope independently recomputes the outer payload
digest over the exact serialized payload bytes, re-checks the declared byte
count, rebuilds every canonical object from its parsed fields, and
re-authenticates both embedded signature digests per function before
returning the summaries. Any mutation anywhere in the envelope invalidates
verification.
Source bytes are snapshotted before parsing and re-checked after rendering;
drift fails the whole command closed. All diagnostics use the previously
unused SPX-A2xx family: SPX-A201 options, SPX-A202 selection,
SPX-A203 budget exhaustion, SPX-A204 envelope/backend consistency.
Evidence
Executable evidence lives in tests/offline_package/abi_report.rs,
tests/language/interop_scalar_widen.rs, plus module tests in src/abi_report.rs:
pinned golden envelope KATs over examples/calculator.spx and
examples/meaning.spx, byte-identical double
runs, verbatim cross-consistency against the native projection, byte-level
cross-consistency of every portable mapping and raw export name against the
real Core-Wasm module emitted by wasm::emit_module_with_scalar_exports for
the same program and selection (and, for widened scalars, against the real
Core-Wasm module emitted by the ordinary lane for the same functions),
checked-layout agreement including the
Native64/Wasm32 bool divergence, every exclusion reason exercised against
real programs, CLI exit-code contracts, budget-exhaustion failure, and tamper
rejection per digest field. No compiler, Node runtime, browser, or any other
target execution is involved, and release regression evidence is HOSTED GREEN for v0.4.0.
Scalar-surface widening (2026-08-23)
The admission profile was widened from by-value i64/bool to the full
Copy-scalar surface: i64, i32, u8, bool, f32, f64, and char
parameters and results, with mixed signatures allowed. Nothing else changed:
envelope shape, digest domains, key order, ordering, budget rules,
diagnostics (SPX-A201–SPX-A204), and nonclaims are byte-compatible for
previously admitted programs, and all pre-existing pinned KATs remain green.
- Native facts now cover every widened scalar: C spellings mirror the
production projection exactly (
int32_t,uint8_t,uint32_tforchar,float,double), and sizes/alignments come unchanged fromaggregate_layout::scalar_size_align(Native64). - Canonical rows report the exact Core-Wasm value types the backend lowers to
(
i32forbool/i32/u8/char; exact-widthf32/f64). For widened selections these are authenticated byte-level against the ordinary Core-Wasm module's type section for the same functions. - The Public Scalar Export Profile v1 adapter lane
(
emit_module_with_scalar_exports) has since been widened to the same Copy-scalar surface, so a widened canonical row'sspx_scalar_export name now names an adapter the wrapper lane really emits. Thebool_boundarynote generalizes there:u8andcharadapters trap on the same principle. No new diagnostic codes were needed — unsupported shapes keep failing closed under the existing exclusion vocabulary.
See also C-HEADER-V1.md for the sibling read-only native projection tranche and its shared admission profile, and WASM-SCALAR-EXPORTS-V1.md for the portable lane whose boundary behavior this report documents.