open-standards/wai/wai-int-module/README.md
Transaction Science 3f9c3ef640 wai.neural.int_hyper and wai.neural.int_mlicpp: natural, sets trained on openly licensed natural pictures, held to one decode natively, through their lowerings, in WebAssembly and on GPUs
int_hyper `natural` (wai-rs/tests/vectors/int_hyper/natural_*, record natural_set.json): a
mean-scale hyperprior, 64 synthesis and 64 latent channels, trained by
tools/wai_int_hyper_train.py at 661048492 from seed 20261112 on the 599 training pictures of
research/training-pictures/natural-1.json in 256 x 256 crops: 32,000 steps of 8, Adam 5e-4 then
5e-5 for the last quarter, lambda 0.0130, clip 1, deterministic algorithms, on the Linux x86_64
build host's integrated GPU (PCI 0x1002, gfx1151) through ROCm 7.2 and torch 2.14.0+rocm7.2, in
90 min (03:21:58-04:52:14Z); last logged step 0.5152 bpp at 26.23 dB (loss 2.53). Listing (its
identity) 3b3b56053917bf0b4a49b7011f4c725e3d413da865caec2b6bd57b953c115fb2. Coded picture: the
dead-leaves picture of that seed, stream 0, 128 x 128: 1,540 rANS bytes, 0.752 bpp, 18.74 dB,
decode 08b6bf5b...; WIH1 7922be10....

int_mlicpp `natural` (wai-rs/tests/vectors/int_mlicpp_natural/, record natural_set.json): 64
channels in 4 slices, a 48-channel hyper-latent, a 3 x 3 entropy network, trained by
tools/wai_int_mlicpp_train.py at 661048492 by the same recipe side by side on the same GPU, in 99
min (to 05:01:24Z); last logged loss 2.5833 (0.5009 bpp, 26.08 dB). model.wmb
27643187da6ba44cd5c8e3fc67ff4cf7e26026942414965cfcbd3a4b18bd4285 (1,988,549 B), listing
f37e2302bb2b26bb9a5483bf1f17e0210ecc2cf88b2b55e8b0aaaa6f4e79964b, prior id int_mlicpp/natural.
Coded picture: 1,512 rANS bytes, 0.7383 bpp, 18.65 dB, decode 1bbd9de6.... The synthetic vector
is unchanged under its own identity.

Both records read Open (check --open: tools at their blobs of 661048492, the manifest by its
digest under the licence rule); self-test 16 of 16 (int_hyper) and 14 of 14 (int_mlicpp).

Held: int-payload-conformance `natural` (WIH1); byte-exact goldens wih1_natural_set_is_golden and
int_mlicpp_golden::natural (by the sink's decode and through the lowering, reference and fast
kernels); wai-ops goldens (stage operators); ops-conformance certificates, both acc64, first
acc32 failure h_s input range at 43 bits, listed after the synthetic sets (committed_after) so
the index only gains entries; module corpus 123 cases; the browser crate's Node check; the GPU
capability test (ops_gpu.rs) with both mlicpp vectors. verifiers/trained-sets.sh runs the
manifest's check and self-test and both records' check --open and self-test.

