name: wai-det-jpegai WAISM float-level module of record # The JPEG AI exact decoder module (wai/wai-det-jpegai), the module of record of WAISM's float # level (wai/extensions/waism.md, waism/1-det): one WebAssembly module with the ABI of waism §5 # that decodes wai.image.jpegai through wai-rs's exact decoder, the integer weight bundle # arriving as the capability's set. Held on every engine below, on Linux x86_64 and Linux arm64: # # - the crate built for wasm32-unknown-unknown, held at the float level and refused R3 at the # integer level by both of the profile's checkers (build.sh), and its planted fault built # beside it; # - F1: the probe of waism §9.3 (wai/wai-module-check/planted/probe.wasm) gives its bytes on # wasmtime 50.0.1 with Cranelift, Winch and Pulley with the NaN rule set and on Wasmi 2.0.0 # built with it, and other bytes on the three wasmtime engines with it unset; the probe # with a NaN-dependent branch planted fails F1; # - F2: the jpegai/v1 bundle, fetched from WAI's models root and checked against # wai/tools/jpegai-e2e-v1.sha256, and every case of the module corpus (corpus.json) through # the module of record (record/) and this build, on the four engines the probe holds (the # configuration vectors on the two compiling ones): the native exact decoder's pinned RGB8, # each refusal fixture's code and each configuration's outcome, one run digest per set of cases; # - the planted decoder: the pinned RGB8 on an engine the probe holds; another output on the # engine with the NaN rule unset, run past the probe; and refused there by the probe # (module_probe_mismatch) when the probe runs first. # # A module of record is pinned: record/manifest.json names its build. A later change to the # decoder it was built from changes what build.sh builds, not record/, and both are held here # to the same corpus. # # One run per branch at a time. A push supersedes the run before it. concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }} cancel-in-progress: true on: pull_request: paths: - 'wai/wai-det-jpegai/**' - 'wai/wai-rs/tests/vectors/jpegai/**' - 'wai/wai-module-check/planted/probe*' - 'wai/extensions/waism.md' - 'wai/tools/jpegai-e2e-v1.sha256' - '.github/workflows/wai-det-jpegai.yml' push: branches: - main paths: - 'wai/wai-det-jpegai/**' - 'wai/wai-rs/tests/vectors/jpegai/**' - 'wai/wai-module-check/planted/probe*' - 'wai/extensions/waism.md' - 'wai/tools/jpegai-e2e-v1.sha256' - '.github/workflows/wai-det-jpegai.yml' # The decoder the module is built from (wai-rs, wai-ops) changes often; the weekly run holds # the module and a fresh build of it to the corpus. schedule: - cron: '50 4 * * 0' jobs: # Does this pull request's own diff touch the paths above? 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: gate 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-det-jpegai.yml \ "${{ github.event.pull_request.base.sha }}" \ "${{ github.event.pull_request.head.sha }}") echo "this change touches wai-det-jpegai: $r" echo "run=$r" >> "$GITHUB_OUTPUT" engines: needs: relevant if: needs.relevant.outputs.run == 'true' name: ${{ matrix.os }} · both checkers, F1, F2 on wasmtime (Cranelift, Winch, Pulley) and Wasmi, the planted faults runs-on: ${{ matrix.os }} timeout-minutes: 90 strategy: fail-fast: false matrix: os: [linux, linux-arm64] steps: - uses: actions/checkout@v5 - name: Install Rust 1.99.1 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.99.1 rustup toolchain install 1.99.1 --profile minimal rustup default 1.99.1 rustup target add wasm32-unknown-unknown echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - uses: actions/setup-node@v4 with: node-version: '22' - name: The module and its planted fault, held by both checkers shell: bash run: bash wai/wai-det-jpegai/build.sh --out "$RUNNER_TEMP/module" --planted - name: The jpegai/v1 bundle, fetched and checked against its manifest shell: bash timeout-minutes: 10 run: bash wai/tools/wai_jpegai_fetch_e2e_inputs.sh "$RUNNER_TEMP/jpegai" - name: The engines' runner shell: bash working-directory: wai/wai-det-jpegai/host run: cargo build --locked --release - name: F1, the probe on each engine with the NaN rule set and unset, and the planted probe failing it shell: bash working-directory: wai/wai-det-jpegai run: | set -euo pipefail H=host/target/release/wai-det-jpegai-host "$H" --f1 if "$H" --f1 --probe ../wai-module-check/planted/probe-nan-branch.wasm > "$RUNNER_TEMP/f1-planted.log"; then cat "$RUNNER_TEMP/f1-planted.log"; echo "::error::the probe with a NaN-dependent branch passed F1"; exit 1 fi cat "$RUNNER_TEMP/f1-planted.log" grep -q "the probe accepted an engine whose NaN rule is not set" "$RUNNER_TEMP/f1-planted.log" || { echo "::error::the planted probe failed F1 for another reason"; exit 1; } # The two compiling engines run every case; the two interpreters run the jpegai/v1 cases, # because a configuration vector's decode takes them minutes (README, F2), and the 29 of # them would not fit this job. The README records a run of every case on all four. - name: F2, every case on the four engines the probe holds, the module of record and this build shell: bash working-directory: wai/wai-det-jpegai run: | set -euo pipefail host/target/release/wai-det-jpegai-host --engines cranelift,winch --external "$RUNNER_TEMP/jpegai" corpus.json \ record/wai_det_jpegai.wasm "$RUNNER_TEMP/module/wai_det_jpegai.wasm" host/target/release/wai-det-jpegai-host --engines pulley,wasmi --only jpegai/v1/ --external "$RUNNER_TEMP/jpegai" corpus.json \ record/wai_det_jpegai.wasm "$RUNNER_TEMP/module/wai_det_jpegai.wasm" - name: The planted decoder, pinned where the probe holds, another output past it, refused by it shell: bash working-directory: wai/wai-det-jpegai run: | set -euo pipefail H=host/target/release/wai-det-jpegai-host P="$RUNNER_TEMP/module/wai_det_jpegai.planted.wasm" J="$RUNNER_TEMP/jpegai" "$H" --engines cranelift --only jpegai/v1/test256 --external "$J" corpus.json "$P" if "$H" --engines cranelift-nan-off --no-probe --only jpegai/v1/test256 --external "$J" corpus.json "$P" > "$RUNNER_TEMP/planted-off.log"; then cat "$RUNNER_TEMP/planted-off.log"; echo "::error::the planted decoder gave the pinned output on an engine with the NaN rule unset"; exit 1 fi cat "$RUNNER_TEMP/planted-off.log" grep -q "jpegai/v1/test256: sha256:" "$RUNNER_TEMP/planted-off.log" || { echo "::error::the planted decoder failed for another reason"; exit 1; } if "$H" --engines cranelift-nan-off --only jpegai/v1/test256 --external "$J" corpus.json "$P" > "$RUNNER_TEMP/planted-probe.log"; then cat "$RUNNER_TEMP/planted-probe.log"; echo "::error::the probe held an engine with the NaN rule unset"; exit 1 fi cat "$RUNNER_TEMP/planted-probe.log" grep -q "module_probe_mismatch" "$RUNNER_TEMP/planted-probe.log" || { echo "::error::the run failed for another reason than the probe"; exit 1; }