name: WAI conformance # WAI's load-bearing claim is bit-exact reconstruction on every machine, # no tolerance parameter. This workflow enforces it mechanically: every # cargo-class corpus — and the integer-exact neural decoders, which make the # same promise (the registry's NeuralIntegerExact class: i64-only, no float # ONNX) — is re-derived on every OS/arch leg of the matrix below (x86-64 and # arm64) and must reproduce its frozen BLAKE3 hashes; and the integer # byte-equality goldens (rANS / int_synth / JPEG-AI mANS, generated once on # a reference machine) must decode identically everywhere. All of it is pure # Rust (no C codec chain, no ONNX Runtime), so the matrix needs no system # dependencies. # One run per branch at a time. A push supersedes the run before it. # # There is one `macos` runner and it is the dev Mac, so every macOS job in this # repo queues on it. With no concurrency group, a session pushing four versions # of a branch queued four complete sets of runs and every one of them had to # drain: on 2026-10-05 a PR's 21 contexts settled none in 70 minutes behind a # backlog of 25 runs, and the queue grew faster than it cleared. Only the newest # commit's verdict is wanted, so the older runs are cancelled. # # Verified on this forge (Forgejo 16.0.5) in `ci-test` before being added here: # the key parses, and a newer push moves an older run to `cancelled` even while # it is still queued, which is the case that matters. # # `cancel-in-progress: true` also applies to `main`. That is deliberate and # safe here: main advances by merge commits whose tree contains the commits # before them, so the newer run covers the older one's changes. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: pull_request: paths: - 'wai/wai-rs/**' # wai-rs path-depends on wai-quantum, and the quantum corpora below are # verified through it: a change there changes what this workflow checks. - 'wai/wai-quantum/**' # The integer decoders that decode through the integer operator set depend on it. - 'wai/wai-ops/**' - 'wai/*-conformance/**' - 'wai/byte-exact-conformance/**' # The registry export and the two library tests that read files outside # wai-rs (the codec glossary, SPEC.md) must fire this workflow too: a # hand edit of an exported file, of SPEC §5 or of the glossary is checked # here. vocab/v1's and v2's pin terms are checked by a library test. - 'wai/registry/**' - 'wai/vocab/**' - 'wai/glossary/**' - 'wai/SPEC.md' - 'wai/REGISTRY.md' # A library test checks SPEC §5's pinned integer payloads against this # extension's sections, so an edit of it is checked here too. - 'wai/extensions/integer-payloads.md' # A library test (staged::tests::staged_delivery_text_lists_the_codes) checks # that this extension's §4.2 and A.6 list the codes the sink reports. - 'wai/extensions/staged-delivery.md' # A library test (codecs::registry::tests::wire_identifiers_are_in_their_documents) # checks every wire identifier against the section of these texts it names, and # staged::moq::tests::moq_streaming_format_lists_the_codes checks §4.1's codes. - 'wai/extensions/http-delivery.md' - 'wai/extensions/moq-streaming-format.md' - 'wai/extensions/jwp-receipts.md' # The quantum referee requires this extension's Appendix B to state its phase tables. - 'wai/extensions/quantum-sim.md' # tests/live_events.rs requires this extension's §9 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/live-events.md' # tests/live_room.rs requires this extension's §11 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/live-rooms.md' # tests/capture_take.rs requires this extension's §12 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/capture-binding.md' # tests/live_compose.rs requires this extension's §10 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/live-compose.md' # tests/live_record.rs requires this extension's §9 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/live-recording.md' # tests/timed_text.rs requires this extension's §12 to list the codes the reference # reports, and the registry's wire identifiers test reads its sections. - 'wai/extensions/timed-text.md' # tests/access_services.rs requires this extension's §10 to list the codes the reference # reports, access_services_verify.py reads that table, and the registry's wire # identifiers test reads its sections. - 'wai/extensions/access-services.md' # tests/live_metering.rs requires this extension's §9 to list the codes the reference # reports, live_metering_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/live-metering.md' # tests/energy_steering.rs requires this extension's §10 to list the codes the reference # reports, energy_steering_verify.py reads that table, and the registry's wire # identifiers test reads its sections. - 'wai/extensions/energy-steering.md' # tests/live_moderation.rs requires this extension's §10 to list the codes the reference # reports, live_moderation_verify.py reads its §9.5, §9.6 and §10 tables, and the # registry's wire identifiers test reads its sections. - 'wai/extensions/live-moderation.md' # tests/live_watermark.rs requires this extension's §11 to list the codes the reference # reports, live_watermark_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/forensic-watermark.md' # e2ee_verify.py reads this extension's §13 table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/confidentiality.md' # tests/live_ads.rs requires this extension's §10 to list the codes the reference # reports, live_ads_verify.py reads that table, and the registry's wire identifiers test # reads its sections. - 'wai/extensions/live-ads.md' # tests/ad_presentation.rs requires this extension's §11 to list the codes the reference # reports, ad_presentation_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/ad-presentation.md' # The ad-presentation step runs the browser client's reference producer against the # corpus. - 'joule-code/joule-code-rs/crates/joule-moq-web/web/ads/**' # tests/live_provenance.rs requires this extension's §12 to list the codes and the C2PA # codes the reference reports, c2pa_live_verify.py reads that table, and the registry's # wire identifiers test reads its sections. - 'wai/extensions/live-provenance.md' # tests/derive_edge.rs requires this extension's §9 to list the codes the reference # reports and its §4 the derivations, edge_verify.py reads both tables, and the # registry's wire identifiers test reads its sections. - 'wai/extensions/deriving-edge.md' # tests/synthesis.rs requires this extension's §12 to list the codes the reference # reports and its §10.2 table to pin the reference's icons, synthesis_verify.py reads # both, tests/synthesis_mark.rs and synthesis_mark_verify.py read its scheme's # definition, generator, figures, table and claims (§7.4 to §7.5.8), and the registry's # wire identifiers test reads its sections. - 'wai/extensions/synthesis.md' # tests/exact_upscale.rs requires this extension's §8 to list the codes the reference # reports, upscale_verify.py reads that table, and the registry's wire identifiers test # reads its sections. - 'wai/extensions/exact-upscale.md' # tests/ai_usage.rs requires this extension's §9 to list the codes the reference reports, # ai_usage_verify.py reads that table, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/ai-usage.md' # tests/contribution.rs requires this extension's §11 to list the codes the reference # reports, contribution_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/contribution.md' # tests/settlement.rs requires this extension's §11 to list the codes the reference # reports, settlement_verify.py reads that table, and the registry's wire identifiers test # reads its sections. - 'wai/extensions/settlement.md' # tests/browser_sink.rs requires this extension's §11 to list the codes the reference # reports, browser_sink_verify.py reads its §2, §4.1, §4.2 and §11 tables and # capability-constraints' §3.1 register, and the registry's wire identifiers test reads # its sections. - 'wai/extensions/browser-sink.md' - 'wai/extensions/capability-constraints.md' # The browser sink's functions for a page, held to the same corpus natively. - 'wai/wai-live-web/**' # tests/takedown.rs requires this extension's §11 to list the codes the reference # reports, takedown_verify.py reads that table, and the registry's wire identifiers test # reads its sections. The registry of clocks it reads is under wai/registry/ above. - 'wai/extensions/takedown.md' # tests/co_performance.rs requires this extension's §10 to list the codes the reference # reports, co_performance_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/co-performance.md' # tests/age_assurance.rs requires this extension's §11 to list the codes the reference # reports, age_assurance_verify.py reads that table, and the registry's wire identifiers # test reads its sections. - 'wai/extensions/age-assurance.md' # tests/influence.rs requires this extension's §9 to list the codes the reference adds, # influence_verify.py reads that table, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/influence.md' # tests/direction.rs requires this extension's §13 to list the codes the reference reports, # direction_verify.py reads that table, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/direction.md' # tests/bearer_receipts.rs requires this extension's §10 to list the codes the reference # reports, and bearer_verify.py reads that table. - 'wai/extensions/bearer-receipts.md' # tests/exploration.rs requires this extension's §13 to list the codes the reference # reports and its §3.2 table to name the reference's descriptors, exploration_verify.py # reads §13, and the registry's wire identifiers test reads its sections. - 'wai/extensions/exploration.md' # tests/co_watch.rs requires this extension's §12 to list the codes the reference reports, # co_watch_verify.py reads that table, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/co-watch.md' # The co-watch step runs the browser client's co-watch module against the corpus. - 'joule-code/joule-code-rs/crates/joule-moq-web/web/room/cowatch*' # tests/dred_exact.rs requires this extension's §8 to list the codes the reference # reports and its §4 to state the reference's digests, tests/dred_exact_measure.rs its §6 # table, dred_verify.py reads §4 and §8, and the registry's tests read SPEC §5 against it. - 'wai/extensions/opus-dred.md' # tests/telemetry_aggregate.rs requires this extension's §11 to list the codes the # reference reports, telemetry_aggregate_verify.py reads that table, and the registry's # wire identifiers test reads its sections. - 'wai/extensions/telemetry-aggregation.md' # tests/telemetry_aggregate.rs requires §3.4's table to class the keys the reference # classes, and telemetry_aggregate_verify.py reads that table and §4.1 and §4.2's shards. - 'wai/extensions/delivery-telemetry.md' # tests/exact_tonemap.rs requires this extension's §9 to list the codes the reference # reports and its §6 to state the corpus's measurement, tonemap_verify.py reads §3.3's # table, §5.4's constant and §9, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/exact-tonemap.md' # tests/robustness.rs requires this extension's §12 to list the codes the reference # reports and its §4 to register the reference's transforms, robustness_verify.py reads # both, and the registry's wire identifiers test reads its sections. - 'wai/extensions/robustness-evidence.md' # tests/splat_exact.rs requires this extension's §10 to list the codes the reference # reports and the draft schema under extensions/gltf/ to name §3.2's members, # splat_exact_verify.py reads §10, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/splat-exact.md' - 'wai/extensions/gltf/**' # splat_exact_verify.py decodes each payload with this tool's whm1/1 lowering and # interpreter. - 'wai/tools/wai_ops_check.py' # tests/pq_signatures.rs requires this extension's §8 to list the codes the reference # reports, pq_verify.py reads that table, and the registry's wire identifiers test reads # its §2. - 'wai/extensions/pq-signatures.md' - 'wai/wai-web/**' # The audio provenance check below reads the corpora above with this tool. - 'wai/tools/wai_audio_provenance_check.py' - '.github/workflows/wai-conformance.yml' # No global `shell:` default. The Windows runner is a host executor whose # `bash` is the WSL stub (a different OS), so shell-specific steps below pick # their shell per-OS: bash on unix, pwsh on Windows. Bare `cargo …` steps take # each runner's native default, which runs cargo identically either way. The # Windows legs are out of the matrices for now (see the comment on each matrix); # their pwsh steps stay, inactive, so restoring a leg is a one-line change. schedule: - cron: '20 5 * * *' jobs: # Does this pull request's own diff touch the paths below? This forge matches a # workflow's `paths:` against the push, so a merge of main into a branch fires the # workflow whatever the pull request changes; every job here waits on this answer. # A push to main, a schedule, or anything the script cannot determine answers # `true` (scripts/pr-touches-paths.py). relevant: name: does this change touch it runs-on: linux-arm64 outputs: run: ${{ steps.gate.outputs.run }} steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - id: gate run: | set -euo pipefail r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-conformance.yml \ "${{ github.event.pull_request.base.sha }}" \ "${{ github.event.pull_request.head.sha }}") echo "this change touches wai-conformance: $r" echo "run=$r" >> "$GITHUB_OUTPUT" cargo-classes: needs: relevant if: needs.relevant.outputs.run == 'true' name: cargo-class corpora · ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: # Self-hosted fleet labels. Both architectures: x86_64 by linux, arm64 # by linux-arm64 + macos — what matters for the Fx integer floor is the # arch, not the OS. No Intel-Mac runner exists in the fleet, and it # would add no arch coverage anyway. # Windows x86_64 leg removed 2026-09-30: runner offline. Restore by # re-adding `windows` here once the runner is back online. os: [linux, linux-arm64, macos] steps: - uses: actions/checkout@v5 # unix: the docker runners (linux / linux-arm64) ship no Rust, so rustup # is bootstrapped; the macOS `host` runner has it but launchd's PATH omits # ~/.cargo/bin. dtolnay/rust-toolchain is unusable — it calls a `rustup` # the docker image lacks. - name: Install Rust 1.98.0 (unix) if: matrix.os != 'windows' shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0 rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 rustup component add --toolchain 1.98.0 clippy echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # Windows: a host executor with rustup already installed. Only ensure the # pinned toolchain is present + default. pwsh, never bash (that is WSL here). - name: Install Rust 1.98.0 (Windows) if: matrix.os == 'windows' shell: pwsh run: | rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 - name: Build the cargo classes (pure Rust, no C codec chain) working-directory: wai/wai-rs # neural_int joins the pure-Rust set: the integer-synthesis decoder is # i64-only (no ONNX, no float), so it carries the same bit-exact promise # and is checkable on this matrix with no ONNX Runtime present. receipt_claims # is in the set because the reference meters (wai_meter, wai_world_meter) write a # measurement report by default and require it: without it they would drop out # of this build on every leg of this matrix, without a word. staged and the integer # media features build the staged-delivery core, its corpus tool and `wai stage`; # stage_measure builds the staged-measurement core and wai_stage_measure; telemetry # the delivery-telemetry mapping and wai_telemetry; http the HTTP delivery binding, # its corpus tool and `wai http`. run: cargo build --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,receipt_claims,staged,video_int,audio_int,splat_int,stage_measure,telemetry,http # video_package runs the package receipt's dedup tests, which content_dedup feeds. # The dev profile keeps overflow checks on, so an arithmetic overflow in the HTTP # binding (http_binding::tests, among them a seeded test of every parser of untrusted # input) fails here rather than wrapping. - name: Library unit tests (the fixed-point determinism floors) working-directory: wai/wai-rs run: cargo test --lib --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,oer,receipt_claims,key_discovery,staged,video_int,audio_int,splat_int,stage_measure,telemetry,video_package,http # The JPEG AI exact decoder reproduces across platforms only if no platform math # library is on its path. Two guards, each failing the step: clippy's # disallowed-methods (wai-rs/clippy.toml), which each module on the decode path # denies, rejects a listed float method however it is spelled; and # tests/jpegai_decode_symbols.rs lists the linked decoder's symbols with `nm` and # rejects any C math-library function it imports, whatever made the call, and any # it defines other than the round-to-integral ones (see its doc). `-A clippy::all` # keeps the output to that guard. Unix legs only: `nm` is not on the Windows # runner, and for clippy the unix legs already cover both architectures. - name: JPEG AI exact decode calls no platform math library (unix) if: matrix.os != 'windows' shell: bash working-directory: wai/wai-rs run: | set -euo pipefail cargo clippy --lib --no-default-features --features neural_int -- -A clippy::all cargo test --no-default-features --features world,audio_scene,haptic,splat4d,score,provenance,neural_int,film --test jpegai_decode_symbols # Each extension container refuses a count its bytes cannot hold, without reserving # it first (found by the coverage-guided fuzzer, wai-rs/fuzz/, target `containers`), # and a declared duration past the reader limits it shares with SPEC §2. - name: Extension containers reserve no more than their bytes hold, and are held to their duration limits shell: bash working-directory: wai/wai-rs run: cargo test --no-default-features --features world,audio_scene,haptic,splat4d,score,film --test container_reservations --test extension_duration_limits # The integer decoders run fast kernels (src/int_kernels.rs) that must give # the same integer as the scalar reference kernels for every output element. # The feature list above leaves out audio_int, video_int, world_int and # splat_int, so without these two steps int_audio's kernel-equivalence tests # and tests/int_kernels_vectors.rs (every committed integer-decoder vector # decoded under the reference and under each fast policy, against its frozen # hash) would run nowhere. `--lib` also carries the other kernels' equivalence # modules; tests/int_kernels_geometry.rs runs edge geometry (strides up to # usize::MAX, padding far beyond the kernel) through the public decoders # under every policy. Both profiles, because the overflow-parity tests assert # different things in each: with overflow checks on (dev) that the fast path panics # where the reference panics, with them off (release) that it returns the # same integers. All pure Rust, so every leg runs them. # tests/int_synth_ops.rs holds wai.neural.int_synth to its lowering through the # integer operator set (extensions/integer-operators.md §13.1): every committed set # lowers to its committed graph and loads with its certificate's verdict, decodes # through it to every committed golden, and refuses whatever the direct decode # refuses. tests/int_ops_differential.rs (feature legacy_int: the direct decode, # test-only) decodes random sets and payloads both ways: the same output or both # refused, except on the planned breaks of integer-operators §15.3, where the decode # through the operator set refuses. wai-ops-differential.yml runs it for an hour in # each profile, nightly. tests/int_splat_ops.rs holds wai.splat.int_codec to its # lowering whm1/1 the same way (integer-operators §13.2): its committed set lowers, # from its bytes and from the model this crate parses, to its committed graph, and # loads with its certificate's verdict. tests/int_audio_ops.rs does the same for # wai.audio.int_codec and its lowering wam1/1 (§13.3), and tests/int_hyper_ops.rs # for wai.neural.int_hyper and the keyframe of wai.video.int_hyper (whm1/1: h_s, # then g_s with the RGB8 step), and tests/int_mlicpp_ops.rs for wai.neural.int_mlicpp # (wmb1/1: h_s, entropy, then g_s with the RGB8 step), and tests/int_world_ops.rs for # wai.world.model's integer renderer (world/1, informative: T with its action planes, # then g_s with the RGB8 step). # tests/int_mlicpp.rs decodes the committed wai.neural.int_mlicpp vector against # its pinned hashes (image, every scale bucket, every symbol) under every kernel # policy and thread count, and checks that damaged payloads are refused rather than # overflowing — which is why it runs in both profiles too. # tests/int_mlicpp_preflight.rs (its own binary: it installs a counting global # allocator) checks that a header the model cannot fit is refused before the # decode allocates anything sized from it. # tests/int_audio.rs and tests/int_splat.rs decode the committed wai.audio.int_codec and # wai.splat.int_codec vectors against the hashes the Python integer reference computed at # export, and check each vector's metadata. `--lib` runs int_payload's unit tests: each # binary payload (WIV1, WIH1, WIA1, WIS1) against the JSON it is converted from, under # every kernel policy, and decode_int for every integer capability in this build, which # has no `neural`. tests/int_payload.rs refuses every fixture of int-payload-conformance # with its code, every strict prefix of every payload, and runs a byte-change sweep in # which nothing may panic; tests/int_payload_preflight.rs (its own binary, a counting # allocator) checks that a header past the caps is refused before anything sized from it # is allocated; tests/int_payload_cost.rs (its own binary, a live-bytes allocator) checks # that int_payload::declared_cost bounds what each decode holds, with the store of loaded # sets off, then on (a decode that loads its set, and one that finds it held), that the # store counts at least the bytes it holds, and, in the release step only, decodes a # 2^30-byte clip a 3 KB payload codes; tests/int_set_cache.rs checks that store under # the decodes: a second decode through a set is a hit with the same bytes on every # committed vector, sets one byte apart never share an entry, a refused set stays # refused, refusals keep their codes, and the least recently used set goes first; # tests/int_world_memory.rs (its own binary, the same allocator) checks that the world # renderer, with its set loaded, holds no more than the direct renderer it replaced. # tests/int_video_enc_memory.rs # (its own binary, the same allocator) checks that int_video_enc::working_bytes bounds # what the encoder holds. tests/staged_resources.rs (its # own binary, a counting allocator) checks that the staged sink's work and memory per # layer grow linearly in the layer's units, that a layer past the chain budget is # refused before any stream is decoded, that what no unit holds is dropped, and that a # WIR1 parse holds no more than its declared working bytes. tests/stage_measure.rs counts every # committed staged envelope as exactly its length, refuses JSON, base64 and another capability's # format, and evaluates a measured title read from a map of files to its golden, refusing a # changed byte of a layer, the base, the source or a parameter-set file (extensions/ # staged-measurement.md). Cargo.toml declares them, and the other # feature-gated targets named here, with required-features, so if this step ever loses a # feature, cargo stops with an error instead of compiling an empty binary that reports ok. # Each committed vector's decoded output is also checked against the SHA-256 in # its sha256.json sidecar (SPEC §7 *Digests*), and # int_kernels_vectors::every_decoded_output_states_a_sha256 requires a sidecar, # or a named exclusion, for every corpus directory. tests/generate.rs checks the # wai.generate.spectral vectors, which `generate` enables: the 96x96 vector, sizes.json # and instr-v0.json, the instruction object of form v0 (SPEC §5), whose two larger # listed sizes run only in the release step (seconds each in a debug build). # tests/cli_generate_score.rs runs `wai generate` and `wai score build|render`, which # the features `generate` and `score` build into the `wai` binary: every pin it prints # against those vectors and score-conformance/ (pcm_sha256 among them), every object # instr-v0.json lists as accepted (one at each bound) made and wrapped, every object # it lists as refused refused for the reason it states, and each refusal writing # nothing; tests/generate.rs holds the same lists to a second statement of form v0. # tests/manifest_parse_memory.rs (its own binary, a counting allocator) checks that # reading a manifest allocates within the bound SPEC §2's reader limits give, at the # length limit and at the value limit, and tests/manifest_reader_equivalence.rs holds # the readers to the derived reader's result on every committed envelope. Both run in # the release step only: the first writes manifests of 2^27 bytes, which takes a debug # build most of a minute. # tests/int_video.rs, int_video_halfpel.rs and int_video_keyframe.rs hold the integer # video codec to its goldens (whole clips, half-pel motion, the keyframe through the # integer hyperprior); int_world.rs and int_world2.rs the integer world renderers; # jpegai_bitstream_calibration.rs the JPEG AI bitstream reader against the committed # codestream. No step named any of them until scripts/check-tests-in-ci.py asked. # jpegai_ops.rs holds the JPEG AI scale path (integer-operators §13.6.1) to its committed # lowered graphs and certificate here; its cases on the jpegai/v1 bundle skip here and # run in wai-jpegai-e2e.yml, which fetches the bundle and requires them. # jpegai_nets_ops.rs does the same for its other integer networks (§13.6.2): the # committed synthetic networks' lowered graphs and certificate, and every kernel # policy on them, here; its jpegai/v1 cases there. # int_video_ops.rs and wir1_ops.rs hold WIV1 and WIR1, which decode through the # operator set's stage operators with no graph (integer-operators §13.5), to their # stage forms, goldens and refusals; `i32_forms` builds E9's 32-bit form, which they # and int_ops_differential.rs hold to the exact one. - name: Fast integer kernels ≡ reference kernels (overflow checks on) working-directory: wai/wai-rs run: cargo test --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int,generate,score,staged,stage_measure,legacy_int,i32_forms --lib --test int_kernels_vectors --test int_kernels_geometry --test int_synth_ops --test int_ops_differential --test int_splat_ops --test int_audio_ops --test int_hyper_ops --test int_mlicpp --test int_mlicpp_preflight --test int_mlicpp_ops --test int_world_ops --test int_world_memory --test jpegai_ops --test jpegai_nets_ops --test int_video_ops --test wir1_ops --test int_audio --test int_splat --test generate --test cli_generate_score --test int_payload --test int_payload_preflight --test int_payload_cost --test int_set_cache --test int_video_enc_memory --test cli_stage --test staged_resources --test stage_measure --test stage_measure_bounds --test int_video --test int_video_halfpel --test int_video_keyframe --test int_world --test int_world2 --test jpegai_bitstream_calibration - name: Fast integer kernels ≡ reference kernels (release, overflow checks off) working-directory: wai/wai-rs run: cargo test --release --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int,generate,score,staged,stage_measure,legacy_int,i32_forms --lib --test int_kernels_vectors --test int_kernels_geometry --test int_synth_ops --test int_ops_differential --test int_splat_ops --test int_audio_ops --test int_hyper_ops --test int_mlicpp --test int_mlicpp_preflight --test int_mlicpp_ops --test int_world_ops --test int_world_memory --test jpegai_ops --test jpegai_nets_ops --test int_video_ops --test wir1_ops --test int_audio --test int_splat --test generate --test cli_generate_score --test int_payload --test int_payload_preflight --test int_payload_cost --test int_set_cache --test int_video_enc_memory --test cli_stage --test staged_resources --test stage_measure --test stage_measure_bounds --test manifest_parse_memory --test manifest_reader_equivalence --test int_video --test int_video_halfpel --test int_video_keyframe --test int_world --test int_world2 --test jpegai_bitstream_calibration # The integer decode path builds under each of its features alone, so a sink can take # one medium without the others, and for wasm32 (a browser sink); `int_payload` arms a # medium only under its feature, and none needs `neural`. So does the staged-measurement # core (`stage_measure`), which pulls no ONNX and reads no file on wasm32. The HTTP # binding (`http`) performs no I/O, so it builds alone and for wasm32 too. - name: Each integer feature alone, and wasm32 (unix) if: matrix.os != 'windows' shell: bash working-directory: wai/wai-rs run: | set -euo pipefail for f in neural_int video_int audio_int splat_int staged stage_measure telemetry http; do cargo check --lib --no-default-features --features "$f" done # The decode bench prints its machine line from bench_env; no other step builds it. cargo build --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int --bin wai_decode_bench rustup target add --toolchain 1.98.0 wasm32-unknown-unknown cargo check --lib --target wasm32-unknown-unknown --no-default-features --features video_int,audio_int,splat_int,staged,http # The staged-measurement core is wasm32-clean: a browser computes the same figures. # Built, not only checked, so codegen and linking of the library run for wasm32. cargo build --lib --target wasm32-unknown-unknown --no-default-features --features stage_measure # With the claim classes too: a browser sink seals its reconstruct-session claim # (jwp-receipts §2.4.12), and wai-web's measurement binding signs with them. cargo build --lib --target wasm32-unknown-unknown --no-default-features --features receipt_claims,stage_measure # So is delivery telemetry: a browser sink writes the same reports. cargo build --lib --target wasm32-unknown-unknown --no-default-features --features telemetry # carriage: every registered capability round-trips byte-exact. cli_wrap_intent and # cli_registry run the `wai` binary, which builds without the codecs feature: the # intent rule of `wai wrap`, its refusal of candidate capabilities (SPEC §5), its media # class, and `wai registry export --check` on the tree and on a drifted copy. # tests/manifest_builders.rs: the manifest types are #[non_exhaustive], and the # builders write the JSON a struct literal wrote; members the types keep only # as `extra` (and `security`) survive a round trip. # corpus_provenance: every corpus README states where its content comes from. - name: Carriage conformance, the wai CLI (wrap, registry export) and corpus provenance working-directory: wai/wai-rs run: cargo test --no-default-features --test carriage --test manifest_builders --test cli_wrap_intent --test cli_registry --test corpus_provenance # tests/cli_http.rs runs `wai http publish`, `codecs`, `origin` and `bench` as a user # does: objects named by their content hash with their head proofs, a sequence's union # and floor, the origin's headers, ranges and If-Range on loopback, and a fetch by # the byte-range procedure whose record states energy as not measured; and `hls`, # `mpd`, `seal-playlist` and `check-playlist`, whose receipts need video_manifest; # and `receipts`, an object's receipt index checked over HTTP with its signers # confirmed under a key log, which needs key_discovery: the log anchored over TLS # (cli_tls; the binary's own tests run its TLS client against servers under a test # CA, tests/fixtures/tls/), never over plaintext, and a plaintext test anchor # labelled as one. The second run builds without cli_tls: the CLI then refuses to # anchor and connects to nothing. # Cargo.toml declares it with required-features = ["http"]. tests/dash_read_bounds.rs # holds Appendix I's reader to the document's size under a counting allocator, and an # element's attributes to linear CPU time; a binary of its own, one test. - name: The wai http commands working-directory: wai/wai-rs shell: bash run: | cargo test --no-default-features --features http,video_manifest,key_discovery,cli_tls --bin wai --test cli_http --test dash_read_bounds cargo test --no-default-features --features http,video_manifest,key_discovery --test cli_http -- receipts_never_anchors_over_plaintext # tests/staged_moq.rs runs the MoQ trace of staged-conformance/moq/ (moq-streaming-format # §4.1) with signed receipts: a chain for each track, a receipt held for its parent and # admitted when it arrives, the relay's per-hop delivery timeout, dropped objects checked # by inclusion and named by the relay's delivery-gap claims, and each base's stage claim, # which seals and verifies; the subscriber of two tracks holds exactly their chains. # Cargo.toml declares it with required-features = ["staged", "video_int", "receipt_claims"]. # The interactive-world tests, which no step named: world_replay.rs (the replay # class, under `world`), world_model.rs (the signed action trace and per-frame # provenance, under `world_model`) and int_world_shared.rs (two sinks converging on # one integer world, under both). `world_model` is enabled by no other step. - name: World replay, the world model and the shared integer world working-directory: wai/wai-rs run: cargo test --no-default-features --features world_model,world_int --test world_replay --test world_model --test int_world_shared - name: Staged tracks over MoQ, with signed receipts working-directory: wai/wai-rs run: cargo test --no-default-features --features staged,video_int,receipt_claims --test staged_moq # The machine-readable registry (wai/registry/, wai/vocab/v2.*, the table in # wai/REGISTRY.md) is generated from wai-rs/src/codecs/registry.rs. Regenerate it in # memory and fail on any difference; the message says how to regenerate. One leg: the # export is the same text on every platform. - name: The registry export is up to date (linux) if: matrix.os == 'linux' working-directory: wai/wai-rs run: cargo run -q --no-default-features --bin wai -- registry export --check # The C ABI's envelope surface builds with no codec library (feature `ffi`): # unpack returns each manifest as the envelope carries it, the WAI2 table carries # every component's identity and selectability, wai_envelope_select follows # SPEC §7.1 and never picks a candidate, and the packers refuse a candidate # (SPEC §5). Cargo.toml declares the target with required-features. - name: C ABI envelope surface (no codec library) working-directory: wai/wai-rs run: cargo test --no-default-features --features ffi --test ffi_envelope # The browser crate wraps the same envelope types (wai::container), so role, # companion_of, component identity and the pin reach JS, and its pick is SPEC # §7.1's. Its tests target the pure-Rust half (`core`), which runs natively; one # leg suffices, the logic is architecture-independent. The JS surface itself runs # under wasm32 in wai-web-wasm.yml. - name: wai-web envelope surface (native tests) if: matrix.os == 'linux' working-directory: wai/wai-web run: cargo test --locked # jwp-receipts §7.1, §7.8: no `did:web`/`did:key` literal in a tracked .rs, .json or # .js file under wai/ names a real web origin — every key the tree signs with has a # published seed. Ungated: it reads the tree through `git ls-files` and classifies # with `signer_id`, which builds with no feature. - name: Every signer id in the tree is a label working-directory: wai/wai-rs run: cargo test --no-default-features --test signer_ids_are_labels # jwp-receipts §7: `wai-keys` builds a key log from operator-supplied seeds, appends # revocations and rotations, signs statuses and module grants, verifies a log as # §7.3 anchors one, and checks a DID document against it. The test drives the binary. - name: wai-keys — build, check and publish an origin key log working-directory: wai/wai-rs run: cargo test --no-default-features --features key_discovery --test wai_keys_cli # key_log has no I/O, clock or threads, so a browser sink could run it before it # instantiates a module (§7.9); no browser sink does yet. Nor do the HTTP binding's # receipts and keys (http-delivery §8.1–§8.5), which a browser client checks what it # fetched with. This step checks that both build for wasm32 on the unix legs (the # target is added to the pinned toolchain here; the Windows host runner is not set up # for it). - name: key_log and the HTTP receipts build for wasm32 (unix) if: matrix.os != 'windows' shell: bash working-directory: wai/wai-rs run: | set -euo pipefail rustup target add --toolchain 1.98.0 wasm32-unknown-unknown cargo check --lib --target wasm32-unknown-unknown --no-default-features --features key_discovery,http # The corpus-verify loop is genuinely shell-specific (a helper that groups # log output and propagates the first non-zero exit), so it ships once per # shell family. The command it runs is identical; only the wrapper differs. - name: Every cargo-class corpus reproduces its frozen hashes (unix) if: matrix.os != 'windows' shell: bash working-directory: wai/wai-rs run: | set -euo pipefail F=world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest,pq_signatures v() { echo "::group::$1"; cargo run -q --no-default-features --features "$F" --bin "$2" -- verify "$3"; echo "::endgroup::"; } v worlds wai_world_vectors ../world-conformance v spatial-audio wai_audio_vectors ../audio-conformance v haptics wai_haptic_vectors ../haptic-conformance v state-feeds wai_feed_vectors ../feed-conformance v avatars wai_avatar_vectors ../avatar-conformance v volumetric wai_splat4d_vectors ../volumetric-conformance v score wai_score_vectors ../score-conformance v int-synth wai_int_synth_vectors ../neural-conformance v film wai_film_vectors ../film-conformance v quantum wai_quantum_vectors ../quantum-conformance v quantum-ops wai_quantum_ops_vectors ../quantum-ops-conformance v oer wai_oer_vectors ../oer-conformance v jwp wai_jwp_vectors ../jwp-conformance v claims wai_claim_vectors ../claim-conformance v pin wai_pin_vectors ../pin-conformance v signers wai_signer_vectors ../signer-conformance v int-payload wai_int_payload_vectors ../int-payload-conformance v staged wai_staged_vectors ../staged-conformance v http wai_http_vectors ../http-conformance v staged-measure wai_stage_measure ../staged-measure-conformance v telemetry wai_telemetry ../telemetry-conformance v pq-signatures wai_pq_vectors ../pq-conformance # The pin corpus's second implementation: Python standard library only, sharing no # code with wai-rs. One leg is enough — it checks digests and listing rules, which # do not depend on the architecture — and the macOS host has python3. - name: The pin corpus checks against an independent verifier (macOS) if: matrix.os == 'macos' shell: bash working-directory: wai run: python3 pin-conformance/pin_verify.py pin-conformance # Every committed audio vector must come from a seeded generator. This check reads # each one to PCM (each audio base's stage 0 in the staged corpus, each measured # source over one, each spatial-audio source, every audio file under wai/) and # fails if any correlates above 0.5, at any lag, with a recording in the reference # set the host has: its system sound directory, or the directories named in # WAI_AUDIO_REFERENCE_DIRS. A generated signal stays near 0.2; a lossy coding of a # recording is near 1. A host with no reference set, or no converter to read it, # prints why and skips: the linux legs skip, the macOS leg checks. - name: No committed audio vector is a coding of a reference recording (unix) if: matrix.os != 'windows' shell: bash working-directory: wai run: | if command -v python3 >/dev/null 2>&1; then python3 tools/wai_audio_provenance_check.py else echo "audio provenance: SKIPPED — no python3 on this host" fi # OER's second implementation is portable C, not Rust. Rebuild it from source and # require its output to match the pinned corpus byte for byte: the kernel is # deterministic, and wai_oer_vectors above has already verified the pinned copy, # so equality carries that verification to what the source produces today. # `cc` with the Makefile's flags, so the step needs no `make` on the runner. - name: OER C kernel reproduces its pinned receipts (unix) if: matrix.os != 'windows' shell: bash working-directory: wai/oer-conformance/settle run: | set -euo pipefail cc -O2 -std=c99 -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare \ -o "$RUNNER_TEMP/settle_host" host_main.c settle.c sha256.c tweetnacl.c -lm "$RUNNER_TEMP/settle_host" "$RUNNER_TEMP/firmware_vectors.json" 400 cmp "$RUNNER_TEMP/firmware_vectors.json" ../firmware_vectors.json - name: Every cargo-class corpus reproduces its frozen hashes (Windows) if: matrix.os == 'windows' shell: pwsh working-directory: wai/wai-rs run: | $F = "world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest,pq_signatures" function v($grp, $bin, $path) { Write-Output "::group::$grp" cargo run -q --no-default-features --features $F --bin $bin -- verify $path if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } Write-Output "::endgroup::" } v worlds wai_world_vectors ../world-conformance v spatial-audio wai_audio_vectors ../audio-conformance v haptics wai_haptic_vectors ../haptic-conformance v state-feeds wai_feed_vectors ../feed-conformance v avatars wai_avatar_vectors ../avatar-conformance v volumetric wai_splat4d_vectors ../volumetric-conformance v score wai_score_vectors ../score-conformance v int-synth wai_int_synth_vectors ../neural-conformance v film wai_film_vectors ../film-conformance v quantum wai_quantum_vectors ../quantum-conformance v quantum-ops wai_quantum_ops_vectors ../quantum-ops-conformance v oer wai_oer_vectors ../oer-conformance v jwp wai_jwp_vectors ../jwp-conformance v claims wai_claim_vectors ../claim-conformance v pin wai_pin_vectors ../pin-conformance v signers wai_signer_vectors ../signer-conformance v int-payload wai_int_payload_vectors ../int-payload-conformance v staged wai_staged_vectors ../staged-conformance v http wai_http_vectors ../http-conformance v staged-measure wai_stage_measure ../staged-measure-conformance v telemetry wai_telemetry ../telemetry-conformance v pq-signatures wai_pq_vectors ../pq-conformance # wai-quantum and the quantum corpus under wasm32-wasip2, run by wasmtime. On wasm32 # usize is 32 bits, so arithmetic that cannot overflow on a 64-bit host can there: a # section's offset plus its length, a capacity reserved from a count a file claims, a # shift by a qubit count. The builds are debug builds, so overflow checks are on and # such an overflow panics instead of wrapping. Three steps: # 1. tests/bit_identity.rs, which pins one result of each f64 layer, so the wasm32 # build must give the bits every native leg gives; # 2. the library's unit tests in the modules that hold the circuit core, its # container, its JSON reader and its pins (quantum, ijson, receipt_pins, # quantum_fabric, quantum_source, quantum_channel, quantum_qudit, quantum_receipt), # each required to have run, and each test of the fabric's groundwork for # accelerator members required by name (the WebGPU member itself has no wasm32- # wasip2 build; wai-quantum-webgpu.yml checks that the feature is inert there); # 3. wai_quantum_vectors verify over all four trees of quantum-conformance/ (both # capabilities, the reject corpus and the accept corpus), the same check the matrix # above runs natively. # One leg: wasm32 is the same machine on every host. Linux, so it does not queue on the # single macOS runner. quantum-wasip2: needs: relevant if: needs.relevant.outputs.run == 'true' name: quantum core and corpus under wasm32-wasip2 (wasmtime) runs-on: linux # The fabric's planner test runs fabric-v1 under every planner configuration in a # debug wasm build, several minutes on its own; the timeout leaves it room rather # than the test being skipped on wasm32. timeout-minutes: 90 steps: - uses: actions/checkout@v5 - name: Install Rust 1.98.0 with the wasm32-wasip2 target shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0 rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 rustup target add --toolchain 1.98.0 wasm32-wasip2 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # The release binary, pinned by version and SHA-256, rather than a build from source. - name: Install wasmtime 49.0.2 shell: bash run: | set -euo pipefail [ "$(uname -m)" = x86_64 ] || { echo "::error::the pinned wasmtime archive is x86_64; this host is $(uname -m)"; exit 1; } if ! command -v xz >/dev/null 2>&1; then SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo" $SUDO apt-get update -qq $SUDO apt-get install -y -qq xz-utils fi v=49.0.2 f="wasmtime-v$v-x86_64-linux.tar.xz" curl --proto '=https' --tlsv1.2 -sSfL -o "$RUNNER_TEMP/$f" \ "https://github.com/bytecodealliance/wasmtime/releases/download/v$v/$f" echo "a4d6e9e3a5a60f527cf7793d674c48930c80c2e8977995b8a275cad3254b9322 $RUNNER_TEMP/$f" | sha256sum -c - tar -xJf "$RUNNER_TEMP/$f" -C "$RUNNER_TEMP" echo "$RUNNER_TEMP/wasmtime-v$v-x86_64-linux" >> "$GITHUB_PATH" - name: tests/bit_identity.rs under wasmtime working-directory: wai/wai-quantum env: CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime run: cargo test --locked --target wasm32-wasip2 --features full --test bit_identity # The filters are module paths, so a module that is renamed or loses its tests would # leave its filter matching nothing and the run passing; the loop fails the step # unless every module had a test that passed. - name: The circuit core's unit tests under wasmtime shell: bash working-directory: wai/wai-quantum env: CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime run: | set -euo pipefail mods="quantum ijson receipt_pins quantum_fabric quantum_source quantum_channel quantum_qudit quantum_receipt" filters=() for m in $mods; do filters+=("$m::"); done cargo test --locked --target wasm32-wasip2 --features full --lib -- "${filters[@]}" 2>&1 \ | tee "$RUNNER_TEMP/wasip2-lib.log" for m in $mods; do grep -q "^test $m::.* \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" \ || { echo "::error::no test of $m ran"; exit 1; } done # The fabric's groundwork for accelerator members (certification one case at # a time, the fabric-v1 corpus and its pins, the 32-bit-lane words and their # range guard, run meters, metered calibration, placement for a run and the # fabric's fallback, the program a member runs in every planner configuration, # the WGSL kernels' host layouts, member ids and mutants), each by name: a module # filter is satisfied by any one test of the module, so a test dropped or # compiled out on wasm32 would otherwise go unnoticed. for t in quantum_fabric::tests::certification_is_certify \ quantum_fabric::tests::fxmul_wide_is_the_exact_product \ quantum_fabric::tests::apply_words_is_apply \ quantum_fabric::tests::malformed_words_are_refused \ quantum_fabric::tests::z_on_the_most_negative_lane_is_flagged \ quantum_fabric::tests::simulate_checked_is_simulate \ quantum_fabric::tests::a_rounded_product_is_never_negated \ quantum_fabric::tests::the_guard_horizon_is_pinned \ quantum_fabric::tests::valid_circuits_stay_in_lanes \ quantum_fabric::tests::fabric_corpus_starts_with_random_v1 \ quantum_fabric::tests::the_fabric_v1_corpus_of_each_gateset_is_pinned \ quantum_fabric::tests::fabric_v1_covers_every_dispatch_shape \ quantum_fabric::tests::gate_words_are_the_table \ quantum_fabric::tests::a_meter_reading_is_labelled_or_dropped \ quantum_fabric::tests::a_placement_figure_is_a_measurement_or_nothing \ quantum_fabric::tests::figures_go_on_both_members_or_neither \ quantum_fabric::tests::place_for_sends_small_runs_to_the_cpu_and_large_ones_to_the_gpu \ quantum_fabric::tests::the_fabric_falls_back_and_names_the_member_that_produced_the_result \ quantum_fabric::tests::a_metered_fabric_run_seals_its_reading \ quantum_fabric::tests::a_calibration_gives_the_cpu_reference_its_figure \ quantum_fabric::plan::tests::execute_is_the_native_simulator \ quantum_fabric::plan::tests::every_configuration_is_the_native_simulator \ quantum_fabric::plan::tests::long_circuits_tile_as_they_run_gate_by_gate \ quantum_fabric::plan::tests::tiles_are_exact_on_any_words \ quantum_fabric::plan::tests::tiles_cover_every_path \ quantum_fabric::plan::tests::the_v1_tail_phases_are_not_skipped \ quantum_fabric::plan::tests::malformed_programs_are_refused \ quantum_fabric::wgsl::tests::implementation_id_is_pinned \ quantum_fabric::wgsl::tests::gate_record_layout \ quantum_fabric::wgsl::tests::grids_cover_every_item_once \ quantum_fabric::wgsl::tests::the_index_map_is_a_bijection \ quantum_fabric::wgsl::tests::member_ids_are_pinned \ quantum_fabric::wgsl::tests::the_cpu_reference_is_placed_first_when_nothing_is_metered \ quantum_fabric::wgsl::tests::mutants_apply_once \ quantum_fabric::wgsl::tests::mutant_witnesses_exist \ quantum_fabric::wgsl::tests::placement_breaks_an_implementation_tie_by_name \ quantum_fabric::wgsl::tests::tile_implementation_id_is_pinned \ quantum_fabric::wgsl::tests::tile_records_layout \ quantum_fabric::wgsl::tests::tile_grids_cover_every_tile_once \ quantum_fabric::wgsl::tests::tile_mutants_apply_once \ quantum_fabric::wgsl::tests::tile_mutant_witnesses_exist; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" \ || { echo "::error::$t did not run"; exit 1; } done # The wai package is built as one codegen unit here. Its lib target is also a cdylib, # and the wasm linker in Rust 1.98 (LLD 22) can crash with SIGSEGV linking that cdylib: # the linker keeps the flags of the first object that names the function table, so # when that object names it without NO_STRIP the table is no garbage-collection root. # Nothing the cdylib keeps calls through the table, but it does keep function # addresses, and writing their element segment then dereferences a table that was # never created. Which object comes first follows the hashed names of the codegen # units, so an unrelated change to the crate, or a different checkout path, can bring # the crash on or off. As one unit, wai's object comes first and takes function # addresses, so it names the table with NO_STRIP. LLD 23 keeps NO_STRIP from any # object. The units change how the crate is split for code generation, not what the # program computes. - name: wai_quantum_vectors verify under wasmtime shell: bash working-directory: wai/wai-rs run: | set -euo pipefail cargo build --locked --target wasm32-wasip2 --no-default-features --features quantum --bin wai_quantum_vectors \ --config 'profile.dev.package.wai.codegen-units=1' wasmtime run --dir ../quantum-conformance::/corpus \ target/wasm32-wasip2/debug/wai_quantum_vectors.wasm verify /corpus # The generated v2 vocabulary (wai/vocab/v2.*) is checked as a consumer uses it: # sample manifests, typed and untyped, WAI1 and WAI2, are expanded through the # JSON-LD context exactly as written on the wire and validated against the SHACL # shapes, each with the result it must give (a candidate in any place is # rejected; a media value no revision lists is accepted). One leg: RDF tooling, # not arithmetic. The tool versions are pinned. vocab-shapes: needs: relevant if: needs.relevant.outputs.run == 'true' name: v2 vocabulary · manifests validate as stated runs-on: linux-arm64 steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install the RDF tools shell: bash run: python -m pip install rdflib==7.6.0 PyLD==3.3.0 pyshacl==0.40.1 - name: Sample manifests against vocab/v2.shapes.ttl shell: bash run: python wai/vocab/check_shapes.py # The corpora above are generated and verified by wai-rs, one implementation. These are # the second implementations, written from the extension text in Python and sharing no # code with wai-rs: claim_verify.py (every claim vector, the canonical fixture, and the # bracket arithmetic of energy-measurement §6.2 recomputed with Python's integers), # differential.py (both verifiers' verdicts on generated inputs the corpus does not hold, # under a fixed seed, so a run is reproducible), jwp_verify.py (every JWP vector), and # signer_verify.py (every key-discovery vector and the canonical fixture, with its # verdicts required to equal wai_signer_vectors' line for line), and # int_payload_verify.py (the integer payloads and their refusal fixtures), and # staged_verify.py (the staged-delivery corpus), and http_verify.py (the HTTP delivery # corpus), and quantum-conformance/tools/referee.py (both quantum-sim capabilities), and # one verifier for each corpus under live-conformance/, which live-conformance/README.md # lists beside its directory, extension and generator. # Each exits non-zero on any failure or any difference, and the step fails with it. # One platform: what they check is the reading of the text, not the architecture. independent-verifiers: needs: relevant if: needs.relevant.outputs.run == 'true' name: independent verifiers · claims, JWP, key discovery and integer payloads (Python) runs-on: linux-arm64 steps: - uses: actions/checkout@v5 - name: Install Rust 1.98.0 shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0 rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - uses: actions/setup-python@v5 with: python-version: '3.11' # The ad-presentation step runs the browser client's reference producer under Node, whose # WebCrypto signs with Ed25519. - uses: actions/setup-node@v4 with: node-version: '22' # The verifiers check Ed25519's equation with the `cryptography` package and make the # rest of jwp-receipts §3.1 step 3 themselves. - name: Install the Ed25519 library shell: bash run: python -m pip install cryptography # differential.py drives wai_claim_vectors' `verdicts` mode; the key-discovery # verdicts are compared with wai_signer_vectors'. - name: Build the corpus verifiers wai-rs ships working-directory: wai/wai-rs shell: bash run: cargo build --no-default-features --features key_discovery --bin wai_claim_vectors --bin wai_jwp_vectors --bin wai_signer_vectors # The integer payload corpus's second implementation (int-payload-conformance/README): # it parses every payload with the extension's rules and check order, converts every # JSON source independently and requires the committed bytes, decodes the WIV1 # keyframe-0 payloads in full to their sidecars' SHA-256, and checks every refusal # fixture. Standard library only, so it needs nothing installed. - name: int_payload_verify.py working-directory: wai shell: bash run: python3 int-payload-conformance/int_payload_verify.py int-payload-conformance # The staged-delivery corpus's second implementation (staged-conformance/README): it # replays every case from its stage-0 buffers through its own reading of the # extension (refines, WIR1, the sink's steps, holds, batches, conflicts, deadlines, # tiers, stage hashes), decodes the WIV1 keyframe-0, PNG and FLAC bases, explodes the # WAI2 files, and replays the schedule. Standard library only. - name: staged_verify.py working-directory: wai shell: bash run: python3 staged-conformance/staged_verify.py staged-conformance # The HTTP delivery corpus's second implementation (http-conformance/README): the head, # the head proof (every committed proof rebuilt from the text), response checks, plans, # selection, the byte-range procedure and its fallback, the codecs union and floor, the # playlists (read, rendered, held adjacent, the classical master unchanged), playlist # receipts (WAI's strict Ed25519, _ed25519.py) and the live edge, and the adaptation policies, # checked first against published BLAKE3 vectors, with the standard library alone; # and the receipts, key logs, grants files and parameter sets of §8.1–§8.5, through # http_receipts.py and the corpora's own verifiers of jwp-receipts, which need the # `cryptography` package installed above (without it those cases fail, never skip). # Its mutations and the differential against wai-rs run in wai-http.yml's falsify # job. - name: http_verify.py working-directory: wai shell: bash run: python3 http-conformance/http_verify.py http-conformance # Outside the corpus: wai_http_vectors fuzz writes seeded cases (Content-Range values, # codecs values, #WAI-LAYER lines, manifests and their member types, encryption, # refines, layers declared against their bases, layers over WAI2 components, objects # past the first request through a tampering origin; playlists, adjacent pairs, # published masters, renderings, adaptation states, the integer log and changed # receipt files; receipt files, indexes, grants files and key logs of §8.1–§8.5, # whose cases need the `cryptography` package installed above) with wai-rs's # outcomes, and # http_verify.py must give every one, a refusal by the same code. It prints each # family's count of cases and of refusals. Two fixed seeds, so a run is reproducible. - name: The HTTP differential outside the corpus (wai-rs against http_verify.py) working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo build --no-default-features --features http,video_manifest,key_discovery --bin wai_http_vectors) for seed in 11 12; do wai-rs/target/debug/wai_http_vectors fuzz http-conformance --seed "$seed" --count 400 --out "$RUNNER_TEMP/http-fuzz-$seed.json" python3 http-conformance/http_verify.py cases "$RUNNER_TEMP/http-fuzz-$seed.json" http-conformance done # The staged-measurement corpus's second implementation (staged-measure-conformance/README): # it counts every object, applies every layer from its base's stage 0, computes the quality # integers, the output tree, the prefixes, the overhead points and the dedup totals itself, # and requires its decode to be the fixture tool's and its figures to be goldens.json's. # Standard library only. - name: measure_verify.py working-directory: wai shell: bash run: python3 staged-measure-conformance/measure_verify.py staged-measure-conformance # The delivery simulator's second implementation: Appendix B from the text, every case # of staged-measure-conformance/sim/ reproduced and its claim checked, with a # counter-case required for each part of the stall bound a schedule can lose. - name: sim_verify.py working-directory: wai shell: bash run: python3 staged-measure-conformance/sim_verify.py staged-measure-conformance # The simulator differentially, outside the corpus: seeded random models (a refinement # with its own delivery timeout among them) and plans, each simulated by # wai_stage_measure sim and by sim_verify.py, the refusal or the whole result, the # stall bound and the longest stall equal, and every stall within the bound where it # applies. Two fixed seeds, so a run is reproducible. - name: sim_diff.py, wai_stage_measure against sim_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo build --no-default-features --features stage_measure --bin wai_stage_measure) for seed in 1 2; do python3 staged-measure-conformance/sim_diff.py wai-rs/target/debug/wai_stage_measure "$seed" 1500 done # wai.live.events (extensions/live-events.md): the reference module's unit tests and # tests/live_events.rs (the committed corpus regenerates byte for byte from its fixed # seeds, wai-rs gives every vector, policy case and binding case its stated outcome, # the corpus covers every kind and reason, and §9 lists exactly the reference's # codes); then the corpus's second implementation, live_events_verify.py, written # from the extension's text and sharing no code with wai-rs, which verifies the same # cases with WAI's strict Ed25519 (claim-conformance/_ed25519.py) and BLAKE3 # (claim-conformance/_blake3.py), standard library only, run isolated (-I). - name: live events · wai-rs and live_events_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_events --lib live_events::) (cd wai-rs && cargo test --no-default-features --features live_events --test live_events) python3 -I live-conformance/live_events_verify.py live-conformance/events # wai.live.room (extensions/live-rooms.md): the reference module's unit tests and # tests/live_room.rs (the committed corpus regenerates byte for byte from its fixed # seeds, wai-rs gives every vector its stated outcome, every reason of §11 refuses a # vector, and §11 lists exactly the reference's codes); then the corpus's second # implementation, live_rooms_verify.py, written from the extension's text and sharing # no code with wai-rs, which verifies every event with live_events_verify.py and every # signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), standard # library only, run isolated (-I). - name: live rooms · wai-rs and live_rooms_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_room --lib live_room::) (cd wai-rs && cargo test --no-default-features --features live_room --test live_room) python3 -I live-conformance/live_rooms_verify.py live-conformance/rooms # wai.capture.take (extensions/capture-binding.md): the reference module's unit tests, # the output tree's (whose RFC 6962 hash and RFC 9162 consistency proofs the take tree # reuses), and tests/capture_take.rs (the committed corpus regenerates byte for byte # from its fixed seeds, wai-rs gives every vector its stated outcome, every reason of # §12 appears in it, and §12 lists exactly the reference's codes); then the corpus's # second implementation, capture_take_verify.py, written from the extension's text and # sharing no code with wai-rs, which verifies each room with live_rooms_verify.py and # every signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), and # requires every mutated copy of the corpus to fail; standard library only, run # isolated (-I). - name: capture take · wai-rs and capture_take_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features capture_take --lib -- capture_take:: output_tree::) (cd wai-rs && cargo test --no-default-features --features capture_take --test capture_take) python3 -I live-conformance/capture_take_verify.py live-conformance/takes # wai.live.compose (extensions/live-compose.md): the reference module's unit tests (the # layout over every grid of 1 to 64 tiles stays on its canvas with no tile overlapping # another, the fill modes, the attributes, the mixer) and tests/live_compose.rs (the # committed corpus regenerates byte for byte from its fixed seeds, wai-rs gives every # case its stated outcome, every reason of §10 refuses a case, and §10 lists exactly # the reference's codes); then the corpus's second implementation, # live_compose_verify.py, written from the extension's text and sharing no code with # wai-rs, which verifies each room with live_rooms_verify.py, steps through its # lifecycle replay to each instant itself, gives every layout, mix, descriptor, # composition and receipt the same outcome rectangle for rectangle and sample for # sample, and requires every mutated copy of the corpus to fail; standard library # only, run isolated (-I). - name: live compose · wai-rs and live_compose_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_compose --lib live_compose::) (cd wai-rs && cargo test --no-default-features --features live_compose --test live_compose) python3 -I live-conformance/live_compose_verify.py live-conformance/compose # wai.live.recording (extensions/live-recording.md): the reference module's unit tests, # the output tree's (whose range proofs it adds, tested against RFC 9162 §2.1.3.2's # check), and tests/live_record.rs (the committed corpus regenerates byte for byte from # its fixed seeds, wai-rs gives every recording and clip its stated outcome, every reason # of §9 appears in it, every take it says it reuses is capture binding's byte for byte, # and §9 lists exactly the reference's codes); then the corpus's second implementation, # live_record_verify.py, written from the extension's text and sharing no code with # wai-rs, which checks range proofs by the extension's recursion and by RFC 9162 # §2.1.3.2's own algorithm, verifies each take with capture_take_verify.py and every # signature with WAI's strict Ed25519 (claim-conformance/_ed25519.py), and requires every # mutated copy of the corpus to fail; standard library only, run isolated (-I). - name: live recording · wai-rs and live_record_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_record --lib -- live_record:: output_tree::) (cd wai-rs && cargo test --no-default-features --features live_record --test live_record) python3 -I live-conformance/live_record_verify.py live-conformance/recordings # wai.text.timed (extensions/timed-text.md): the reference module's unit tests (cue model, # annotation, WebVTT, IMSC1 and its render-model bound, timelines, disclosure, and the # 608 encoder and decoder) and tests/timed_text.rs (every file of the committed corpus, # vectors.json and each expected .vtt, .ttml and .608.hex, regenerates byte for byte # from its fixed seeds and no other file is there, wai-rs gives every case its stated # outcome, the corpus covers every 608 code path, and §12 lists exactly the reference's # codes); then the corpus's second implementation, timed_text_verify.py, written from # the extension's text and sharing no code with wai-rs, which verifies every event with # live_events_verify.py, writes every output byte for byte from the text, parses each # IMSC1 document with xml.etree, and requires every mutated copy of the corpus to fail; # standard library only, run isolated (-I). - name: timed text · wai-rs and timed_text_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features timed_text --lib timed_text::) (cd wai-rs && cargo test --no-default-features --features timed_text --test timed_text) python3 -I live-conformance/timed_text_verify.py live-conformance/captions # wai.access.services (extensions/access-services.md): the reference module's unit tests # (words, full and prefix alignment with their walk back, signed integers, gains) and # tests/access_services.rs (vectors.json and each DAPT document regenerate byte for byte # from their fixed seeds and no other file is there, wai-rs gives every vector and # document its stated outcome and figures, every reason of §10 refuses a case, and §10 # lists exactly the reference's codes); then the corpus's second implementation, # access_services_verify.py, written from the extension's text and sharing no code with # wai-rs, which verifies events and captions with timed_text_verify.py and every record # with WAI's strict Ed25519 rule, computes every figure and writes every DAPT document # itself, parses each with xml.etree, reads the extension's reason table, and requires # every mutated copy of the corpus to fail; standard library only, run isolated (-I). - name: access services · wai-rs and access_services_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features access_services --lib access_services::) (cd wai-rs && cargo test --no-default-features --features access_services --test access_services) python3 -I live-conformance/access_services_verify.py live-conformance/access # wai.live.metering (extensions/live-metering.md): the reference module's unit tests # (records and ledgers round-trip, the energy rules, the size bound at its limit, a # total of two classes told from a wrong one, funds rounding, the CMCD event-timeline # record and the application/cmcd batch, a ledger entry's audit path) and # tests/live_metering.rs (the committed corpus regenerates byte for byte from its fixed # seeds and the reference relay's recorded record, wai-rs gives every vector its stated # outcome, every reason of §9 refuses a vector, the large audience's relay record is the # lesson's size, and §9 lists exactly the reference's codes); then the corpus's second # implementation, live_metering_verify.py, written from the extension's text and sharing # no code with wai-rs, which verifies each room with live_rooms_verify.py, each take with # capture_take_verify.py and each composition receipt with live_compose_verify.py, # recomputes every unit, total and grant's consumption itself, and requires every # mutated copy of the corpus to fail; standard library only, run isolated (-I). - name: live metering · wai-rs and live_metering_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_metering --lib live_metering::) (cd wai-rs && cargo test --no-default-features --features live_metering --test live_metering) python3 -I live-conformance/live_metering_verify.py live-conformance/metering # wai.live.steering (extensions/energy-steering.md): the reference module's unit tests # (policies and decisions round-trip and their rules refuse, the window, the request # reader over HLS, DASH and CMCD, the RFC 9651 parser, exact products at their limits, # the margin at its boundary, figures compared only within a class, and a pathway with # no figure never placed first by its rank while one with a figure is within the # limits) and tests/energy_steering.rs (the committed corpus regenerates byte for byte # from its fixed seeds, wai-rs gives every request and vector its stated outcome, every # reason of §10 refuses a vector, and §10 lists exactly the reference's codes); then the # corpus's second implementation, energy_steering_verify.py, written from the # extension's text and sharing no code with wai-rs, which reads the room with # live_rooms_verify.py and the per-hop records with live_metering_verify.py, parses RFC # 9651 itself, recomputes every report, figure, decision and manifest, and requires # every mutated copy of the corpus to fail; standard library only, run isolated (-I). - name: energy steering · wai-rs and energy_steering_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features energy_steering --lib energy_steering::) (cd wai-rs && cargo test --no-default-features --features energy_steering --test energy_steering) python3 -I live-conformance/energy_steering_verify.py live-conformance/steering # wai.live.moderation (extensions/live-moderation.md): the reference module's unit tests # (policies, statements and notices round-trip and their rules refuse, the export's # strings and dates, the content types, the states that show an item) and # tests/live_moderation.rs (every file of the committed corpus, vectors.json and each # statement-of-reasons export, regenerates byte for byte from its fixed seeds and no # other file is there, wai-rs gives every room, export and clip its stated outcome, and # §10 lists exactly the reference's codes, each of which the corpus gives); then the # corpus's second implementation, live_moderation_verify.py, written from the # extension's text and sharing no code with wai-rs, which verifies each room with # live_rooms_verify.py and each clip with live_record_verify.py, writes every export # byte for byte, reads the extension's category, content-type and reason tables, and # requires every mutated copy of the corpus to fail; standard library only, run # isolated (-I). - name: live moderation · wai-rs and live_moderation_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_moderation --lib live_moderation::) (cd wai-rs && cargo test --no-default-features --features live_moderation --test live_moderation) python3 -I live-conformance/live_moderation_verify.py live-conformance/moderation # wai.audio.opus.dred.int (extensions/opus-dred.md): first the draft's weights file and # test vectors, which the corpus names by SHA-256 and does not hold, fetched from the # draft's locations and checked against its digests (live-conformance/dred/fetch.sh). # Then the reference module's unit tests (the range decoder against its encoder, the # extension draft's worked examples, payloads round-trip, weights quantized from their # bits, the activation tables, the driver on a synthetic set), tests/dred_exact.rs (the # corpus regenerates byte for byte from its seeds and the weights and no other file is # there, every payload and case reaches its outcome, §8 lists exactly the module's codes, # §4 states its digests), and in release tests/dred_exact_measure.rs (every record of the # draft's test vectors decoded through the profile and through the floating-point # network: the profile passes the draft's feature test, and §6's table is what it # measures). Then the corpus's second implementation, dred_verify.py, written from the # extension's text and sharing no code with wai-rs, which recomputes every outcome, # digest and row in its own integer arithmetic and requires every mutated copy of the # corpus to fail; standard library only, run isolated (-I). - name: opus deep redundancy · wai-rs and dred_verify.py working-directory: wai shell: bash run: | set -euo pipefail d="${RUNNER_TEMP:-/tmp}/dred" bash live-conformance/dred/fetch.sh "$d" vectors w="$d/dred_unquantized_weights.bin" (cd wai-rs && cargo test --no-default-features --features dred_exact --lib dred_exact::) (cd wai-rs && WAI_DRED_WEIGHTS="$w" cargo test --release --no-default-features --features dred_exact --test dred_exact) (cd wai-rs && WAI_DRED_WEIGHTS="$w" WAI_DRED_VECTORS="$d" cargo test --release --no-default-features --features dred_exact --test dred_exact_measure) python3 -I live-conformance/dred_verify.py live-conformance/dred "$w" # wai.live.ads (extensions/live-ads.md): the reference module's unit tests (policies and # annotations round-trip and their rules refuse, a break's identity, tags, events and # asset lists written exactly), the break form of wai.video.ssai's receipt (its JSON # carriage, each of its rules, its strict signature, the stitched form's legacy pin # unchanged), and tests/live_ads.rs (every file of the committed corpus, vectors.json and # each room's HLS tags, regenerates byte for byte from its fixed seeds and no other file # is there, wai-rs gives every room its stated outcome, and §10 lists exactly the # reference's codes, each of which the corpus gives); then the corpus's second # implementation, live_ads_verify.py, written from the extension's text and sharing no # code with wai-rs, which verifies each room with live_rooms_verify.py, writes every tag, # event and asset list byte for byte, verifies every receipt with WAI's strict Ed25519 # rule and BLAKE3 from claim-conformance, reads the extension's reason table, and # requires every mutated copy of the corpus to fail; standard library only, run isolated # (-I). - name: live ads · wai-rs and live_ads_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_ads --lib live_ads::) (cd wai-rs && cargo test --no-default-features --features live_ads --lib wai_video_ssai::) (cd wai-rs && cargo test --no-default-features --features live_ads --test live_ads) python3 -I live-conformance/live_ads_verify.py live-conformance/ads # wai.live.ad_presentation (extensions/ad-presentation.md): the reference module's unit # tests (claims round-trip and their rules refuse, the quartile, the qualifying run, the # touched objects, a policy's presentation fields, RFC 9577's TokenChallenge) and # tests/ad_presentation.rs (every file of the committed corpus regenerates byte for byte # from its fixed seeds and no other file is there, RFC 9578's own token verifies under its # key, wai-rs gives every room its outcome and every claim its verdict, and §11 lists # exactly the reference's codes); then the corpus's second implementation, # ad_presentation_verify.py, written from the extension's text and sharing no code with # wai-rs, which verifies each room with live_ads_verify.py, judges every claim and its # RSASSA-PSS itself, requires every mutated copy of the corpus to fail and catches each of # its own checks dropped; standard library only, run isolated (-I). Last, the browser # client's reference producer (joule-moq-web/web/ads), which records observation # sequences into spans and writes and signs the corpus's claims from them, byte for byte. - name: ad presentation · wai-rs, ad_presentation_verify.py and the reference producer working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_ads --lib live_ads::presentation::) (cd wai-rs && cargo test --no-default-features --features live_ads --test ad_presentation) python3 -I live-conformance/ad_presentation_verify.py live-conformance/presentation node --test ../joule-code/joule-code-rs/crates/joule-moq-web/web/ads/presentation.test.mjs # wai.live.provenance (extensions/live-provenance.md): the reference module's unit tests # (boxes, chunks, emsg and the BMFF hash; the JUMBF store; COSE_Sign1 and the OKP key; # certificates written and read, their profile and chain; identifiers, track renderings, # dates and the compositor's source type) and tests/live_provenance.rs (every file of the # committed corpus regenerates byte for byte from its fixed seeds and the packaging # corpus's AV1 floor, and no other file is there; wai-rs gives every vector its stated # outcome; every reason of §12 refuses a vector; §12 lists exactly the reference's codes # with the two C2PA codes it reports); then the corpus's second implementation, # c2pa_live_verify.py, written from the extension's text and sharing no code with # wai-rs, which reads CBOR, ISO BMFF, JUMBF, COSE and X.509 DER itself, verifies every # signature with WAI's strict Ed25519 rule and every receipt with BLAKE3 from # claim-conformance, reads the extension's reason table, and requires every mutated copy # of a good vector to be refused; standard library only, run isolated (-I). - name: live provenance · wai-rs and c2pa_live_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_provenance --lib live_provenance::) (cd wai-rs && cargo test --no-default-features --features live_provenance --test live_provenance) python3 -I live-conformance/c2pa_live_verify.py live-conformance/c2pa-live # wai.media.synthesis (extensions/synthesis.md): the reference module's unit tests (the # pinned derivations by their rules, the class lattice, a generator's envelope) and # tests/synthesis.rs (the committed corpus regenerates byte for byte from its fixed seeds # and no other file is there, wai-rs gives every case its stated outcome and statements, # §12 lists exactly the reference's codes, each of which the corpus gives, and §10.2's # table pins exactly the reference's icons); then the corpus's second implementation, # synthesis_verify.py, written from the extension's text and sharing no code with wai-rs, # which runs the pinned derivations and writes each digital source type and C2PA # statement itself, verifies each room with live_rooms_verify.py and every record with # WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's icon # and reason tables, and requires every mutated copy of the corpus to fail; standard # library only, run isolated (-I). - name: synthesis provenance · wai-rs and synthesis_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features synthesis --lib synthesis::) (cd wai-rs && cargo test --no-default-features --features synthesis --test synthesis) python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis # The registered watermark schemes wai-mark:tent64 and wai-mark:tent64s # (extensions/synthesis.md §7.4 to §7.9): the reference's unit tests (the code corrects 29 # errors and its generator is the definition's, the layouts, the embedding and the # detector in every orientation, the tiled detector's exact autocorrelation and its # recovery from a crop and a rotation, the battery's resampling, rotation and keyframe), # then tests/synthesis_mark.rs in release, since it embeds and attacks every picture of # the measurement sets under both schemes (every file of live-conformance/synthesis-mark/ # regenerates byte for byte, both measurements among them, and no other file is there; # every embedding, detection and case gets what it states; the extension's definitions, # generator polynomial and shuffles are the reference's; §7.5.8 and §7.9.7 claim only # attacks the measurements show survived, and §7.5.6's and §7.9.5's figures are the # measurements'); then the second implementation, synthesis_mark_verify.py with # _wai_mark.py, written from the extension's text and sharing no code with wai-rs, which # embeds, detects and decodes itself, both stages of the tiled detector among them, runs # the battery's picture attacks, derives the frames the vectors name, verifies every case # with synthesis_verify.py, mutates copies of the corpus and weakens its own verifier in # turn; standard library only, run isolated (-I). - name: synthesis watermark · wai-rs and synthesis_mark_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features synthesis_mark --lib -- synthesis::mark synthesis_mark::) (cd wai-rs && cargo test --release --no-default-features --features synthesis_mark --test synthesis_mark) python3 -I live-conformance/synthesis_mark_verify.py live-conformance/synthesis-mark # wai.media.upscale (extensions/exact-upscale.md): the integer super-resolution # derivations' unit tests (the wai-ops/1 graph against the arithmetic of §3.2 written out # loop by loop, on random priors and pictures; a prior with no detail is the pinned # upscale; sr4 is sr2 twice; a prior that breaks §3.1 refused in its order; a picture past # the caps refused), the module's unit tests (the pixel counts of §6.3, a residual within # half its step), and tests/exact_upscale.rs (the committed corpus regenerates byte for # byte from its fixed seeds and its two pinned trained priors, and no other file is there; # wai-rs gives every case its stated outcome and statements; §8 lists exactly the # reference's codes, each of which the corpus gives; sha256.json names every accepted # output); then the corpus's second implementation, upscale_verify.py, written from the # extension's text and sharing no code with wai-rs, which runs the derivations with # _int_sr.py, verifies the claims with synthesis_verify.py and the residuals with # staged_verify.py, and requires every mutated copy of the corpus to fail; standard # library only, run isolated (-I). - name: exact upscale · wai-rs and upscale_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features neural_int --lib int_sr::) (cd wai-rs && cargo test --no-default-features --features exact_upscale --lib exact_upscale::) (cd wai-rs && cargo test --no-default-features --features exact_upscale --test exact_upscale) python3 -I live-conformance/upscale_verify.py live-conformance/upscale # Robustness evidence for soft bindings (extensions/robustness-evidence.md): the # reference's unit tests (gamma is the rounded power, rates are exact and reduced, every # attack of synthesis §7.5.7's battery is a transform that gives its bytes, parameters # outside their ranges are refused), then tests/robustness.rs in release, since # regenerating the corpus runs the harness over the measurement sets of synthesis §7.5.8 # (every file of live-conformance/robustness/ regenerates byte for byte and no other file # is there; every case gets what it states; §12 lists exactly the reference's codes and # the corpus refuses a case for each; §4 registers exactly the reference's transforms; # the tent64 records' tables are the synthesis corpus's battery.json; the tent64 claim is # synthesis §7.5.8's list; jwp-receipts §3.1 lists the span reasons); then the second # implementation, robustness_verify.py with _wai_mark.py, written from the extension's # text and sharing no code with wai-rs, which reruns the conformance record's battery end # to end and requires the same table, checks the tent64 records against battery.json and # the claim against synthesis §7.5.8, mutates copies of the corpus and weakens its own # verifier in turn; standard library only, run isolated (-I). - name: robustness evidence · wai-rs and robustness_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features robustness --lib robustness::) (cd wai-rs && cargo test --release --no-default-features --features robustness --test robustness) python3 -I live-conformance/robustness_verify.py live-conformance/robustness # wai.ai.usage (extensions/ai-usage.md): the reference module's unit tests (RFC 9651's # Dictionary parser against the vocabulary's examples and the RFC's edges, statements # read and refused in their steps' order, the precedence rule, HTTP fields compared by # meaning), the consumption class's body and terms in claim_receipt, and # tests/ai_usage.rs (vectors.json regenerates byte for byte from its fixed seeds and no # other file is there, wai-rs gives every statement, object, room, response, catalog, # claim and gate its stated outcome, §9 lists exactly the reference's codes, each of which # the corpus gives, and jwp-receipts §3.1 lists the class rules); then the corpus's second # implementation, ai_usage_verify.py, written from the extension's text and sharing no # code with wai-rs, which parses Structured Fields, canonical forms, receipts and claims # itself, reads rooms with live_rooms_verify.py, checks signatures with WAI's strict # Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's reason table, # requires every mutated copy of the corpus to fail, and drops each of its own checks in # turn and requires the corpus to catch the weakened verifier; standard library only, run # isolated (-I). Last, claim-conformance's own verifier reads every consumption claim of # the corpus through jwp-receipts §3.1 steps 1 to 4 and requires the stated step and reason. - name: AI usage · wai-rs and ai_usage_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features ai_usage --lib ai_usage::) (cd wai-rs && cargo test --no-default-features --features ai_usage --lib claim_receipt::consumption::) (cd wai-rs && cargo test --no-default-features --features ai_usage --test ai_usage) python3 -I live-conformance/ai_usage_verify.py live-conformance/usage python3 -I claim-conformance/claim_verify.py consumption live-conformance/usage/vectors.json # wai.media.contribution (extensions/contribution.md): the reference module's unit tests # (every proof of the steps' tree walks to its root, the copying operations follow their # sample mappings, a map has one encoding) and tests/contribution.rs (the committed corpus # regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives # every case its stated outcome and statements, §11 lists exactly the reference's codes, # each of which the corpus gives, and the corpus generates with the model file of # wai.generate.spectral's conformance vector); then the corpus's second implementation, # contribution_verify.py, written from the extension's text and sharing no code with # wai-rs, which evaluates every pinned operation, runs the generator in its own arithmetic # after checking it against the generator's conformance vector, computes every map, share # and C2PA statement itself, reads origin claims with synthesis_verify.py and every record # with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires every mutated # copy of the corpus to fail, and drops each of its own checks in turn and requires the # corpus to catch the weakened verifier; standard library only, run isolated (-I). - name: contribution records · wai-rs and contribution_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features contribution --lib contribution::) (cd wai-rs && cargo test --no-default-features --features contribution --test contribution) python3 -I live-conformance/contribution_verify.py live-conformance/contribution # wai.delivery.settlement (extensions/settlement.md): the reference module's unit tests # (range proofs over every range around every chunk boundary of objects of many lengths # against BLAKE3's own root, tampered proofs refused, the group tree of jwp-receipts §2.2, # records and item lists read and refused, amounts rounded down per line) and # tests/settlement.rs (vectors.json regenerates byte for byte from its fixed seeds and no # other file is there, wai-rs gives every statement and range proof its stated outcome, §11 # lists exactly the reference's codes, each of which the corpus gives, beside every code it # reuses); then the corpus's second implementation, settlement_verify.py, written from the # extension's text and sharing no code with wai-rs, which verifies range proofs over # BLAKE3's chunk tree with claim-conformance's BLAKE3, reads rooms, grants and proofs with # live_rooms_verify.py and per-hop records with live_metering_verify.py, checks signatures # with WAI's strict Ed25519 rule, recomputes every figure of every statement, reads the # extension's reason table, requires every mutated copy of the corpus to fail, and drops # each of its own checks in turn and requires the corpus to catch the weakened verifier; # standard library only, run isolated (-I). - name: delivery settlement · wai-rs and settlement_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features settlement --lib settlement::) (cd wai-rs && cargo test --no-default-features --features settlement --test settlement) python3 -I live-conformance/settlement_verify.py live-conformance/settlement # The browser sink (extensions/browser-sink.md): the reference module's unit tests (the # registry gate's rows, registered tiers, integers as §5 reads them, a binding's # canonical form, an answer for an unregistered codec string never read, powerEfficient # never stated off the user agent's route, the side table's ambiguity) and # tests/browser_sink.rs (both files of the committed corpus regenerate byte for byte and # no other file is there, wai-rs gives every case its stated outcome, every reason of # §11 appears in the corpus and §11 lists exactly the reference's codes, and the chain # the generator signs by hand verifies under jwp_delivery); wai-live-web's browser # functions held to the same corpus natively, and its wasm-route decoder verifying, # decoding and binding every chain object to the published frame digests; then the # corpus's second implementation, browser_sink_verify.py, written from the extension's # text and sharing no code with wai-rs, which reads the registry export for each # capability's class, recomputes every route, evaluation, energy entry, binding, chain # signature, frame state and side table, changes the answers for unregistered codec # strings every way and requires the corpus still to pass, and requires every mutated # copy of the corpus to fail; standard library only, run isolated (-I). The browser's # own run of it is joule-moq-web.yml's scenario binding. - name: browser sink · wai-rs, wai-live-web and browser_sink_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features browser_sink --lib browser_sink::) (cd wai-rs && cargo test --no-default-features --features browser_sink,receipt_claims --test browser_sink) (cd wai-rs && cargo run -q --no-default-features --features browser_sink --bin wai_browser_sink_vectors -- verify ../live-conformance/browser) (cd wai-live-web && cargo test --locked --lib browser_tests) (cd wai-live-web && cargo test --locked --features int_video --lib browser_tests) python3 -I live-conformance/browser_sink_verify.py live-conformance/browser # wai.media.takedown (extensions/takedown.md): the reference module's unit tests (times, # clock identifiers, the published registry, the order of subjects, the lower median) and # tests/takedown.rs (the committed corpus regenerates byte for byte from its fixed seeds # and no other file is there, wai-rs gives every case its stated outcome and facts and # every counts entry its rows, §11 lists exactly the reference's codes, each of which the # corpus gives, and the registry the module carries is registry/takedown-clocks.json); # then the corpus's second implementation, takedown_verify.py, written from the # extension's text and sharing no code with wai-rs, which computes every closure, holder, # purge time, clock verdict and counts row itself, reads derivation records and delivery # receipts with edge_verify.py, origin claims with synthesis_verify.py, acknowledgements # with settlement_verify.py and every record with WAI's strict Ed25519 rule and BLAKE3 # from claim-conformance, requires every mutated copy of the corpus to fail, and drops # each of its own checks in turn and requires the corpus to catch the weakened verifier; # run isolated (-I). The reference relay's DVR store honours takedowns (§10.1), tested by # joule-moq-relay's tests/dvr.rs in joule-code-conformance.yml. - name: takedown · wai-rs and takedown_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features takedown --lib takedown::) (cd wai-rs && cargo test --no-default-features --features takedown --test takedown) python3 -I live-conformance/takedown_verify.py live-conformance/takedown # wai.media.influence (extensions/influence.md): the reference module's unit tests (the # blend keeps its base and its references by weight, the makers' split is whole, an # estimate mixed into a share is told from another difference) and tests/influence.rs (the # committed corpus regenerates byte for byte from its fixed seeds and no other file is # there, wai-rs gives every case, statement and report its stated outcome, every reason of # §9 and every code it reuses refuses a vector, and §9 lists exactly the reference's codes); # then the corpus's second implementation, influence_verify.py, written from the # extension's text and sharing no code with wai-rs, which verifies each session with # contribution_verify.py, regenerates every conditioned step with that implementation's # arithmetic of the generator, reads usage statements with ai_usage_verify.py and # statements with settlement_verify.py, computes every step map, share, attribution line # and report itself, requires every mutated copy of the corpus to fail, and drops each of # its own checks in turn and requires the corpus to catch the weakened verifier; standard # library only, run isolated (-I). - name: influence attribution · wai-rs and influence_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features influence --lib influence::) (cd wai-rs && cargo test --no-default-features --features influence --test influence) python3 -I live-conformance/influence_verify.py live-conformance/influence # wai.media.direction (extensions/direction.md): the reference module's unit tests (the # interpolations reach both keys and stay between them, the framing measure at its bounds, # a signed integer's one spelling, the timeline's starts and overlaps, a frame set's one # encoding) and tests/direction.rs (the committed corpus regenerates byte for byte from its # fixed seeds and no other file is there, wai-rs gives every case its stated outcome and # statements, §13 lists exactly the reference's codes, each of which the corpus gives, and # the corpus generates with the model file of wai.generate.spectral's conformance vector); # then the corpus's second implementation, direction_verify.py, written from the # extension's text and sharing no code with wai-rs, which runs the generator in its own # arithmetic after checking it against the generator's conformance vector, renders every # frame, interpolates every track, measures every box and writes every statement and C2PA # statement itself, reads records with synthesis_verify.py's strict JSON reader and every # signature with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires every # mutated copy of the corpus to fail, and drops each of its own checks in turn and requires # the corpus to catch the weakened verifier; standard library only, run isolated (-I). - name: direction records · wai-rs and direction_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features direction --lib direction::) (cd wai-rs && cargo test --no-default-features --features direction --test direction) python3 -I live-conformance/direction_verify.py live-conformance/direction # wai.live.coperformance (extensions/co-performance.md): the reference module's unit tests # (the policy and every statement round-trip and their rules refuse, the attributes' # decimal integers, a schedule's turns in bars and microseconds, the symbolic bodies read # whole) and tests/co_performance.rs (vectors.json regenerates byte for byte from its fixed # seeds and no other file is there, wai-rs gives every room its stated outcome, and §10 # lists exactly the reference's codes, each of which the corpus gives); then the corpus's # second implementation, co_performance_verify.py, written from the extension's text and # sharing no code with wai-rs, which verifies each room with live_rooms_verify.py and every # signature with WAI's strict Ed25519 rule from claim-conformance, recomputes every intent, # fidelity statement, turn, floor, commitment, selection and credit, reads the extension's # reason table, requires every mutated copy of the corpus to fail, and drops each of its # own checks in turn and requires the corpus to catch the weakened verifier; standard # library only, run isolated (-I). - name: co-performance · wai-rs and co_performance_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features co_performance --lib co_performance::) (cd wai-rs && cargo test --no-default-features --features co_performance --test co_performance) python3 -I live-conformance/co_performance_verify.py live-conformance/coperformance # wai.age.assurance (extensions/age-assurance.md): the reference module's unit tests (the # pinned AlgorithmIdentifier and RFC 9578's first vector through this module, the # TokenChallenge read exactly, the suppression floor, the grant attribute `age`, a span's # coverage) and tests/age_assurance.rs (vectors.json regenerates byte for byte from its # fixed seeds and no other file is there, wai-rs gives every case its stated outcome, and # §11 lists exactly the reference's codes, each of which the corpus gives); then the # corpus's second implementation, age_assurance_verify.py, written from the extension's # text and sharing no code with wai-rs, which reads every record, writes JCS and verifies # every token's RSASSA-PSS itself, reads rooms with live_rooms_verify.py, checks signatures # with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the extension's # reason table, requires every mutated copy of the corpus to fail, and drops each of its # own checks in turn and requires the corpus to catch the weakened verifier; standard # library only, run isolated (-I). - name: age assurance · wai-rs and age_assurance_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features age_assurance --lib age_assurance::) (cd wai-rs && cargo test --no-default-features --features age_assurance --test age_assurance) python3 -I live-conformance/age_assurance_verify.py live-conformance/age # wai.bearer.receipts (extensions/bearer-receipts.md): the reference module's unit tests # (the bound, the bitmap rules, the bearer classes, and the corpus reaching every stated # outcome and failing a changed one) and tests/bearer_receipts.rs (vectors.json # regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives # every case its stated outcome, the cases that carry one receipt on every bearer class # carry the same bytes with the same object verdicts, §10 lists exactly the reference's # codes, each of which the corpus gives, and jwp-receipts §3.1 lists the class codes at # their steps); then the corpus's second implementation, bearer_verify.py, written from # the extension's text and sharing no code with wai-rs, which verifies groups and objects # with jwp_verify.py, claims through jwp-receipts §3.1 steps 1-5 with claim_verify.py and # confirmations with signer_verify.py (each needs the `cryptography` package installed # above), writes the context checks, the verdict, the bound and offline confirmation # itself, reads the extension's reason table, requires every mutated copy of the corpus # to fail, and drops each of its own checks in turn and requires the corpus to catch the # weakened verifier; run isolated (-I). Last, claim-conformance's own verifier reads every # transmission and reconciliation claim of the corpus through jwp-receipts §3.1 steps 1 # to 4 and requires the stated step and reason. - name: bearer receipts · wai-rs and bearer_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features bearer_receipts --lib bearer) (cd wai-rs && cargo test --no-default-features --features bearer_receipts --test bearer_receipts) python3 -I live-conformance/bearer_verify.py live-conformance/bearers python3 -I claim-conformance/claim_verify.py bearer live-conformance/bearers/vectors.json # wai.media.exploration (extensions/exploration.md): the reference module's unit tests (the # descriptors of flat, single-row and checkerboard pictures, grid bins at both ends, the # sample distance's zero, the taste score, derived prompts, and a schedule that replays and # keeps the first comer without an objective) and tests/exploration.rs (vectors.json # regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives # every generation, descriptor vector and case its stated outcome, §13 lists exactly the # reference's codes, each of which the corpus gives, and §3.2 names the reference's # descriptors); then the corpus's second implementation, exploration_verify.py, written from # the extension's text and sharing no code with wai-rs, which makes every picture with the # generator as the extension's Appendix A restates it, computes the descriptors, replays # every archive's schedule, reads usage statements with ai_usage_verify.py, verifies every # record with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the # extension's reason table, requires every mutated copy of the corpus to fail, and drops each # of its own checks in turn and requires the corpus to catch the weakened verifier; standard # library only, run isolated (-I). - name: exploration · wai-rs and exploration_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features exploration --lib exploration::) (cd wai-rs && cargo test --no-default-features --features exploration --test exploration) python3 -I live-conformance/exploration_verify.py live-conformance/exploration # wai.live.cowatch (extensions/co-watch.md): the reference module's unit tests (the policy # and its rules, statements read back and refused, the controlled position in the order of # §5.4, each branch of the catch-up rule, percentiles by nearest rank, the control attribute) # and tests/co_watch.rs (vectors.json regenerates byte for byte from its fixed seeds and no # other file is there, wai-rs gives every room and catch-up case its stated outcome, and §12 # lists exactly the reference's codes, each of which the corpus gives); then the corpus's # second implementation, co_watch_verify.py, written from the extension's text and sharing # no code with wai-rs, which verifies each room with live_rooms_verify.py and every # signature with WAI's strict Ed25519 rule, recomputes the controlled position, every # sample, percentile and verdict, requires every mutated copy of the corpus to fail and # drops each of its own checks in turn and requires the corpus to catch the weakened # verifier; standard library only, run isolated (-I). Last, the browser client's co-watch # module (joule-moq-web/web/room/cowatch.js), which gives every catch-up case its # correction, recomputes each accepted room's controlled position, and writes the corpus's # controls and presentation statements byte for byte. - name: co-watch · wai-rs, co_watch_verify.py and the page's module working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features co_watch --lib co_watch::) (cd wai-rs && cargo test --no-default-features --features co_watch --test co_watch) python3 -I live-conformance/co_watch_verify.py live-conformance/cowatch node --test ../joule-code/joule-code-rs/crates/joule-moq-web/web/room/cowatch.test.mjs # wai.telemetry.aggregate (extensions/telemetry-aggregation.md): the reference module's unit # tests (the fields against a wide-arithmetic-free product, the generators' orders, # TurboSHAKE128 against RFC 9861, HPKE against RFC 9180 A.1.1, the FLP accepting a valid # measurement and refusing an invalid one, delivery-telemetry's key classes) and # tests/telemetry_aggregate.rs (vectors.json regenerates byte for byte from its fixed seeds and # no other file is there, vdaf-22/ is the draft's test vectors as published and wai-rs passes # every one, every receipt, cell and delivery-only report gets its stated outcome, every # reason of §11 and every reused code refuses a vector, §11 lists exactly the reference's # codes, delivery-telemetry §3.4 classes exactly the reference's keys); then the corpus's # second implementation, telemetry_aggregate_verify.py, written from the extension's text and # the drafts it cites and sharing no code with wai-rs, which evaluates Prio3 itself and passes # the draft's vectors, opens every report with its own X25519, HKDF, AES-128-GCM and HPKE, # re-runs every flow (both aggregators' verification, the aggregation job byte for byte, the # batch buckets, every refusal, the collection), verifies every receipt and cell with WAI's # strict Ed25519 rule from claim-conformance, reads the key classes and the reason table from # the texts, requires every mutated copy of the corpus to fail, and drops each of its own # checks in turn and requires the corpus to catch the weakened verifier; standard library # only, run isolated (-I). - name: QoE aggregation · wai-rs and telemetry_aggregate_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features telemetry_aggregate --lib -- telemetry_aggregate:: telemetry::) (cd wai-rs && cargo test --no-default-features --features telemetry_aggregate --test telemetry_aggregate) python3 -I live-conformance/telemetry_aggregate_verify.py live-conformance/aggregate # wai.media.tonemap, wai.meta.gainmap and wai.meta.st2094_50 (extensions/exact-tonemap.md): # the reference module's unit tests (the fixed-point log2 and exp2 at known points, the # table of K against its rule, the sRGB table, tan through its series, PCHIP slopes of a # line, rounding of halves for both signs) and the PNG reader's, then tests/exact_tonemap.rs # (the committed corpus regenerates byte for byte, no other file is there, every case and # envelope gets its stated outcome, §9 lists exactly the reference's codes, §6 states the # corpus's measurement against binary64, and frames.rgb8 is the int_video clip's decode # whose digests its sidecar publishes); then the corpus's second implementation, # tonemap_verify.py, written from the extension's text and sharing no code with wai-rs, # which computes both derivations in integer arithmetic of its own, reads PNG, envelopes # (with staged_verify.py) and both companions itself, recomputes §6's measurement, verifies # every record with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires # every mutated copy of the corpus to fail, and drops each of its own checks in turn and # requires the corpus to catch the weakened verifier; standard library only, run isolated # (-I). - name: exact tone mapping · wai-rs and tonemap_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features exact_tonemap --lib -- exact_tonemap:: png_still::) (cd wai-rs && cargo test --no-default-features --features exact_tonemap --test exact_tonemap) python3 -I live-conformance/tonemap_verify.py live-conformance/tonemap # wai.splat.exact (extensions/splat-exact.md): the reference module's unit tests # (exp_neg_q16 against the exponential, binary32 ranges rounded half up exactly, the # signed integers' grammar, the identity set carrying every byte, and tiles that leave a # frame unchanged) and tests/splat_exact.rs (live-conformance/splat/ regenerates byte for # byte and no other file is there, every case gets its stated outcome, §10 lists exactly the # reference's codes, the tiles leave every view of every scene unchanged, and the draft # schema names §3.2's members); then the corpus's second implementation, # splat_exact_verify.py, written from the extension's text and sharing no code with wai-rs: # it reads each glTF asset, decodes each payload with int_payload_verify.py's parser and # rANS decoder and tools/wai_ops_check.py's whm1/1 interpreter, renders every view with its # own integer renderer, verifies every record with WAI's strict Ed25519 rule and BLAKE3 # from claim-conformance, reads the extension's reason table, requires every mutated copy # of the corpus to fail, drops each of its own checks in turn and changes each rule of its # renderer in turn, and requires the corpus to catch every one; standard library only, run # isolated (-I). - name: exact splats · wai-rs and splat_exact_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features splat_exact --lib splat_exact::) (cd wai-rs && cargo test --no-default-features --features splat_exact --test splat_exact) python3 -I live-conformance/splat_exact_verify.py live-conformance/splat # wai.live.e2ee (extensions/confidentiality.md): the corpus's second implementation, # e2ee_verify.py, written from the extension's text and the documents it reads and # sharing no code with the reference (joule-moq's secure_objects and joule-moq-mls, # whose own checks run in joule-code-conformance.yml). Standard library only, run # isolated (-I): AES, AES-GCM and RFC 9605's counter mode written from their # specifications for test vectors only, HKDF and HMAC from the standard library, # BLAKE3 and strict Ed25519 from claim-conformance. It checks every vector RFC 9605 # and draft-ietf-moq-secure-objects-01 publish, every record, key schedule, sealed # object and room of vectors.json (taking each epoch's application secret as given, # §14), and requires every mutated copy of the corpus to fail. - name: end-to-end encrypted rooms · e2ee_verify.py working-directory: wai shell: bash run: python3 -I live-conformance/e2ee_verify.py live-conformance/e2ee # wai.live.watermark (extensions/forensic-watermark.md): the reference module's unit tests # (the CBOR reader's deterministic-encoding rules, tokens of both COSE structures and # every mode read and their rules refuse, a record's rules, big-endian bit addressing, # the exact match and the binding) and tests/live_watermark.rs (vectors.json regenerates # byte for byte from its fixed seeds and no other file is there, wai-rs gives every # token, session list, match and disclosure its stated outcome, and §11 lists exactly the # reference's codes, each of which the corpus gives); then the corpus's second # implementation, live_watermark_verify.py, written from the extension's text and sharing # no code with wai-rs, which reads rooms with live_rooms_verify.py and tokens with a CBOR # reader of its own, requires every mutated copy of the corpus to fail, and drops each of # its own checks in turn and requires the corpus to catch the weakened verifier; standard # library only, run isolated (-I). - name: forensic watermark sessions · wai-rs and live_watermark_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features live_watermark --lib live_watermark::) (cd wai-rs && cargo test --no-default-features --features live_watermark --test live_watermark) python3 -I live-conformance/live_watermark_verify.py live-conformance/watermark # wai.edge.derivation (extensions/deriving-edge.md): the reference module's unit tests # (the operations pixel by pixel, which operations the registry's composition rule makes # exact, the check each derivation takes, a record's reading rule by rule, its round trip # and signature, the pinned output manifest, provenance items and AI-origin labels, the # C2PA stores embedded in a still), the still writer and reader the module # shares with wai-pack (png_still), and tests/derive_edge.rs (vectors.json regenerates # byte for byte from its fixed seeds and no other file is there, wai-rs gives every vector # its stated outcome, §9 lists exactly the reference's codes and §4 its derivations, and # the reference edge wai_edge, run twice over a clip, makes a chain of two hops that # verifies and is refused once a byte changes); then the corpus's second implementation, # edge_verify.py, written from the extension's text and sharing no code with wai-rs, # which reads receipts and writes stills itself, re-executes every replicate hop, # requires every mutated copy of the corpus to fail, and drops each of its own checks in # turn and requires the corpus to catch the weakened verifier; standard library only, # run isolated (-I). - name: deriving edge · wai-rs and edge_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features derive_edge --lib derive_edge::) (cd wai-rs && cargo test --no-default-features --features derive_edge --lib png_still::) (cd wai-rs && cargo test --no-default-features --features derive_edge --test derive_edge) python3 -I edge-conformance/edge_verify.py edge-conformance # The quantum corpus's second implementation (quantum-sim extension), integers only: # it derives the circuit/1 phase table by its recurrence and the circuit2 table by an # interval-certified procedure, and requires both literal tables and their digests, # and the extension's Appendix B to state the same; # rebuilds every file of both vector trees byte for byte and recomputes every manifest # entry with its own reader, simulator, sampler and BLAKE3; refuses every reject file # with its listed class and by the rule its name states; and requires dyadic_ladder # to see every ±1 change of every P(k) under both tables. Standard library only, run # isolated (-I), so no module from the working directory, the environment or the # user's site-packages is imported. - name: quantum referee.py shell: bash run: python3 -I wai/quantum-conformance/tools/referee.py wai/quantum-conformance # chain_differential.py signs receipt chains around jwp-receipts §3 step 3 and §6.1 # (two keys, two tracks, both payloads, replays, forks, gaps, the guard and the # freshness bound), and chain_gap_differential.py genuine chains up to 90 groups # delivered shuffled, withheld and walked back with rewritten links and forks; both # require wai_jwp_vectors and jwp_verify.py to give every chain the same verdict. Two # fixed seeds each, so a run is reproducible. # Hybrid signatures (extensions/pq-signatures.md): the reference module's unit tests (its # ML-DSA-65 against FIPS 204's ACVP vectors — keyGen, deterministic sigGen and sigVer — # vendored in pq-conformance/acvp and pinned by SHA-256, and the composite against the # draft's own vector, before anything is built on them), the synthesis reader's hybrid # records, and tests/pq_signatures.rs (vectors.json regenerates byte for byte, every case # reaches its verdict, §8 lists exactly the reference's codes, each given); then the # corpus's second implementation, pq_verify.py, written from the extension's text and # sharing no code with wai-rs, which verifies ML-DSA-65 from FIPS 204's text in pure # Python (_mldsa.py), checks every ACVP verification vector and signature and the draft's # vector, every case, the sizes §9 states and §8's table, requires every mutated case to be # refused and the corpus to catch it with any one of its checks dropped; run isolated (-I). # Last, the two give every case the same verdict. - name: hybrid signatures · wai-rs and pq_verify.py working-directory: wai shell: bash run: | set -euo pipefail (cd wai-rs && cargo test --no-default-features --features pq_signatures --lib pq_sig::) (cd wai-rs && cargo test --no-default-features --features synthesis,pq_signatures --lib synthesis::pq_tests) (cd wai-rs && cargo test --no-default-features --features pq_signatures --test pq_signatures) python3 -I pq-conformance/pq_verify.py pq-conformance python3 -I pq-conformance/pq_verify.py verdicts pq-conformance/vectors.json > "$RUNNER_TEMP/pq-py.tsv" (cd wai-rs && cargo run -q --no-default-features --features pq_signatures --bin wai_pq_vectors -- verdicts ../pq-conformance/vectors.json) > "$RUNNER_TEMP/pq-rs.tsv" diff "$RUNNER_TEMP/pq-py.tsv" "$RUNNER_TEMP/pq-rs.tsv" - name: claim_verify.py, differential.py, jwp_verify.py, chain_differential.py, chain_gap_differential.py, signer_verify.py working-directory: wai shell: bash run: | set -euo pipefail python3 claim-conformance/claim_verify.py claim-conformance/vectors.json python3 claim-conformance/differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_claim_vectors" --random 2000 --seed 1 python3 jwp-conformance/jwp_verify.py jwp-conformance/vectors.json for seed in 1 2; do python3 jwp-conformance/chain_differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_jwp_vectors" --n 3000 --seed "$seed" python3 jwp-conformance/chain_gap_differential.py "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_jwp_vectors" --n 400 --seed "$seed" done python3 signer-conformance/signer_verify.py signer-conformance/vectors.json python3 signer-conformance/signer_verify.py verdicts signer-conformance/vectors.json > "$RUNNER_TEMP/signer-py.tsv" "$GITHUB_WORKSPACE/wai/wai-rs/target/debug/wai_signer_vectors" verdicts signer-conformance/vectors.json > "$RUNNER_TEMP/signer-rs.tsv" diff "$RUNNER_TEMP/signer-py.tsv" "$RUNNER_TEMP/signer-rs.tsv" # Delivery telemetry's second implementation is an independent open-source CMCD and CMSD # library at locked versions (telemetry-conformance/cml/package-lock.json). The # differential builds each observation's report from the extension's tables, encodes it # with the library, requires the bytes of expected/cmcd.json and expected/cmsd.json, reads # the expected strings back as dictionary, query and header shards, and validates every # report with no error. One platform: string encoding, not arithmetic. telemetry-differential: needs: relevant if: needs.relevant.outputs.run == 'true' name: delivery telemetry · CMCD and CMSD against an independent library runs-on: linux-arm64 steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: '22' - name: npm ci, then the differential working-directory: wai/telemetry-conformance/cml shell: bash run: | set -euo pipefail npm ci --no-audit --no-fund node differential.mjs .. byte-exact: needs: relevant if: needs.relevant.outputs.run == 'true' name: cross-arch byte-equality · ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: # Self-hosted fleet labels. Both architectures: x86_64 by linux, arm64 # by linux-arm64 + macos — what matters for the Fx integer floor is the # arch, not the OS. No Intel-Mac runner exists in the fleet, and it # would add no arch coverage anyway. # Windows x86_64 leg removed 2026-09-30: runner offline. Restore by # re-adding `windows` here once the runner is back online. os: [linux, linux-arm64, macos] steps: - uses: actions/checkout@v5 - name: Install Rust 1.98.0 (unix) if: matrix.os != 'windows' shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0 rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - name: Install Rust 1.98.0 (Windows) if: matrix.os == 'windows' shell: pwsh run: | rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 - name: Integer rANS + int_synth + JPEG-AI mANS goldens (one machine → every machine) working-directory: wai/byte-exact-conformance run: cargo test --release # The codec wrappers are behind `codecs`, which binds C and C++ libraries that no # container image of this fleet carries, so no other job compiles them. A feature no # workflow enables has no CI coverage at all: without this job the wrappers' tests, # and the limits on what a text payload may decode to (SPEC §2), pass by not running. # # One platform, the `macos` runner, whose host has the libraries. What the job proves # is how the wrappers treat hostile bytes and where their limits fall, which is the # same code on every host. A missing library fails the build step by name. codec-wrappers: needs: relevant if: needs.relevant.outputs.run == 'true' name: codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path runs-on: macos steps: - uses: actions/checkout@v5 - name: Install Rust 1.98.0 shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # Every one of these test files is `#![cfg(feature = "codecs")]`: built without # the feature each reports "0 passed" and exits 0. So the step names the feature, # and then requires that each of the five binaries ran at least one test. - name: Fuzz smoke, the text and media decode limits and the C entry points working-directory: wai/wai-rs shell: bash run: | set -o pipefail cargo test --locked --features codecs \ --test fuzz_smoke --test text_decode_bounds --test text_decode_memory \ --test media_decode_bounds --test ffi_robustness \ 2>&1 | tee "$RUNNER_TEMP/codec-wrappers.log" ran=$(grep -cE '^test result: ok\. [1-9][0-9]* passed' "$RUNNER_TEMP/codec-wrappers.log" || true) if [ "$ran" -ne 5 ]; then echo "::error::expected five test binaries that each ran tests; $ran did" exit 1 fi # wai_prov needs `codecs`, so no other job builds it. Its --carry path writes the # provenance asset and receipt that wai-web's reach vectors commit: carried onto # its own receipt, a run must write both again byte for byte. A receipt changed # by one byte must be refused, which shows the comparison is not vacuous. - name: wai_prov carries the committed provenance receipt, byte for byte working-directory: wai/wai-rs shell: bash run: | set -euo pipefail cargo build --locked --features provenance,codecs,receipt_claims --bin wai_prov bin="${CARGO_TARGET_DIR:-target}/debug/wai_prov" v=../wai-web/reach/test/vectors/provenance "$bin" "$RUNNER_TEMP/prov" --carry "$v/captured.receipt.json" cmp "$RUNNER_TEMP/prov/captured.jpeg.wai" "$v/captured.jpeg.wai" cmp "$RUNNER_TEMP/prov/captured.receipt.json" "$v/captured.receipt.json" sed 's/"encode.jpeg"/"encode.jpeh"/' "$v/captured.receipt.json" > "$RUNNER_TEMP/changed.receipt.json" if cmp -s "$RUNNER_TEMP/changed.receipt.json" "$v/captured.receipt.json"; then echo "::error::the changed receipt is not changed"; exit 1 fi if "$bin" "$RUNNER_TEMP/prov-changed" --carry "$RUNNER_TEMP/changed.receipt.json"; then echo "::error::a changed receipt was carried"; exit 1 fi # tests/semantic_path.rs needs `semantic`, which builds on `codecs` and binds the # ONNX runtime, so this is the one job that can run it. - name: The semantic path working-directory: wai/wai-rs shell: bash run: | set -o pipefail cargo test --locked --features codecs,semantic --test semantic_path 2>&1 | tee "$RUNNER_TEMP/semantic-path.log" ran=$(grep -cE '^test result: ok\. [1-9][0-9]* passed' "$RUNNER_TEMP/semantic-path.log" || true) if [ "$ran" -ne 1 ]; then echo "::error::the semantic path's test binary ran no test" exit 1 fi # The C2PA emitter is gated behind an off-by-default feature, so the four-platform # job above — which builds a fixed feature list — never compiles it. A feature no # workflow enables has no CI coverage at all: the suite passes, and the tests in it # simply do not run. # # One platform, deliberately. Everything the matrix above exists to prove is about # byte-identical reconstruction across architectures; a signed manifest makes no # such claim and would not become more true for being emitted on four machines. What # this job proves is that the manifest is still well-formed, still carries the three # assertions, and still validates — which is architecture-independent. c2pa-emitter: needs: relevant if: needs.relevant.outputs.run == 'true' name: C2PA manifest emission · signed, read back, validated runs-on: linux-arm64 steps: - uses: actions/checkout@v4 - name: Install Rust 1.98.0 shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0 rustup toolchain install 1.98.0 --profile minimal rustup default 1.98.0 echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # `rust_native_crypto` rather than the SDK's default openssl backend, so this # job needs no system libraries — the same property the matrix above depends on. # Asserted, not assumed: an openssl-linked build would still pass the tests here # while quietly making the crate undistributable to a bare runner. - name: The emitter pulls in no system crypto working-directory: wai/wai-rs shell: bash run: | for dep in openssl openssl-sys; do if cargo tree --no-default-features --features c2pa_emit -i "$dep" >/dev/null 2>&1; then echo "::error::$dep reached the c2pa_emit dependency graph" exit 1 fi done echo "no system crypto in the graph" - name: Emit, sign, read back, validate working-directory: wai/wai-rs run: cargo test --lib --no-default-features --features c2pa_emit c2pa_emit # A room-session receipt (extensions/live-metering.md §7) in a real signed manifest: # energy_kwh only where one class covers the session whole, the companion always. - name: Emit a room-session receipt, sign, read back, validate working-directory: wai/wai-rs run: cargo test --lib --no-default-features --features c2pa_emit,live_metering c2pa_emit::tests::a_session # The feature must stay optional. If `provenance` ever pulls c2pa in, every # consumer that wanted only the binding types inherits a large dependency tree # they did not ask for, and the "off by default" claim in the extension is false. - name: The feature stays optional working-directory: wai/wai-rs shell: bash run: | if cargo tree --no-default-features --features provenance -i c2pa >/dev/null 2>&1; then echo "::error::c2pa is reachable from the provenance feature; it must stay opt-in" exit 1 fi cargo build --no-default-features --features provenance echo "provenance builds without c2pa"