Run through rb, macOS x86_64 (iMac): gens; wai_int_payload_vectors verify, wai-verify vectors
verify, wai_ops_check.py, int_payload_verify.py, corpus.py --check, all 0; wai-rs tests
int_hyper_ops, int_kernels_vectors, corpus_provenance, int_payload, int_mlicpp, int_mlicpp_ops
(release, no-fail-fast) and int_hyper_ops, int_payload (debug) 0; byte-exact-conformance
(release) 0; wai-ops tests 0; clippy -D warnings clean for neural_int and for the ops_gpu set
(no new lint in any other set: the union set's and byte-exact's and wai-ops's are pre-existing,
none in a touched line). Linux x86_64 (Framework): ops_gpu on gpu-vulkan-1002 and
swgpu-vulkan-10005, int_hyper 15 cases and int_mlicpp 2, graphs_differ 0, errors 0; the 48
test-picture payloads decode by wai_det_cost to the trainers' recorded digests.
Plants caught: the fast kernels' IGDN one off on 64-channel layers fails both trained sets'
goldens (3 tests) while 116 pass; one byte changed in leaves_g_s.bin and in int_mlicpp/model.wmb
(changed bytes under an existing set's name) each fail `wai breaking` as an unacknowledged wire
break; wai breaking against 88b0bdb4c passes (25 compatible changes).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 01:35:09 -05:00

111 lines
7 KiB
Markdown

# wai-int-module — the operator-set module
The first module of record of WA²ISM™'s integer level
([`extensions/waism.md`](../extensions/waism.md), `waism/1-int`): one WebAssembly module, with
the interface of waism §5 and nothing else, that decodes WAI's integer capabilities. Its decoders
are `wai-rs`'s, whose networks run on the integer operator set (`wai-ops/1`,
[integer-operators](../extensions/integer-operators.md)). The networks and their weights are not
in the module: each arrives as its capability's parameter set, data a sink holds to its digest,
so one checked module serves every capability below.
| capability | payload | set | output |
|---|---|---|---|
| `wai.neural.int_hyper` | `WIH1` | the file sequence of `entropy.json`, `g_s.whm`, `h_s.whm` | RGB8 |
| `wai.video.int_hyper` | `WIV1`, keyframe 1 | the same | each frame's SHA-256, in order |
| `wai.video.int_motion` | `WIV1`, keyframe 0 | none | each frame's SHA-256, in order |
| `wai.audio.int_codec` | `WIA1` | `model.wam` | int16 PCM, little-endian |
| `wai.splat.int_codec` | `WIS1` | `g_s.whm` | the attribute tensor |
| `wai.neural.int_synth` | the latent | `int_synth.json` | RGB8 |
| `wai.neural.int_mlicpp` | the coded image | `model.wmb` | RGB8 |
| `wai.audio.opus.dred.int` | an Opus packet | the draft's weights file | the feature rows, `i32` little-endian; none for a packet with no DRED |
| `wai.avatar.face` | `WFK1` | the file sequence of `generator.wfg`, `identity.wfi` | the frames' RGB8, one after another |
Each output is the capability's canonical buffer (waism §5 step 5): for video, a per-frame hash,
whose SHA-256 is the clip digest the integer-payload corpus states. A refusal is the capability's
own code, with `wai_run` returning 1. A set of one file is that file's bytes; a set of several is
their file sequence (waism §5, *The set*).
## What holds it
- **No floating point, no import, a fixed interface.** Both of the profile's checkers
([`../wai-module-check`](../wai-module-check)), the Rust checker and `check-module.mjs`, hold
each build at the integer level. Every allocation traps where memory cannot grow, so a failed
`memory.grow` inside `wai_run` ends in a trap and never in an output (R13); `wai_alloc` alone
returns 0.
- **The module corpus.** [`corpus.json`](corpus.json), written by [`corpus.py`](corpus.py) from
the committed corpora: every vector and refusal fixture of the capabilities above, 121 cases,
each with its capability, payload, set and the SHA-256 of the output or the refusal code. Its
sources are `int-payload-conformance/`, `neural-conformance/`, `wai-rs/tests/vectors/int_mlicpp/`,
`live-conformance/dred/` (whose weights file `live-conformance/dred/fetch.sh` fetches and checks)
and `live-conformance/avatar-face/` (each frame vector as a segment of one frame).
- **The engines.** Each runner decodes every case on an instance of its own, as waism §5 and §6
checks 11 to 13 state, holds every output to the corpus, and prints a **run digest**: the
SHA-256 of one line a case, its name and its outcome. Every run gives the same run digest.
| runner | engine |
|---|---|
| [`host/`](host) | wasmtime 50.0.1 with Cranelift, and with Winch; Wasmi 2.0.0 with its floating point turned off |
| [`run-node.mjs`](run-node.mjs) | Node, each module in a worker under a wall-clock limit |
| [`browser/run-browser.mjs`](browser/run-browser.mjs) | Chromium, headless: each case in a page's worker, each output sent back as bytes and held to the corpus outside the page |
## The modules of record
[`record/`](record) holds two builds of this crate for `wasm32-unknown-unknown`, named by their
SHA-256 in [`record/manifest.json`](record/manifest.json):
| file | build | instructions | of them 128-bit vector instructions |
|---|---|---|---|
| `wai_int.wasm` | scalar | 314,437 | 0 |
| `wai_int.simd128.wasm` | SIMD128 | 313,155 | 7,099 |
The SIMD128 build is the same source, which the compiler lowers to WebAssembly's integer vector
instructions where it can. Its output is the scalar build's: every case gives the same outcome in
both, on every engine.
Each module of record gave every case of the corpus its stated outcome, with run digest
`0098ef57a0c75c4563b842e8969778b7744a258872ae7ae48917fb1a93b3aaf5`, on these (macOS arm64:
the build of this source made over `wai` 0.4.0, before its version moved to 0.5.0, with
SHA-256 `80e64e02…1441` and `f0f9e1df…1fc1`):
| host | wasmtime 50.0.1, Cranelift | wasmtime 50.0.1, Winch | Wasmi 2.0.0 | Node | Chromium, headless |
|---|---|---|---|---|---|
| Linux x86_64 | yes | yes | yes | 22.23.4 | 148.0.7778.96 |
| Linux arm64 | yes | yes | yes | 24.22.2 | |
| macOS arm64 | | | | 26.13.0 | 156.0.8078.4 |
That run digest is of the corpus's first 120 cases. With the 121st, `int-payload/leaves` (a
`WIH1` payload decoded against the set trained on generated pictures,
`wai-rs/tests/vectors/int_hyper/leaves_set.json`), both modules of record gave every case its
stated outcome on Linux x86_64 under wasmtime 50.0.1 (Cranelift and Winch) and Wasmi 2.0.0, with
run digest `f245b5f0b7e7dc3b1aa8c3974fa413cfc4d87097b790dcfe3f5478fa5c457836`. The corpus then
gained two cases, `int-payload/natural` and `int_mlicpp/natural` (the sets trained on openly
licensed natural pictures, `wai-rs/tests/vectors/int_hyper/natural_set.json` and
`wai-rs/tests/vectors/int_mlicpp_natural/natural_set.json`), 123 in all; `wai-int-module.yml` runs
them on its engines, and no run of the 123 is recorded here yet.
The module is the same source on every host, and its bytes are not: the compiler's crate hashes
take in the absolute path of each path dependency and the host it runs on, and they order what it
emits. Linux arm64's build of this source has other bytes (765,514 and 773,603), and on wasmtime
with both compilers, Wasmi and Node there it gave every case the same outcome, the same run
digest. So `record/` is named by its SHA-256, and a build is held to the corpus, not to `record/`'s
bytes.
## Building and running
```
bash build.sh [--out DIR] # both builds, each held by both checkers
bash ../live-conformance/dred/fetch.sh DRED # the weights file the corpus names
(cd host && cargo run --release -- --external DRED ../corpus.json ../record/wai_int.wasm ../record/wai_int.simd128.wasm)
node run-node.mjs --external DRED corpus.json record/wai_int.wasm record/wai_int.simd128.wasm
node browser/run-browser.mjs --browser PATH --external DRED corpus.json record/wai_int.wasm
python3 -I corpus.py --check # corpus.json is the committed corpora's
python3 -I plant.py float|relaxed IN OUT # a rule-breaking instruction, for the checkers
```
`build.sh` names no path of the machine that runs it in the module: the checkout, the Cargo home
and the toolchain are remapped.
CI: `.github/wai-conformance/verifiers/module-check.sh` holds `record/` to its manifest and both
builds at the integer level by both checkers, and refuses the module of record with a float
instruction planted, and with a relaxed vector instruction, at the rule and offset the plant
gives; `.github/workflows/wai-int-module.yml` runs the engines.