open-standards/wai/wai-quantum-service/smoke.sh
Transaction Science 7cef125325
All checks were successful
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m23s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 5s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 1m47s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 2m49s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 7s
WAI energy receipts / does this change touch it (pull_request) Successful in 10s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 7s
WAI neural sink gates / does this change touch it (pull_request) Successful in 11s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m12s
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Successful in 10s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 8s
wai-quantum command line / does this change touch it (pull_request) Successful in 8s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / does this change touch it (pull_request) Successful in 7s
wai-quantum signal processor / does this change touch it (pull_request) Successful in 5s
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / does this change touch it (pull_request) Successful in 6s
wai-quantum Metal member / does this change touch it (pull_request) Successful in 5s
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 6s
wai-quantum npu-cores member / does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 3m38s
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Successful in 27s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Successful in 20s
wai-quantum service / does this change touch it (pull_request) Successful in 6s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 7s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 6s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 7s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 5s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 6s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Successful in 24s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 5s
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 5s
wai-web wasm32 / does this change touch it (pull_request) Successful in 5s
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Successful in 15s
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Successful in 1m13s
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Successful in 13s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Successful in 10s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Successful in 8s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m3s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 5m25s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 6m1s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 4m2s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 7m37s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 4m8s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 6m16s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 4m10s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 20m25s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m2s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 27s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m17s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m12s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m24s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 1m45s
wai-pack / wai-pack · linux (pull_request) Successful in 1m20s
wai-quantum command line / command line · linux (pull_request) Successful in 1m7s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 6m57s
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Successful in 24s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 3m25s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 4m35s
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Successful in 21s
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Successful in 26s
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Successful in 26s
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Successful in 21s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Successful in 20s
wai-quantum service / service · linux (pull_request) Successful in 39s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Successful in 19s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 3m23s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 14m8s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 19s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 28s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Successful in 14s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 10s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 8m5s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 15s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 12s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 29s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 3m12s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m9s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m13s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m18s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m22s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 15s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m23s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 15m0s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 12s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 26s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m36s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m35s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 6m54s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m14s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 24s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m18s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 25s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 6m16s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 23s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 19s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m8s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 35m22s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m33s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 14m16s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 23s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 54s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m14s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 3m12s
wai-pack / wai-pack · macos (pull_request) Successful in 1m3s
wai-quantum command line / command line · macos (pull_request) Successful in 28s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 14s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Successful in 1m13s
wai-quantum Metal member / member · Metal (macos) (pull_request) Successful in 29s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Successful in 5m49s
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Successful in 29s
wai-quantum service / service · macos (pull_request) Successful in 44s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 9s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m12s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 13s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 15s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 4m26s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m43s
wai-quantum 0.6.14: design critique, equivalence, alternatives and classical shortcuts across every surface; contraction trees that sweep along the line
This carries 0.6.13, which was not published on its own, and 0.6.14.

## 0.6.13

The engine is the microscope and the judge, a local model is a muse that waits to be
asked, and the reader is the author. Every figure is the engine's. Nothing changes the
reader's program until they apply a change.

engine::critique gives a program's measures before it runs:
- gates by kind; one-, two- and three-qubit gates; T gates; gates off the Clifford
  angles;
- depth and two-qubit depth, and whether it is a Clifford circuit;
- a fidelity at reference error rates, named as a model.
It also gives the program's smells, each with its lines and operations: gates that
cancel, rotations that merge or do nothing, idle qubits, and qubits never measured.
critique::variants rewrites the program's own text with the smells fixed, all of them
to a fixed point and each one alone. Each candidate carries its measures and the
equivalence verdict; one the check finds different is never offered.

engine::equiv compares two programs up to a global phase:
- by tableau for Clifford circuits, at any size;
- otherwise on every basis state, to 8 qubits;
- otherwise on random product states, to 22 qubits, which is evidence, not proof;
- otherwise unchecked, with the reason.
qasm::parse_lines gives each operation's line, and draw::layout each gate's operation
index.

engine::shortcuts lists every exact classical route the engine knows, priced on the
program, and names the cheapest for each question:
- the stabilizer tableau;
- the cut-rank sum;
- an exact matrix product state, at a bond bounded by the operator Schmidt ranks of
  the gates crossing each cut. The bound is held by a test against the true Schmidt
  ranks of random circuits;
