name: wai-web wasm32 # The browser sink (wai/wai-web) is the same Rust as the native reference, # compiled to wasm32-unknown-unknown. This job builds it and runs, under node: # # - demo/verify_int_synth_wasm.mjs against the committed conformance corpus # wai/neural-conformance/ (not the demo's staged copies): the wasm32 # int_synth decode must hash to the corpus's frozen native hashes; # - demo/verify_menu.mjs: every capability the browser sink advertises is # registered in wai/registry/capabilities.json as a payload or companion # capability, none is a candidate (SPEC §5), and the wasm build's own # registry agrees with the export on every candidate; # - demo/verify_pack.mjs: the browser writers `pack` and `packMulti` refuse # every candidate the export lists, in every place an envelope can name one, # and a manifest that names a member twice in one object; # - a byte comparison of the demo's staged int_synth copies with the corpus; # - the crate's wasm_tests under wasm-bindgen-test-runner, and its native unit # tests on the host. # # The full-scale int_hyper wasm decode needs vectors regenerated from a # pretrained model; wai-sota-vectors.yml runs it after regenerating them. # 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: push: branches: [main] paths: - 'wai/wai-web/**' - 'wai/wai-rs/**' - 'wai/wai-quantum/**' - 'wai/neural-conformance/**' - 'wai/registry/**' - '.github/workflows/wai-web-wasm.yml' pull_request: paths: - 'wai/wai-web/**' - 'wai/wai-rs/**' - 'wai/wai-quantum/**' - 'wai/neural-conformance/**' - 'wai/registry/**' - '.github/workflows/wai-web-wasm.yml' jobs: wasm32: name: wai-web wasm32 build · corpus, menu and writers runs-on: linux timeout-minutes: 45 steps: - uses: actions/checkout@v5 # The docker runner image ships no Rust. - name: Install Rust 1.98.0 with the wasm32 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 wasm32-unknown-unknown echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # Pinned to the wasm-bindgen version in wai-web/Cargo.lock: the CLI and the # crate must match exactly. - name: wasm-bindgen CLI 0.2.127 shell: bash run: cargo install --locked wasm-bindgen-cli --version 0.2.127 - uses: actions/setup-node@v4 with: node-version: '22' - name: Build wai-web for wasm32 (node bindings) shell: bash working-directory: wai/wai-web run: | set -euo pipefail cargo build --locked --release --target wasm32-unknown-unknown wasm-bindgen --target nodejs --out-dir demo/pkg-node --out-name wai_web \ target/wasm32-unknown-unknown/release/wai_web.wasm # The JS surface itself (pick, companionsOf, verifyPin, rendition() and # companion() refusing what is never presented or does not match its digest, # the held-sets conversion, and the WAI2 parse at 32-bit usize) runs only on # wasm32 (`mod wasm_tests`). wasm-bindgen-test-runner, installed above at the # version Cargo.lock pins, runs it under Node. The count check turns a test # that stopped being compiled into a failure instead of a silent "0 passed". - name: wai-web JS surface (wasm32 tests under Node) shell: bash working-directory: wai/wai-web run: | set -euo pipefail CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner \ cargo test --locked --target wasm32-unknown-unknown 2>&1 | tee "$RUNNER_TEMP/wai-web-wasm.log" grep -q "test result: ok. 4 passed; 0 failed" "$RUNNER_TEMP/wai-web-wasm.log" # The crate's native unit tests, run on the host: the pure-Rust halves of the # bindings, which wasm_tests does not run. They decode the committed integer # payloads to their sidecars' SHA-256 (int_payload::tests) and check that the # writers `pack` and `packMulti` refuse a payload that is not the format SPEC §5 # pins its integer capability to, and a manifest that names a member twice (tests). The count check turns a test that # stopped being compiled into a failure instead of a silent "0 passed". - name: wai-web native unit tests shell: bash working-directory: wai/wai-web run: | set -euo pipefail cargo test --locked --lib 2>&1 | tee "$RUNNER_TEMP/wai-web-native.log" grep -q "test result: ok. 9 passed; 0 failed" "$RUNNER_TEMP/wai-web-native.log" - name: wasm32 int_synth decode equals the frozen native corpus shell: bash working-directory: wai/wai-web run: node demo/verify_int_synth_wasm.mjs ./pkg-node/wai_web.js ../neural-conformance # decodeWiv1, decodeWih1, decodeWia1 and decodeWis1 on the committed integer # payloads give the SHA-256 their sidecars state, and a JSON form is refused. - name: wasm32 integer payload decode equals the native sidecars shell: bash working-directory: wai/wai-web run: node demo/verify_int_payload_wasm.mjs ./pkg-node/wai_web.js ../wai-rs/tests/vectors - name: The browser menu is registered and names no candidate shell: bash working-directory: wai/wai-web run: node demo/verify_menu.mjs ./pkg-node/wai_web.js ../registry/capabilities.json - name: The browser writers refuse every candidate shell: bash working-directory: wai/wai-web run: node demo/verify_pack.mjs ./pkg-node/wai_web.js ../registry/capabilities.json - name: The demo's staged int_synth vectors are byte copies of the corpus shell: bash working-directory: wai run: | set -euo pipefail cmp wai-web/demo/int_synth/expected_hashes.json neural-conformance/expected_hashes.json for n in gradient bloom facade photo; do for f in latent.bin int_synth.json; do cmp "wai-web/demo/int_synth/$n/$f" "neural-conformance/vectors/$n/$f" done done