wai-ops: the reference crate and conformance vectors for wai-ops/1 (D2a) #206
Merged
dcharlot
merged 15 commits from 2026-10-10 17:17:02 -04:00
wai/d2a-operators-crate into main 2026-10-10
ops-conformance: say why the corpus carries no sha256.json
All checks were successful
wai-ops integer operators / wasm32 under Node (pull_request) Successful in 19s
wai-ops integer operators / independent checker (Python) (pull_request) Successful in 11s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 4s
WAI section references / cited sections exist (pull_request) Successful in 10s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 2m50s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 14m47s
wai-pack / wai-pack · linux (pull_request) Successful in 1m6s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 1m46s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 19s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m14s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 20m46s
standards workspaces build + test / aac-rs (pull_request) Successful in 10m39s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 4m15s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 1m29s
standards workspaces build + test / map-rs (pull_request) Successful in 52s
standards workspaces build + test / mesh-rs (pull_request) Successful in 1m15s
standards workspaces build + test / openpay (pull_request) Successful in 5m42s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 13m8s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 56s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 4m22s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 58s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m57s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m48s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m6s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 10m6s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 29s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 3m11s
wai-ops integer operators / macos-arm64 (pull_request) Successful in 25s
wai-pack / wai-pack · macos (pull_request) Successful in 2m13s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
int_kernels_vectors: ops-conformance states no digest of decoded output
Some checks failed
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
wai-ops integer operators / linux-aarch64 (pull_request) Has been cancelled
wai-ops integer operators / linux-x86_64 (pull_request) Has been cancelled
wai-ops integer operators / macos-arm64 (pull_request) Has been cancelled
wai-ops integer operators / wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
wai-ops integer operators / wasm32 under Node (pull_request) Has been cancelled
wai-ops integer operators / independent checker (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
WAI section references / cited sections exist (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
workflow hygiene / every workflow supersedes its own queue (pull_request) Has been cancelled
every_decoded_output_states_a_sha256 enumerates every wai/*-conformance/ directory, and the new ops-conformance had neither a sha256.json sidecar nor an exclusion, so the cargo-class corpora job failed reading the sidecar. It takes an exclusion, because SPEC §7 *Digests* does not reach it: the rule binds a vector that states a digest of a parameter-set decode's output, and no file there states one. Every operator, stage and graph vector, the lower_* decodes of the sets under sets/ included, states its output integers in full or its refusal code; certificates/index.json states only each set's SHA-256 (a parameter-set identity), and the lowered graphs are held as bytes and compared byte for byte. The output digests a capability decoded through its lowering must reproduce (integer-operators §14.4) stay in that capability's own corpus, whose sidecars wai-ops's goldens already read. Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09
wai-ops.yml: the goldens' digest file in the filter; every test on the 32-bit leg
Some checks failed
WAI conformance / cargo-class corpora · linux (pull_request) Failing after 1m49s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 14s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 30s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 51s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 1m54s
wai-ops integer operators / linux-x86_64 (pull_request) Successful in 21s
wai-ops integer operators / wasm32-wasip2 (wasmtime) (pull_request) Successful in 23s
wai-ops integer operators / wasm32 under Node (pull_request) Successful in 19s
wai-ops integer operators / independent checker (Python) (pull_request) Successful in 11s
WAI section references / cited sections exist (pull_request) Successful in 10s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 14m13s
standards workspaces build + test / jouleclaw-rs (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
wai-ops integer operators / linux-aarch64 (pull_request) Has been cancelled
wai-ops integer operators / macos-arm64 (pull_request) Has been cancelled
- The goldens compare against wai/neural-conformance/sha256.json, which the `paths:` filters did not match (the repo's own matcher said False). Both lists now take wai/neural-conformance/**, so a re-pinned digest runs wai-ops. - The wasip2 leg ran only `vectors verify`, so the unit tests and the goldens never ran on a 32-bit target. It now runs `cargo test` under wasmtime in the default build (unit and step-8 tests) and with `uncertified` (unit tests, goldens, step-8 test), with the wai directory preopened at its own absolute path for the files the tests read. Both pass locally under wasmtime. - The native default-build step runs `cargo test`, not `--lib`, so the step-8 test and the doc tests that keep an unloaded graph from running are run. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: the interpreter runs only a loaded graph, so step 8 cannot be bypassed
Load step 8 was enforced at `graph::load` only. `interp::run` took any `&Graph`, and a lowering's graph, a parsed one or a struct literal reached it without step 8: in the default build, `lower::int_synth` then `run` decoded the gradient set to its committed digest while `graph::load` of the same bytes refused it at Load(8). - `graph::Loaded` holds a graph that passed every load step; its field is private and only `graph::load` makes one. `run` takes `&Loaded`. - A `Graph`, parsed, lowered or built in place, is data. A compile_fail example (E0308) on `Loaded` shows a lowered graph cannot be passed to `run`. - The goldens load every lowered graph from its bytes before running it, so their `uncertified` gate now guards something. - tests/step8.rs, in every build: each lowered int_synth graph is refused at Load(8) without the switch and loads with it. - Cargo.toml says who enables the switch, and that no decoder may. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: a vector for each run and load rule the text now states
A review found rules that only the crate and the README settled, and that no vector pinned: changing the checker to another reading of each changed no committed byte. integer-operators now states each one, and each now has a vector that a different reading fails: - state: a refused decode changes no state; until a decode completes, a state input is `init`, sized by input 0 of the decode being made (§10.3). - run step 1 runs input by input; an input with a dimension of 0 is model_mismatch (§4). - run step 3: conv_transpose's uncropped output of cout planes is capped, not one plane; the caps come before the shape rule, both for that output and for an uncropped side; the shape rule comes before max_elems (crop_to) (§4, §5.3). - crop: a scalar start of −1 is refused though −1 + h ≤ H, and at load a scalar start is planned at 0, not at its range's low end (§5.10). - load step 5: chscale's m_bytes and layernorm_c's g_bytes of 2 are refused, and 4 loads (§10.4). subpos_merge now caps its output sides before its shape rule, in the crate and the checker, as §4 states for every operator. No input within the caps can tell the two orders apart. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai_ops_check.py: load step 8,
profiles recomputed, lowering vectors tied to their roles
The checker copied each vector's `profiles` from the committed line, never ran load step 8, and took the graph bytes of graphs/lower_*.jsonl as given. So a regression in the generator's tagger, or a lowering vector whose graph was not its role as lowered, would have passed. - A bounds pass and verdict written from integer-operators §8.1–§8.5: every +, −, × and floor division saturated at ±2^255 with the node's saturated flag (§8.1), the term and partial-sum intervals (§8.2), each operator's rule (§8.3), the classes and parameter conditions of §7, and what a node fits and the verdict (§8.5). It writes no certificate. - Load step 8: an empty `check` interval, a lut16 input range past ±32767, or a verdict that meets neither profile refuses the graph (model_mismatch). - `profiles` is recomputed: both profiles for a refused load, else exactly those the verdict meets (§14.1). It agrees with all 1,599 committed tags, and with Appendix C's predictions for every committed set (int_synth gradient, bloom and facade acc32; photo and every WHM1, WAM1 and WMB1 set acc64). - Each lowering vector's id names <file>/<set>/<role>; its graph must be that role as re-lowered, and every role must have one. The README now points to §14.1 for every field, and lists the coverage classes of §14.1 item 6 that wait for step 8 in wai-ops: sigmoid and elu at −2^63, and an rq whose q passes 64 bits while y fits. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: a tensor a ReLU reads inside a WHM1 network is derived, as §13.2 says
§13.2 gives `check` only to an x_ℓ that a layer of tag 0, 1, 2 or 4 reads, and `check [−2^63, I64]` to a network input that no such layer reads; every other tensor is `derived`. The lowering and the checker both gave every x_ℓ a ReLU reads `check [−2^63, I64]`, so a reader of the text could not reproduce three committed graphs. Both now follow the text. The checker's `x_record` is rewritten from the §13.2 wording, not from the crate. Regenerated: the h_s graph of the int_hyper set 7aceaa1a… and of the int_mlicpp sets 07e1835d… and 7ef44f3b…, and the lower_whm1 and lower_wmb1 vectors that embed them. No output changes: the range they drop held every i64. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: rate_predict vectors at the i16 extremes with rates near 2^32
With prev = [−32768, 32767], rate_num = 2^32 − 1 and rate_den = 2^32 − 2, (b − a)·ρ is 65535·(2^32 − 2), just under 2^48, and rdiv's 2|n| + d passes 2^48 (§5E E12 now states the widths). Three vectors pin the results: both orders of the extremes, and two channels at rate_den = 2^31. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: residual_step's 32-bit form, with the conditions under which it fits i32
E9's 32-bit form fits i32 only when hi − lo ≤ 65535 and lo − 131070 and hi + 131070 also fit. At lo = 2^31 − 65536, hi = 2^31 − 1, q = 65535, pred = hi, r = 2, it formed hi + 131070 and the function overflowed. - `residual_step_i32` asserts its conditions (`i32_form_fits`) in debug builds. - `residual_identity_holds` covers the ranges nearest the i32 limits on which the form still fits, and `residual_form_condition_is_tight` shows that one step past them it does not, while the exact form gives the clamped value. - stage/residual_step.jsonl gains 32 vectors at the i32 limits, at r = ±R and ±(R + 1), with q = 1 and q = 65535, as §14.1 item 7 asks. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: mans_decode reports a refusal at the position whose step refuses
Only the `in` step set the reported position, so a refusal in a position's `out` step (in sgm, the flush after an escape) named the last `in` of its group. mans_decode/sgm/40 said at=11; symbol 10's escape flush refuses, and it now says at=10. A flush that belongs to no single position reports the last position whose `in` step ran, as integer-operators §14.1 now states. The checker sets the position at each `in` and `out` step and names the group, remainder and row-end flushes as such, following §14.1's wording. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: the strict run-out case alone, not paired with a non-minimal count
Its stream's groups were 2, 6, 0: a zero last group, so under final_only it showed the non-minimal refusal, which has its own paired case. Now 1, 6: under canonical it is refused at the symbol (stream_exhausted), under final_only the symbol decodes and the end refuses (stream_exhausted at 1). Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: CI on every leg the corpus runs on, and the corpus README
.github/workflows/wai-ops.yml, with a concurrency group per ref: - linux, linux-arm64, macos: the unit tests in the default build (load step 8 refuses every graph) and with the `uncertified` switch, the goldens in debug and release, and `wai-ops vectors verify`; - wasm32-wasip2 under wasmtime 38.0.3: `wai-ops vectors verify`; - wasm32-unknown-unknown under Node: every vector file recomputed; - tools/wai_ops_check.py, the independent checker, and the concurrency gate. ops-conformance/README.md names the layout, the conventions both recomputations follow where §14.1 leaves a choice (data inputs only in `inputs`, a refused decode leaves the state, each stage operator's `in`, `modes` and `expect`, and what `at` reads for each), the lowered sets' digests, and how to regenerate and verify. The three goldens that need data this repository does not commit (a jpegai bundle, a legacy decoder's intermediates on one codestream, the reference encoder's mANS streams) are now `#[ignore]` with the reason, so CI reports them ignored rather than passed; locally, with the data, all three pass. The tagger now applies §8.5's fit rule as written; the corpus is unchanged by it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: an independent checker, wai_ops_check.py, for the vectors and the lowerings
wai/tools/wai_ops_check.py, Python standard library only, sharing no code with wai-ops. From integer-operators (and integer-payloads for the source forms), it recomputes every vector file of ops-conformance: each graph vector's `load` (WHG1 and load steps 1–7) and every decode's `expect` (§4, every operator of §5, the transposed convolution in its gather form), and each stage vector's `expect` (§5E); writes each file canonically and requires the committed bytes. It re-lowers every set the index lists by §13 and requires each lowered graph's bytes and each set's digest. On the committed corpus it rewrites all 53 vector files and all 28 lowered graphs byte for byte; a changed output, a changed symbol and a changed byte of a lowered graph each fail it. Independence: written in the same session as wai-ops, after it, from the text, with the text open and the Rust closed, and structured differently where the text allows. It is not the separate text-only session the plan asks for; that session is still owed before D2a merges. graph.rs gains tests that a graph round-trips, that the default build refuses every graph at load step 8, and that the `uncertified` switch skips it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: the conformance corpus, its generator, and the WASI and browser-engine legs
wai/ops-conformance/, in integer-operators §14.1's format, written by `wai-ops vectors gen`: - vectors/<operator>.jsonl: one-operator graph vectors for every graph operator: random cases over several magnitudes, and the coverage classes of §14.1: bound-attaining inputs, rounding ties at every mode and the shifts the class names, geometry, the i32 limits and one past them, check and scalar ranges at their ends and one past, every run-time shape refusal, and the distinguishing cases (per-term igdn floors, leaky floors, softmax rows, elu(0), a half mean in layernorm_c, ε = 2^64 − 1, exp at n = 62 and 63). - stage/<operator>.jsonl: E1–E13. E1 under every mode, with each strict refusal alone and in each pair one symbol can give, under both end rules; E8 with zero tails, short streams, and escapes at bounds of 128 and 255. - graphs/: the phase form against conv_transpose (the generator checks the two outputs agree), a state carried across three decodes, a refusal at each load check (steps 1–7) and at each run step, and every lowering on a small set. - certificates/<capability>/<set digest>/<role>.whg1: the lowered graphs of every committed set and of the small sets, with certificates/index.json. Every vector's `profiles` is the profiles its graph meets under §7 and §8.3, from the generator's own tagger; a case that meets neither is not written (its load refusal is a D2b vector). The certifier must agree with every tag. `wai-ops vectors verify` recomputes every vector file, re-lowers every set and regenerates the corpus, and requires every byte to match. It passes natively, as the same binary built for wasm32-wasip2 under wasmtime, and through wai-ops/node, the recomputation as a wasm32-unknown-unknown module run by Node. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-ops: the reference crate for wai-ops/1 (WHG1, plans, interpreter, stage operators, lowerings)
A new crate, wai/wai-ops: no_std with alloc, no dependencies. - xint: a 512-bit signed integer with the saturation of integer-operators §8.1. - json: a reader that keeps numbers as written, and the canonical writer of §8.5. - graph: WHG1 parse and write, load steps 1–6 of §10.5. - plan: the load-time plan (step 7) and the run-time plan (§4). - interp: every graph operator of §5, exact in i128, with the policies and the sequence state of §10.3. - stage: E1–E13; E1 with both escapes, both end rules and both table rules, E8 total with every refusal stream_exhausted. - lower: int_synth/1, whm1/1, wam1/1, wmb1/1, world/1 and jpegai-int/1 (§13.6.1), each writing §13.0's canonical bytes. Load step 8 (the bounds pass and the verdict) is not built: without the `uncertified` feature every graph is refused at step 8; with it, step 8 is skipped. tests/goldens.rs lowers every committed set and decodes its committed payload through the interpreter and the stage operators, and every output digest reproduces: the four int_synth sets, both world clips frame by frame, the int_hyper tiny set, splat, audio and int_mlicpp. Opt-in, against data that is not committed: the jpegai scale path and both mANS decodes equal the legacy decoder's every intermediate on a real codestream, and E8 equals the reference encoder's streams and tables. Co-Authored-By: Claude Opus 5.5 <[email protected]>