Generated on the final tree: the views page, rebuilt (802 495 bytes, under 1 MiB) from its sources; the notebooks' stored outputs; the agent docs. The pins that move: wai-web's course check names its engine now, so its digest moves (374b400e... to 969b2c1c..., and with every release from here), and the page's wasm32 count is 18 (native 26, as pinned). wai-quantum-qpu's library count is 34, as the cherry-picked pin says. What replaying each workflow's jobs found, each fixed here: - the views page's one line carried the estimate pane's English note, "no other beats on both", which the comparative-prose check reads across the line; the note says "none of the others beats on both"; - the docs runner's broken.qasm is broken on purpose, so the editors check requires it to fail to parse, as the intent set's broken programs; - the command line's parse test named the service's submit and task in a build without the service; those checks are a test of their own, built with it; - the set-only Merkle helpers warned in a build without receipts; - a one-element loop in the service's strict test; - the energy job looked for the live counter's line at the start of a line, where --nocapture puts it after the test's name; - the Python test comparing a run on the service with one here now leaves out the provenance the service adds, and checks it is there. The release heading's caller list is the final API check's: the frame text's new fields and variant, and the request's compile passes and mitigation. Co-Authored-By: Claude Opus 5.5 <[email protected]>
233 lines
12 KiB
YAML
233 lines
12 KiB
YAML
name: wai-quantum service
|
|
|
|
# The WAI quantum stack as a public job service (wai/wai-quantum-service): its
|
|
# tests, clippy with warnings as errors, and its smoke checks over HTTP against
|
|
# an instance started here, on Linux and on the macOS runner (the host the
|
|
# service is deployed to). Its tests also hold the command line's snapshot of
|
|
# its MCP tools (wai/wai-quantum-cli/docs/service-mcp.json) to the live list,
|
|
# and one (tests/restart.rs) kills the service mid-job and starts it again on
|
|
# its store. Each instance here keeps its job store in the runner's own
|
|
# scratch directory.
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-service/**'
|
|
# The command line's agent docs list this service's tools from a snapshot
|
|
# there, which this service's tests hold to its live list.
|
|
- 'wai/wai-quantum-cli/docs/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-service.yml'
|
|
pull_request:
|
|
paths:
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-service/**'
|
|
# The command line's agent docs list this service's tools from a snapshot
|
|
# there, which this service's tests hold to its live list.
|
|
- 'wai/wai-quantum-cli/docs/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-service.yml'
|
|
|
|
jobs:
|
|
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-quantum-service.yml \
|
|
"${{ github.event.pull_request.base.sha }}" \
|
|
"${{ github.event.pull_request.head.sha }}")
|
|
echo "this change touches wai-quantum-service: $r"
|
|
echo "run=$r" >> "$GITHUB_OUTPUT"
|
|
|
|
service-linux:
|
|
name: service · linux
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: linux
|
|
timeout-minutes: 60
|
|
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 --component clippy
|
|
rustup default 1.98.0
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- name: Tests and clippy
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-service
|
|
run: |
|
|
set -euo pipefail
|
|
cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/test.log"
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::no test ran"; exit 1; }
|
|
cargo clippy --locked --release --all-targets -- -D warnings
|
|
# The engine's parts of the service, each required by name: sets and
|
|
# sweeps and their Merkle paths, a result's provenance, the package
|
|
# counter's reader and probe (on fake trees; a container hides the real
|
|
# one), and a real-valued input bound by the reader.
|
|
- name: The engine's sets, provenance and package energy
|
|
shell: bash
|
|
working-directory: wai/wai-quantum
|
|
run: |
|
|
set -euo pipefail
|
|
cargo test --locked --release --features full --lib -- engine::sets:: engine::energy:: merkle:: engine::run::tests::a_result_s_provenance qasm::tests::a_bound_parameter 2>&1 | tee "$RUNNER_TEMP/engine.log"
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/engine.log" || { echo "::error::the engine's tests did not pass"; exit 1; }
|
|
for t in engine::sets::tests::one_receipt_binds_every_item_and_any_change_breaks_it \
|
|
engine::sets::tests::a_sweep_is_its_grid_each_point_the_program_written_out \
|
|
engine::sets::tests::a_failed_item_is_bound_by_its_error \
|
|
merkle::tests::every_leaf_s_path_leads_to_the_root_and_nothing_else_does \
|
|
engine::run::tests::a_result_s_provenance_names_the_passes_its_certificate_ran \
|
|
engine::energy::tests::the_probe_finds_a_live_counter_s_cadence_and_refuses_a_stalled_one \
|
|
engine::energy::tests::only_top_level_package_zones_are_read_and_a_frozen_one_is_not_live \
|
|
engine::energy::tests::a_package_figure_names_its_scope_and_declares_its_edges \
|
|
qasm::tests::a_bound_parameter_reads_as_the_program_written_with_its_value; do
|
|
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run"; exit 1; }
|
|
done
|
|
- name: The smoke checks over HTTP
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-service
|
|
run: |
|
|
set -euo pipefail
|
|
key="$RUNNER_TEMP/service.key"; rm -f "$key" "$RUNNER_TEMP/service.keys.json"
|
|
store="$RUNNER_TEMP/store"; rm -rf "$store"
|
|
cargo build --locked --release
|
|
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 \
|
|
./target/release/wai-quantum-service serve 2> "$RUNNER_TEMP/service.log" &
|
|
pid=$!
|
|
trap 'kill $pid 2>/dev/null || true; cat "$RUNNER_TEMP/service.log"' EXIT
|
|
for _ in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:18241/v1/health && break; sleep 0.2; done
|
|
bash smoke.sh http://127.0.0.1:18241
|
|
|
|
service-macos:
|
|
name: service · macos
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: macos
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
# launchd's PATH omits cargo on the macOS host runner.
|
|
- name: Put cargo on PATH
|
|
shell: bash
|
|
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- name: Tests
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-service
|
|
run: |
|
|
set -euo pipefail
|
|
nice -n 10 cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/test.log"
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::no test ran"; exit 1; }
|
|
# The single-precision state vector on this host's GPU, against the
|
|
# double-precision one; the GPU is declared, so its absence fails.
|
|
- name: The GPU state vector
|
|
shell: bash
|
|
working-directory: wai/wai-quantum
|
|
env:
|
|
WAI_QUANTUM_SV_METAL_EXPECT: "1"
|
|
run: |
|
|
set -euo pipefail
|
|
nice -n 10 cargo test --locked --release --features quantum_sv_metal --lib quantum_sv_metal 2>&1 | tee "$RUNNER_TEMP/gpu.log"
|
|
grep -qE '^test result: ok\. 4 passed; 0 failed' "$RUNNER_TEMP/gpu.log" || { echo "::error::not every GPU test ran and passed"; exit 1; }
|
|
# The cut-rank table on this host's GPU, against the double-precision
|
|
# walk; the GPU is declared, so its absence fails, and each GPU test is
|
|
# checked by name.
|
|
- name: The GPU cut-rank table
|
|
shell: bash
|
|
working-directory: wai/wai-quantum
|
|
env:
|
|
WAI_QUANTUM_CUTRANK_METAL_EXPECT: "1"
|
|
run: |
|
|
set -euo pipefail
|
|
nice -n 10 cargo test --locked --release --features quantum_cutrank_metal --lib quantum_cutrank 2>&1 | tee "$RUNNER_TEMP/cutrank-gpu.log"
|
|
for t in the_gpu_table_agrees gpu_samples_follow_the_probabilities; do
|
|
grep -q "^test quantum_cutrank::tests::$t ... ok$" "$RUNNER_TEMP/cutrank-gpu.log" \
|
|
|| { echo "::error::quantum_cutrank::tests::$t did not run and pass"; exit 1; }
|
|
done
|
|
- name: The smoke checks over HTTP
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-service
|
|
run: |
|
|
set -euo pipefail
|
|
key="$RUNNER_TEMP/service.key"; rm -f "$key" "$RUNNER_TEMP/service.keys.json"
|
|
store="$RUNNER_TEMP/store"; rm -rf "$store"
|
|
cargo build --locked --release
|
|
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 \
|
|
./target/release/wai-quantum-service serve 2> "$RUNNER_TEMP/service.log" &
|
|
pid=$!
|
|
trap 'kill $pid 2>/dev/null || true; cat "$RUNNER_TEMP/service.log"' EXIT
|
|
for _ in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:18241/v1/health && break; sleep 0.2; done
|
|
bash smoke.sh http://127.0.0.1:18241
|
|
|
|
# The processor packages' counters on a Linux host that has them readable
|
|
# (the hardware runner, outside any container): the engine's live test
|
|
# required to take its live branch, and the service's smoke checks with a
|
|
# metered figure required on every job.
|
|
energy-linux:
|
|
name: service energy · linux packages
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: linux-hw
|
|
timeout-minutes: 90
|
|
env:
|
|
CARGO_PROFILE_RELEASE_DEBUG: '0'
|
|
CARGO_BUILD_JOBS: '8'
|
|
steps:
|
|
- name: Fetch the source
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
ref="${{ github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number) || github.ref }}"
|
|
want="${{ github.event.pull_request.head.sha || github.sha }}"
|
|
rm -rf src && mkdir src && cd src
|
|
git init -q
|
|
git fetch -q --depth 1 http://100.64.224.0:3400/Transaction-Science/open-standards.git "$ref"
|
|
git checkout -q FETCH_HEAD
|
|
got="$(git rev-parse HEAD)"
|
|
echo "fetched $ref at $got"
|
|
if [ "$got" != "$want" ]; then
|
|
echo "::error::$ref is at $got, not $want: it moved after this run started, and a newer run tests it"
|
|
exit 1
|
|
fi
|
|
- name: The package counter, live
|
|
shell: bash
|
|
working-directory: src/wai/wai-quantum
|
|
env:
|
|
WAI_QUANTUM_PACKAGE_ENERGY_EXPECT: "1"
|
|
run: |
|
|
set -euo pipefail
|
|
log=$(mktemp)
|
|
CARGO_TARGET_DIR="$HOME/hw-target/wai-quantum" nice -n 10 cargo test --locked --release --features quantum_engine,quantum_receipt --lib engine::energy:: -- --nocapture --test-threads=1 2>&1 | tee "$log"
|
|
# With --nocapture the test's line follows its name on the same line.
|
|
grep -q 'package counter: {"joules_micro":' "$log" || { echo "::error::the package counter's live path never ran"; exit 1; }
|
|
- name: The service's smoke checks, every job metered
|
|
shell: bash
|
|
working-directory: src/wai/wai-quantum-service
|
|
run: |
|
|
set -euo pipefail
|
|
export CARGO_TARGET_DIR="$HOME/hw-target/wai-quantum-service"
|
|
nice -n 10 cargo build --locked --release
|
|
t=$(mktemp -d)
|
|
WAI_QSVC_KEY="$t/service.key" WAI_QSVC_STORE="$t/store" WAI_QSVC_ADDR=127.0.0.1:18244 WAI_QSVC_BUDGET_GB=4 WAI_QSVC_JOB_GB=2 WAI_QSVC_WORKERS=1 \
|
|
"$CARGO_TARGET_DIR/release/wai-quantum-service" serve 2> "$t/service.log" &
|
|
pid=$!
|
|
trap 'kill $pid 2>/dev/null || true; cat "$t/service.log"; rm -rf "$t"' EXIT
|
|
for _ in $(seq 1 100); do curl -s -o /dev/null http://127.0.0.1:18244/v1/health && break; sleep 0.2; done
|
|
curl -sS http://127.0.0.1:18244/v1 | python3 -I -c 'import json,sys; e=json.load(sys.stdin)["energy"]; assert e["meter"]=="packages", e; print("meter:", e)'
|
|
SMOKE_EXPECT_ENERGY=1 bash smoke.sh http://127.0.0.1:18244
|