- the light cone;
- a tensor-network contraction, when asked to be thorough;
- the state vector.
A cheap route proves a design classically easy; none being cheap proves nothing. On
the 70-qubit random graph-state circuit the quick check finds the cut-rank sum (widest
cut 30) in under 2 s. The thorough one finds widest cut 29 in about 4 minutes.

Quantum Studio gains:
- the critique, always on under the diagram, with the smells flagged on it, Show and
  Fix;
- the classical cost, on request;
- Alternatives: Improve (the engine's rewrites and the model's, each checked) and
  Explore (the model's different circuits, each measured and compared), with an atlas
  and Apply;
- Predict first, which sets the reader's expected outcome against the run;
- an assistant that asks questions first and speaks only when asked, offering (never
  sending) a hint when allowed. Its new tools are critique_qasm, check_equivalent and
  classical_shortcuts.
wai-web exports the four engine calls. The desktop app answers them natively.
wai-quantum-cli 0.1.1 adds critique, equivalent (exit 0/1/2), improve and shortcuts,
with four MCP tools.

examples/cutrank_qasm gains probs: the exact 2^n·p of given bit strings, with their
linear cross-entropy.

## 0.6.14

A deep circuit on a line, contracted qubit by qubit along time, keeps a boundary of
only the bonds between two neighbouring qubits: about half the depth for a
controlled-Z brickwork. The contraction search rarely found that tree on its own.

- Network::amplitude_split_placed builds the same network as amplitude_split, index
  for index, with each index's place in the circuit: a qubit and a time.
- tensor_places, sweep_orders and sweep_path turn the places into the trees that sweep
  qubit by qubit, or time by time.
- find_path_seeded and find_path_restarts_seeded score such trees beside the trials and
  polish the best of them all alike. A seed that is not a tree of the network is
  ignored.
- The engine's tensor_network method and the thorough shortcut lens take both sweeps as
  seeds.

On the 70-qubit random graph-state circuit, one amplitude's largest intermediate falls
from 2^48 to 2^36, and its multiply-adds from 2^56.1 to 2^48.7, in the thorough lens.
With 16 trials and no seeds the search finds 2^59. The pinned plans in
tests/bit_identity.rs call find_path itself and are unchanged.

The job service answers four design checks: POST /v1/critique, /v1/equivalent,
/v1/improve and /v1/shortcuts, with the matching MCP tools. They run in its own process
within bounds:
- each counts against the client's submissions;
- at most two run at once, and one that waits ten seconds is refused with a 503;
- equivalence work past 4e9 gate amplitudes, and a thorough search, are refused with a
  422 naming the local command.
The smoke script checks each one. It now follows a job that outlasts /v1/run's wait,
as a client does, instead of failing on a loaded host.

wai-quantum-cli 0.1.2 carries the faster contraction.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-22 02:40:04 -04:00

290 lines
19 KiB
Shell

#!/usr/bin/env bash
# smoke.sh BASE_URL: the service's promises, checked over HTTP against a running
# instance (CI starts one locally; after a deploy, run it against production).
#
# bash smoke.sh http://127.0.0.1:8241
# bash smoke.sh https://<public base>
#
# Each check prints one line and the script fails on the first that does not
# hold. Needs curl and python3.
set -euo pipefail
U=${1:?usage: smoke.sh BASE_URL}
U=${U%/}
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
post() { curl -sS --max-time 120 -X POST "$U$1" -H 'content-type: application/json' --data-binary "@$2"; }
py() { python3 -I -c "$@"; }
# POST /v1/run, then follow a job still queued or running past the service's
# wait through GET /v1/jobs/{id}, as a client would: on a loaded host a job
# can outlast the wait without anything being wrong. At most ten minutes.
run() {
post /v1/run "$1" > "$2"
for _ in $(seq 1 120); do
case "$(py 'import json,sys; print(json.load(open(sys.argv[1])).get("status", ""))' "$2")" in
queued|running) sleep 5; curl -sS --max-time 30 "$U/v1/jobs/$(py 'import json,sys; print(json.load(open(sys.argv[1]))["id"])' "$2")" > "$2.next" && mv "$2.next" "$2" ;;
*) return 0 ;;
esac
done
}
# The service describes itself, with its methods and its receipt key.
curl -sS --max-time 30 "$U/v1" > "$tmp/describe.json"
py 'import json,sys
d=json.load(open(sys.argv[1]))
assert d["service"]=="wai-quantum-service", d
ms={m["method"] for m in d["methods"]}
assert {"exact","statevector","stabilizer","pauli","tensor_network","cutrank","density_matrix","trajectories"} <= ms, ms
assert len(d["receipt_key"])==64
print("describe: ok,", len(ms), "methods, receipt key", d["receipt_key"][:16]+"…")' "$tmp/describe.json"
# A 40-qubit GHZ state: Clifford, so the stabilizer method, and only the two
# all-equal outcomes.
py 'import json
n=40
q="OPENQASM 3.0;\nqubit[%d] q;\nh q[0];\n" % n + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
print(json.dumps({"qasm": q, "shots": 1000, "seed": 7}))' > "$tmp/ghz.json"
run "$tmp/ghz.json" "$tmp/ghz.out"
py 'import json,sys
d=json.load(open(sys.argv[1])); r=d["result"]
assert d["status"]=="done" and r["method"]=="stabilizer", d
c=r["counts"]; assert set(c) <= {"0"*40, "1"*40} and sum(c.values())==1000, c
assert "receipt" in r
print("ghz-40: ok,", r["method"], c)' "$tmp/ghz.out"
# Its receipt verifies, and a changed result does not.
py 'import json,sys
req=json.load(open(sys.argv[1])); res=json.load(open(sys.argv[2]))["result"]
json.dump({"request": req, "result": res}, open(sys.argv[3],"w"))
res["counts"]["0"*40] = res["counts"].get("0"*40, 0) + 1
json.dump({"request": req, "result": res}, open(sys.argv[4],"w"))' "$tmp/ghz.json" "$tmp/ghz.out" "$tmp/v.json" "$tmp/t.json"
post /v1/verify "$tmp/v.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies")'
post /v1/verify "$tmp/t.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is False, d; print("receipt: a changed result does not verify")'
# The job carries its request as submitted, so whoever holds only the id can
# check the receipt: verify from the service's answer alone.
py 'import json,sys
req=json.load(open(sys.argv[1])); job=json.load(open(sys.argv[2]))
assert job["request"]==req, job.get("request")
json.dump({"request": job["request"], "result": job["result"]}, open(sys.argv[3],"w"))' "$tmp/ghz.json" "$tmp/ghz.out" "$tmp/vj.json"
post /v1/verify "$tmp/vj.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies from the job alone")'
# The job's energy: a counter figure with its class and declared uncertainty,
# or why it is unmetered, never zero. SMOKE_EXPECT_ENERGY=1 (a macOS host)
# requires the figure. A changed figure breaks the receipt: it is sealed.
export SMOKE_EXPECT_ENERGY="${SMOKE_EXPECT_ENERGY:-0}"
py 'import json,os,sys
e=json.load(open(sys.argv[1]))["result"]["energy"]
if "joules_micro" in e:
uj=e["joules_micro"]; u=e["energy_uncertainty"]
assert uj > 0 and e["energy_provenance"] == "OnChipCounter", e
assert u["relative_ppm"] > 0 and u["window_us"] > 0 and uj * u["relative_ppm"] >= 288676, e
assert e["energy_counter_filtering"] in ("Unknown", "Off", "On") and e["coverage"] in ("whole", "partial"), e
print("energy: %.6f J of CPU, %s, %s" % (uj / 1e6, e["coverage"], e["energy_provenance"]))
else:
assert os.environ["SMOKE_EXPECT_ENERGY"] != "1", e
assert e["unmetered"], e
print("energy: unmetered,", e["unmetered"])' "$tmp/ghz.out"
py 'import json,sys
d=json.load(open(sys.argv[1]))
e=d["result"]["energy"]
if "joules_micro" in e: e["joules_micro"] += 1
else: e["unmetered"] += "."
json.dump(d, open(sys.argv[2],"w"))' "$tmp/vj.json" "$tmp/ve.json"
post /v1/verify "$tmp/ve.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is False, d; print("energy: a changed figure does not verify")'
# As a browser sends it back: whole doubles without a fraction, keys reversed.
py 'import json,sys
def js(v):
if isinstance(v, float) and v.is_integer(): return int(v)
if isinstance(v, dict): return {k: js(v[k]) for k in reversed(list(v))}
if isinstance(v, list): return [js(x) for x in v]
return v
v=json.load(open(sys.argv[1])); json.dump(js(v), open(sys.argv[2],"w"))' "$tmp/vj.json" "$tmp/vjs.json"
post /v1/verify "$tmp/vjs.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies after a browser-style round trip")'
# Continuous angles on a small circuit: the dense state vector, and the
# probabilities sum to the shots.
py 'import json; print(json.dumps({"qasm": "qubit[3] q; rx(0.3) q[0]; ry(1.2) q[1]; cx q[0], q[2]; crz(0.7) q[1], q[2];", "shots": 500, "observables": ["Z0", "Z1 Z2"]}))' > "$tmp/rot.json"
run "$tmp/rot.json" "$tmp/rot.out"
py 'import json,sys,math
d=json.load(open(sys.argv[1])); r=d["result"]
assert d["status"]=="done" and r["method"]=="statevector", d
assert sum(r["counts"].values())==500
z0=r["expectations"][0]["value"]; assert abs(z0-math.cos(0.3))<1e-12, z0
print("rotations: ok, <Z0> =", z0)' "$tmp/rot.out"
# A 100-qubit circuit's expectation values: sparse Pauli dynamics, each value
# with its bound.
py 'import json
n=100
q="qubit[%d] q;\n" % n + "".join("rx(0.3) q[%d];\n" % i for i in range(n)) + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
print(json.dumps({"qasm": q, "observables": ["Z0", "Z50 Z51"]}))' > "$tmp/wide.json"
run "$tmp/wide.json" "$tmp/wide.out"
py 'import json,sys,math
d=json.load(open(sys.argv[1])); r=d["result"]
assert d["status"]=="done" and r["method"]=="pauli", d
e=r["expectations"]; assert all("bound" in x for x in e), e
assert abs(e[0]["value"]-math.cos(0.3)) <= e[0]["bound"]+1e-9, e
print("pauli-100: ok,", [(x["observable"], round(x["value"],6), x["bound"]) for x in e])' "$tmp/wide.out"
# The pauli answer carries its threshold ladder, and the smaller threshold
# never drops more.
py 'import json,sys
d=json.load(open(sys.argv[1])); e=d["result"]["expectations"][0]
l=e["ladder"]; b=[x["bound"] for x in l]
assert len(l)>=2 and l[-1]["value"]==e["value"] and all(y<=x+1e-12 for x,y in zip(b,b[1:])), e
print("pauli ladder: ok,", [(x["threshold"], round(x["value"],6)) for x in l])' "$tmp/wide.out"
# Noisy shots: branching trajectories, every shot counted, and shots that
# share their errors sharing a state.
py 'import json
n=14
q="qubit[%d] q;\nbit[%d] c;\n" % (n,n) + "".join("ry(0.4) q[%d];\n" % i for i in range(n)) + "".join("cz q[%d], q[%d];\n" % (i,i+1) for i in range(n-1)) + "c = measure q;\n"
print(json.dumps({"qasm": q, "method": "trajectories", "shots": 2000, "noise": {"depolarizing_1q": 0.0005, "depolarizing_2q": 0.002, "readout": 0.01}}))' > "$tmp/noisy.json"
run "$tmp/noisy.json" "$tmp/noisy.out"
py 'import json,sys
d=json.load(open(sys.argv[1])); assert d.get("status")=="done", d; r=d["result"]
assert r["method"]=="trajectories", d
assert sum(r["counts"].values())==2000, r
h=r["accuracy"]["histories"]; assert 1 <= h < 2000, r["accuracy"]
print("noisy-14: ok,", r["method"], h, "histories for 2000 shots")' "$tmp/noisy.out"
# A wide noisy Clifford circuit: Pauli frames on the stabilizer tableau.
py 'import json
n=500
q="qubit[%d] q;\n" % n + "h q[0];\n" + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
print(json.dumps({"qasm": q, "shots": 1000, "noise": {"depolarizing_2q": 0.0005, "readout": 0.001}, "observables": ["Z0 Z499"]}))' > "$tmp/nghz.json"
run "$tmp/nghz.json" "$tmp/nghz.out"
py 'import json,sys
d=json.load(open(sys.argv[1])); assert d.get("status")=="done", d; r=d["result"]
assert r["method"]=="stabilizer" and r["accuracy"]["class"]=="estimate", d
assert sum(r["counts"].values())==1000, r
e=r["expectations"][0]; assert 0.5 < e["value"] < 1.0 and e["stderr"] > 0, e
print("noisy-ghz-500: ok,", r["method"], "<Z0 Z499> =", round(e["value"],4), "±", round(e["stderr"],4))' "$tmp/nghz.out"
# The single-precision state vector on the GPU, where the service has one,
# against the double-precision one.
if py 'import json,sys; d=json.load(open(sys.argv[1])); sys.exit(0 if any(m["method"]=="statevector_single" and m.get("available") for m in d["methods"]) else 1)' "$tmp/describe.json"; then
py 'import json; print(json.dumps({"qasm": "qubit[12] q; h q; rx(0.3) q[0]; cx q[0], q[11]; crz(0.7) q[3], q[9]; ry(1.1) q[5];", "observables": ["Z0 Z11", "X5"], "method": "statevector_single"}))' > "$tmp/gpu.json"
py 'import json,sys; d=json.load(open(sys.argv[1])); d["method"]="statevector"; json.dump(d, open(sys.argv[2],"w"))' "$tmp/gpu.json" "$tmp/cpu.json"
run "$tmp/gpu.json" "$tmp/gpu.out"
run "$tmp/cpu.json" "$tmp/cpu.out"
py 'import json,sys
g=json.load(open(sys.argv[1])); c=json.load(open(sys.argv[2])); assert g.get("status")=="done" and c.get("status")=="done", (g, c)
gv=[e["value"] for e in g["result"]["expectations"]]; cv=[e["value"] for e in c["result"]["expectations"]]
assert g["result"]["accuracy"]["class"]=="single" and all(abs(a-b)<1e-5 for a,b in zip(gv,cv)), (gv, cv)
e=g["result"]["energy"]
# The counter reads the CPU only, so a GPU job never claims a whole figure.
assert "joules_micro" not in e or (e["coverage"]=="partial" and "GPU" in e["excludes"][0]), e
print("gpu: ok,", g["result"]["accuracy"]["device"], gv, "energy", e.get("coverage", "unmetered"))' "$tmp/gpu.out" "$tmp/cpu.out"
else
echo "gpu: this instance has none"
fi
# What a program finds first: the index, the examples, the OpenAPI document.
curl -sS --max-time 30 -H 'accept: application/json' "$U/" > "$tmp/index.json"
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["mcp"].endswith("/mcp") and d["openapi"].endswith("/v1/openapi.json"), d; print("index: ok,", d["mcp"])' "$tmp/index.json"
curl -sS --max-time 30 "$U/v1/examples" > "$tmp/examples.json"
curl -sS --max-time 30 "$U/v1/openapi.json" > "$tmp/openapi.json"
py 'import json,sys
e=json.load(open(sys.argv[1]))["examples"]; o=json.load(open(sys.argv[2]))
assert len(e)>=5 and all("job" in x and "qasm" in x["job"] for x in e), e
assert o["openapi"].startswith("3.1") and "/v1/run" in o["paths"] and "/mcp" in o["paths"], list(o["paths"])
print("examples and openapi: ok,", len(e), "examples,", len(o["paths"]), "paths")' "$tmp/examples.json" "$tmp/openapi.json"
# An agent over the Model Context Protocol: initialize, list the tools, run
# the first example, and check its receipt.
mcp() { curl -sS --max-time 120 -X POST "$U/mcp" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' --data-binary "$1"; }
mcp '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' > "$tmp/mcp-init.json"
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary '{"jsonrpc":"2.0","method":"notifications/initialized"}')
mcp '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' > "$tmp/mcp-tools.json"
py 'import json,sys
i=json.load(open(sys.argv[1]))["result"]; t=json.load(open(sys.argv[2]))["result"]["tools"]
assert i["protocolVersion"]=="2025-06-18" and "tools" in i["capabilities"], i
names={x["name"] for x in t}; assert {"run_quantum_circuit","get_quantum_job","verify_quantum_receipt","quantum_service_info","quantum_circuit_examples","critique_qasm","check_equivalent","improve_qasm","classical_shortcuts"} <= names, names
assert sys.argv[3]=="202", sys.argv[3]
print("mcp: ok, initialized,", len(t), "tools")' "$tmp/mcp-init.json" "$tmp/mcp-tools.json" "$code"
py 'import json,sys
job=json.load(open(sys.argv[1]))["examples"][0]["job"]
print(json.dumps({"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run_quantum_circuit","arguments":job}}))' "$tmp/examples.json" > "$tmp/mcp-call.json"
mcp "@$tmp/mcp-call.json" > "$tmp/mcp-run.json"
py 'import json,sys
r=json.load(open(sys.argv[1]))["result"]; job=r["structuredContent"]; text=r["content"][0]["text"]
assert not r["isError"] and job["status"]=="done" and "counts" in job["result"], r
assert "method:" in text and "counts" in text, text
req=json.load(open(sys.argv[2]))["examples"][0]["job"]
print(json.dumps({"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"verify_quantum_receipt","arguments":{"request":req,"result":job["result"]}}}))' "$tmp/mcp-run.json" "$tmp/examples.json" > "$tmp/mcp-verify.json"
curl -sS --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary "@$tmp/mcp-verify.json" > "$tmp/mcp-verified.json"
py 'import json,sys
v=json.load(open(sys.argv[1]))["result"]; assert v["structuredContent"]["valid"] is True, v
print("mcp run + verify: ok,", json.load(open(sys.argv[2]))["result"]["content"][0]["text"].splitlines()[1])' "$tmp/mcp-verified.json" "$tmp/mcp-run.json"
# Grover's search on five qubits as the IDE writes it: its oracle and its
# diffusion are each a Z under four controls. Four rounds find the item.
py 'import json
n, marked = 5, 0b10110
def mcz(): return "ctrl(4) @ z q[0],q[1],q[2],q[3],q[4];\n"
q = "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[5] q;\n" + "".join("h q[%d];\n" % i for i in range(n))
for _ in range(4):
flips = "".join("x q[%d];\n" % i for i in range(n) if not marked >> i & 1)
q += flips + mcz() + flips
q += "".join("h q[%d];\nx q[%d];\n" % (i, i) for i in range(n)) + mcz() + "".join("x q[%d];\nh q[%d];\n" % (i, i) for i in range(n))
print(json.dumps({"qasm": q, "shots": 1000}))' > "$tmp/grover.json"
run "$tmp/grover.json" "$tmp/grover.out"
py 'import json,sys
d=json.load(open(sys.argv[1])); r=d["result"]
hits=r["counts"].get("10110", 0)
assert d["status"]=="done" and hits > 980, d
print("grover-5 (ctrl modifiers): ok,", r["method"], hits, "of 1000 on the marked item")' "$tmp/grover.out"
# A program that measures in the middle and acts on what it read: teleportation
# delivers ry(0.7)|0⟩ to q[2], so ⟨Z2⟩ = cos 0.7 and ⟨X2⟩ = sin 0.7 exactly.
py 'import json; print(json.dumps({"qasm": "OPENQASM 3.0; qubit[3] q; bit[3] c; ry(0.7) q[0]; h q[1]; cx q[1], q[2]; cx q[0], q[1]; h q[0]; c[0] = measure q[0]; c[1] = measure q[1]; if (c[1]) x q[2]; if (c[0]) z q[2]; c[2] = measure q[2];", "observables": ["Z2", "X2"], "shots": 2000}))' > "$tmp/tele.json"
run "$tmp/tele.json" "$tmp/tele.out"
py 'import json,math,sys
d=json.load(open(sys.argv[1])); r=d["result"]; e=[x["value"] for x in r["expectations"]]
assert d["status"]=="done" and abs(e[0]-math.cos(0.7))<1e-12 and abs(e[1]-math.sin(0.7))<1e-12, d
assert r["dynamic"]["branches_weighed"]==4 and sum(r["counts"].values())==2000, r
print("teleport (mid-circuit measurement, if): ok,", r["method"], e)' "$tmp/tele.out"
# A Clifford circuit on 60 qubits, then T and H on each: past the state
# vector, and not Clifford, so auto samples it exactly by cut-rank. Its graph
# (a ring with chords of length 5) keeps every cut narrow.
py 'import json
n=60; q="OPENQASM 3.0; qubit[%d] q; bit[%d] c; h q;" % (n, n)
q+="".join(" cz q[%d], q[%d]; cz q[%d], q[%d];" % (i, (i+1)%n, i, (i+5)%n) for i in range(n))
q+="".join(" t q[%d]; h q[%d];" % (i, i) for i in range(n)) + " c = measure q;"
print(json.dumps({"qasm": q, "shots": 100, "seed": 3}))' > "$tmp/cut.json"
run "$tmp/cut.json" "$tmp/cut.out"
py 'import json,sys
d=json.load(open(sys.argv[1])); r=d["result"]
assert d["status"]=="done" and r["method"]=="cutrank" and sum(r["counts"].values())==100, d
assert r["accuracy"]["class"]=="exact" and r["accuracy"]["max_cut"]<=12, r["accuracy"]
print("cutrank (60 qubits, Clifford then T and H): ok, max cut", r["accuracy"]["max_cut"], "bits,", r["distinct_outcomes"], "distinct outcomes")' "$tmp/cut.out"
# A refusal says why.
py 'import json; print(json.dumps({"qasm": "qubit[1] q; bit c; c = measure q; while (c) { x q; c = measure q; }"}))' > "$tmp/bad.json"
code=$(curl -sS -o "$tmp/bad.out" -w '%{http_code}' -X POST "$U/v1/jobs" -H 'content-type: application/json' --data-binary "@$tmp/bad.json")
[ "$code" = 400 ] || { echo "a bad program got HTTP $code"; exit 1; }
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "not supported" in d["error"], d; print("refusal: ok,", d["error"])' "$tmp/bad.out"
# The design checks answer at once: a critique, an improvement checked the same
# circuit, the equivalence check, the classical shortcuts, and a thorough search
# sent to the command line.
py 'import json; print(json.dumps({"qasm": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nh q[0];\ncx q[0], q[1];\n"}))' > "$tmp/design.json"
post /v1/critique "$tmp/design.json" > "$tmp/critique.out"
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["ok"] and d["gates"]==3 and d["smells"][0]["kind"]=="cancels" and d["smells"][0]["lines"]==[3,4], d; print("critique: ok,", d["smells"][0]["message"])' "$tmp/critique.out"
post /v1/improve "$tmp/design.json" > "$tmp/improve.out"
py 'import json,sys; c=json.load(open(sys.argv[1]))["candidates"][0]; assert c["measures"]["gates"]==1 and c["equivalence"]["verdict"]=="equivalent", c; print("improve: ok,", c["equivalence"]["how"])' "$tmp/improve.out"
py 'import json; print(json.dumps({"a": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nh q[0];\ncx q[0], q[1];\n", "b": "OPENQASM 3.0;\nqubit[2] q;\ncx q[0], q[1];\n"}))' > "$tmp/pair.json"
post /v1/equivalent "$tmp/pair.json" > "$tmp/equivalent.out"
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["verdict"]=="equivalent" and d["how"]=="tableau", d; print("equivalent: ok, by tableau")' "$tmp/equivalent.out"
post /v1/shortcuts "$tmp/design.json" > "$tmp/shortcuts.out"
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["summary"].startswith("Classically easy at any width"), d; print("shortcuts: ok,", d["summary"][:40] + "…")' "$tmp/shortcuts.out"
py 'import json; print(json.dumps({"qasm": "qubit[1] q;", "thorough": True}))' > "$tmp/thorough.json"
code=$(curl -sS -o "$tmp/thorough.out" -w '%{http_code}' -X POST "$U/v1/shortcuts" -H 'content-type: application/json' --data-binary "@$tmp/thorough.json")
[ "$code" = 422 ] || { echo "a thorough search got HTTP $code"; exit 1; }
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum shortcuts --thorough" in d["error"], d; print("thorough: ok, sent to the command line")' "$tmp/thorough.out"
echo "smoke: every check held at $U"