diff --git a/.github/workflows/repo-checks.yml b/.github/workflows/repo-checks.yml index 7df9bf358..b1c869d7c 100644 --- a/.github/workflows/repo-checks.yml +++ b/.github/workflows/repo-checks.yml @@ -112,6 +112,18 @@ jobs: if: ${{ !cancelled() }} run: python scripts/check-wai-section-refs.py + # ── Every wai.quantum string is registered, listed or a schema's name ──── + # The registry export (wai/registry/capabilities.json, generated from + # wai/wai-rs/src/codecs/registry.rs) and the quantum crates' schema files are the + # lists; this reads them and every text file, and names the file and line of any + # string neither accounts for (wai/REGISTRY.md). + - name: "quantum names: the check fails closed (self-test)" + if: ${{ !cancelled() }} + run: bash scripts/check-wai-quantum-names-selftest.sh + - name: "quantum names: every wai.quantum string is registered, listed or a schema's name" + if: ${{ !cancelled() }} + run: python3 -I scripts/check-wai-quantum-names.py + # ── The lists wai-conformance.yml derives hold the hand lists they replaced ─ # Its feature lists, test lists, verifier steps, corpora and gate paths are read from # the files that own them (.github/wai-conformance/, the tags of wai/wai-rs/tests/). diff --git a/scripts/check-wai-quantum-names-selftest.sh b/scripts/check-wai-quantum-names-selftest.sh new file mode 100755 index 000000000..cffa3e15f --- /dev/null +++ b/scripts/check-wai-quantum-names-selftest.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +# +# check-wai-quantum-names-selftest.sh — check-wai-quantum-names.py can fail. +# +# A check that cannot fail is decoration. This builds a scratch repository shaped like +# this one (a registry export, the registry's table and page, a crate with a schema file +# and a source that uses each kind of accounted string, a changelog, a binary file) and +# asserts that the check passes it, and fails each way a string can go unaccounted, +# naming the file and line. The namespace's prefix is spelled through $q here, so this +# file holds none of the test's strings itself. +set -uo pipefail + +here=$(cd "$(dirname "$0")" && pwd) +check="$here/check-wai-quantum-names.py" +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +q=wai.quantum + +mk() { + rm -rf "$tmp/repo" + mkdir -p "$tmp/repo/wai/registry" "$tmp/repo/wai/wai-rs/src/codecs" "$tmp/repo/wai/crate/src" \ + "$tmp/repo/wai/crate/schemas" "$tmp/repo/wai/changes" + cd "$tmp/repo" || exit 2 + git init -q . + cat > wai/registry/capabilities.json < wai/wai-rs/src/codecs/registry.rs < wai/REGISTRY.md + cat > wai/crate/schemas/doc.v1.json < wai/crate/src/lib.rs <, "$q.". +pub fn sentence() -> &'static str { "it reads $q.circuit." } +R + # The changelog keeps names as they were, and a binary file is not a source. + printf '### A change\n\n- \x60%s\x60 was renamed.\n' "$q.renamed" > wai/CHANGELOG.md + printf '### A change\n\n- \x60%s\x60 is new.\n' "$q.entry" > wai/changes/2026-01-01-a-change.md + printf 'WQC1\0\0%s\0' "$q.circuit/9" > wai/crate/vector.bin + git add -A + cd "$here" || exit 2 +} + +fails=0 +expect() { # expect [text the output must hold] + local want=$1 what=$2 needle=${3:-} out rc + out=$(python3 -I "$check" --root "$tmp/repo" 2>&1); rc=$? + if [ "$want" = pass ] && [ $rc -ne 0 ]; then echo "FAIL $what: the check failed"; printf '%s\n' "$out" | sed 's/^/ /'; fails=$((fails+1)); return; fi + if [ "$want" = fail ] && [ $rc -eq 0 ]; then echo "FAIL $what: the check passed"; printf '%s\n' "$out" | sed 's/^/ /'; fails=$((fails+1)); return; fi + if [ -n "$needle" ] && ! printf '%s\n' "$out" | grep -qF -- "$needle"; then + echo "FAIL $what: the output does not say '$needle'"; printf '%s\n' "$out" | sed 's/^/ /'; fails=$((fails+1)); return + fi + echo "ok $what" +} + +mk +expect pass "every kind of accounted string, a placeholder, a prefix, the changelog and a binary file" + +mk +printf 'pub const X: &str = "%s";\n' "$q.planted" >> "$tmp/repo/wai/crate/src/lib.rs" +expect fail "an unlisted string in a tracked source" "wai/crate/src/lib.rs:8: $q.planted is not registered" + +mk +printf '%s\n' "see $q.planted/1" > "$tmp/repo/wai/crate/notes.md" +expect fail "an unlisted string in a file not yet added" "wai/crate/notes.md:1: $q.planted/1" + +mk +printf '%s\n' "the family $q.nofam.*" >> "$tmp/repo/wai/crate/src/lib.rs" +expect fail "a pattern that matches nothing" "$q.nofam.* matches no" + +mk +sed -i.bak "s|$q.doc/1\"|$q.doc/2\"|" "$tmp/repo/wai/crate/schemas/doc.v1.json" && rm "$tmp/repo/wai/crate/schemas/doc.v1.json.bak" +expect fail "a schema whose title is not its file's name" "doc.v1.json: its title is $q.doc/2" + +mk +sed -i.bak "/FAM/d" "$tmp/repo/wai/crate/src/lib.rs" && rm "$tmp/repo/wai/crate/src/lib.rs.bak" +sed -i.bak "s|$q.fam.\*|the family|" "$tmp/repo/wai/crate/src/lib.rs" && rm "$tmp/repo/wai/crate/src/lib.rs.bak" +expect fail "a label nothing outside the registry uses" "the label $q.fam.one is used nowhere outside" + +mk +sed -i.bak "s|\"name\": \"$q.wire/1\"|\"name\": \"$q.module\"|" "$tmp/repo/wai/registry/capabilities.json" && rm "$tmp/repo/wai/registry/capabilities.json.bak" +expect fail "a string the registry holds twice" "$q.module is held twice" + +mk +printf 'pub const X: &str = "%s";\n' "$q.planted" >> "$tmp/repo/wai/crate/src/lib.rs" +sed -i.bak "s|{\"label\": \"$q.module\"|{\"label\": \"$q.planted\", \"reason\": \"r\"}, &|" "$tmp/repo/wai/registry/capabilities.json" && rm "$tmp/repo/wai/registry/capabilities.json.bak" +expect pass "the planted string, once listed as a label" + +mk +rm "$tmp/repo/wai/registry/capabilities.json" +expect fail "no registry export (fails closed)" "cannot read wai/registry/capabilities.json" + +mk +rm -rf "$tmp/repo/.git" +expect fail "not a git checkout (fails closed)" "check-wai-quantum-names: git" + +if [ $fails -ne 0 ]; then + echo "$fails self-test case(s) failed" + exit 1 +fi +echo "check-wai-quantum-names: every self-test case behaves" diff --git a/scripts/check-wai-quantum-names.py b/scripts/check-wai-quantum-names.py new file mode 100755 index 000000000..cdbc7f134 --- /dev/null +++ b/scripts/check-wai-quantum-names.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +"""check-wai-quantum-names.py: every `wai.quantum.*` string in the tree is accounted for. + +A string of the quantum namespace is one of: + + - a string the registry registers (a capability or a record), or one of its named + identifiers, unregistered labels or wire identifiers. The registry is one table, + wai/wai-rs/src/codecs/registry.rs, exported by `wai registry export` as + wai/registry/capabilities.json (CI holds the export to the table with + `wai registry export --check`). This reads the export. A label there says what it + names: a module of the quantum crates, a receipt kind, a kernel, a document with no + schema file, or a string a test gives a reader to see it refused. + - the name of a document a quantum crate writes, `wai.quantum./`, + kept as a JSON Schema at `schemas/.v.json` beside the crate's + manifest, whose `title` is the name (wai/wai-quantum/VERSIONING.md, *The schemas*). + A name such a file gives as the `const` of a member (a document carried inside + another) is accounted for the same way. The schema files are the list: a new + document adds its file, and no line anywhere else. + +A string is `wai.quantum.` followed by dot-separated segments of letters, digits, `_` +and `-`, and optionally `/` and a revision (`wai.quantum.circuit2`, +`wai.quantum.cal.noise_learn`, `wai.quantum.job-result/1`, `wai.quantum.sv/run-wide`). +A pattern `wai.quantum..*` is accounted for when some accounted string starts +with `wai.quantum..`. A placeholder (`wai.quantum.`) or a prefix +(`"wai.quantum."`) is not a string and is not read. + +Every text file git tracks or would track is read, except the changelog +(wai/CHANGELOG.md and the entry files of wai/changes/): it records names as they were +when each change was made. Binary files are not read. + +Findings, one line each: + + - a string accounted for by none of the above, with its file and line; + - a quantum schema file whose `title` is not the name its file name gives; + - a `wai.quantum.*` label or wire identifier that nothing outside the registry's own + files (registry.rs, its export, REGISTRY.md) uses, so the list stays the set of + strings in use; + - a `wai.quantum.*` string the registry holds twice. + + check-wai-quantum-names.py [--root DIR] + +Exit 0 when every string is accounted for, 1 with one line a finding otherwise, 2 when +the tree cannot be read. Standard library only. +""" +import json +import os +import re +import subprocess +import sys + +PREFIX = "wai.quantum." +# A string of the namespace, with its revision and a trailing `.*` (a pattern). +TOKEN = re.compile( + r"wai\.quantum\.([A-Za-z0-9_][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_][A-Za-z0-9_-]*)*)" + r"(/[A-Za-z0-9_-]+)?(\.\*)?" +) +EXPORT = "wai/registry/capabilities.json" +# The registry's own files: the table, its export and the page that prints it. +REGISTRY_FILES = {"wai/wai-rs/src/codecs/registry.rs", EXPORT, "wai/REGISTRY.md"} +# The record of past changes, read by nothing here. +HISTORY = ("wai/CHANGELOG.md", "wai/changes/") +SCHEMA_FILE = re.compile(r"(?:^|/)schemas/([a-z0-9_-]+(?:\.[a-z0-9_-]+)*)\.v([0-9]+)\.json$") + + +def fail(msg): + print(f"check-wai-quantum-names: {msg}", file=sys.stderr) + sys.exit(2) + + +def git(root, *args): + r = subprocess.run(["git", "-C", root, *args], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return r.returncode, r.stdout.decode("utf-8", "replace"), r.stderr.decode("utf-8", "replace") + + +def occurrences(root): + """Every string of the namespace in the text files git tracks or would track: + [(path, line, string, is_pattern)].""" + rc, out, err = git(root, "grep", "-I", "-n", "-z", "--untracked", "-F", "-e", PREFIX) + if rc == 1: + return [] + if rc != 0: + fail(f"git grep failed ({rc}): {err.strip()}") + found = [] + for rec in out.split("\n"): + if not rec: + continue + parts = rec.split("\0", 2) + if len(parts) != 3: + fail(f"unreadable git grep line: {rec[:120]!r}") + path, line, text = parts + if path == HISTORY[0] or path.startswith(HISTORY[1]): + continue + for m in TOKEN.finditer(text): + name = PREFIX + m.group(1) + (m.group(2) or "") + found.append((path, int(line), name, bool(m.group(3)))) + return found + + +def registry(root): + """The strings the export holds, by table, and the quantum strings it holds twice.""" + path = os.path.join(root, EXPORT) + try: + with open(path, encoding="utf-8") as fh: + doc = json.load(fh) + except (OSError, ValueError) as e: + fail(f"cannot read {EXPORT}: {e}") + tables = { + "registered": [c["capability"] for c in doc.get("capabilities", [])], + "identifier": [i["identifier"] for i in doc.get("identifiers", [])], + "label": [l["label"] for l in doc.get("unregistered_labels", [])], + "wire identifier": [w["name"] for w in doc.get("wire_identifiers", [])], + } + if not tables["registered"]: + fail(f"{EXPORT} registers nothing") + held = {} + twice = [] + for table, names in tables.items(): + for n in names: + if n.startswith(PREFIX): + if n in held: + twice.append(f"{EXPORT}: {n} is held twice ({held[n]}, {table})") + held.setdefault(n, table) + return tables, held, twice + + +def schema_names(root): + """The document names the quantum schema files give, and the findings about them.""" + rc, out, err = git(root, "ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", "wai/") + if rc != 0: + fail(f"git ls-files failed ({rc}): {err.strip()}") + names, findings = {}, [] + + def consts(v, acc): + if isinstance(v, dict): + for k, x in v.items(): + if k == "const" and isinstance(x, str): + acc.append(x) + else: + consts(x, acc) + elif isinstance(v, list): + for x in v: + consts(x, acc) + + for path in sorted(p for p in out.split("\0") if p): + m = SCHEMA_FILE.search(path) + if not m or not os.path.isfile(os.path.join(root, path)): + continue + try: + with open(os.path.join(root, path), encoding="utf-8") as fh: + doc = json.load(fh) + except (OSError, ValueError) as e: + findings.append(f"{path}: not a JSON document ({e})") + continue + title = doc.get("title") if isinstance(doc, dict) else None + if not (isinstance(title, str) and title.startswith(PREFIX)): + continue + want = f"{PREFIX}{m.group(1)}/{m.group(2)}" + if title != want: + findings.append(f"{path}: its title is {title}, but a schema of that file is named {want}") + continue + names.setdefault(title, path) + acc = [] + consts(doc, acc) + for c in acc: + t = TOKEN.fullmatch(c) + if t and not t.group(3): + names.setdefault(c, path) + return names, findings + + +def main(argv): + root = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) + if len(argv) == 2 and argv[0] == "--root": + root = os.path.abspath(argv[1]) + elif argv: + fail("usage: check-wai-quantum-names.py [--root DIR]") + tables, held, findings = registry(root) + accounted = {n for names in tables.values() for n in names} + schemas, schema_findings = schema_names(root) + findings += schema_findings + accounted |= set(schemas) + + used_outside = set() + seen = 0 + for path, line, name, pattern in occurrences(root): + seen += 1 + if path not in REGISTRY_FILES: + used_outside.add(name) + if pattern: + stem = name + "." + if not any(a.startswith(stem) for a in accounted): + findings.append(f"{path}:{line}: {name}.* matches no registered string, label or schema's name") + continue + if name not in accounted: + findings.append(f"{path}:{line}: {name} is not registered, listed as a label or wire identifier, " + f"or the name of a quantum schema file") + for n, table in sorted(held.items()): + if table in ("label", "wire identifier") and n not in used_outside: + findings.append(f"{EXPORT}: the {table} {n} is used nowhere outside the registry's own files") + + if findings: + for f in findings: + print(f) + sys.stdout.flush() + print(f"\n{len(findings)} finding(s). A new `wai.quantum.*` string is registered, or listed with what it " + "names in UNREGISTERED_LABELS (wai/wai-rs/src/codecs/registry.rs, beside its group), then " + "`wai registry export` is run; a document's name is its schema file " + "(`schemas/.v.json`, its `title` the name).", file=sys.stderr) + return 1 + print(f"check-wai-quantum-names: every wai.quantum string is accounted for " + f"({seen} occurrences read; {len(schemas)} named by schema files)") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/wai/README.md b/wai/README.md index 883cd18eb..565d367f5 100644 --- a/wai/README.md +++ b/wai/README.md @@ -277,8 +277,9 @@ reconstructs to the same statevector hash on a laptop or at the edge. `wai.quantum.circuit2` and `wai.quantum.circuit` are the registered payload capabilities, and `wai.quantum.calibration` and `wai.quantum.job` are registered -records; the other names below are module labels ([`REGISTRY.md`](REGISTRY.md) -lists the receipt labels no revision registers). The two circuit capabilities +records; the other names below are module labels, which no revision registers +([`REGISTRY.md`](REGISTRY.md) lists them with every other `wai.quantum.*` label, and +says what each names). The two circuit capabilities share the container and the gates and differ in the phase table: circuit2's holds the integers nearest to each phase and is the default for new content, and `wai.quantum.circuit` is frozen so that every file, hash and receipt made with it diff --git a/wai/REGISTRY.md b/wai/REGISTRY.md index 4149984c5..c2ce0f1f1 100644 --- a/wai/REGISTRY.md +++ b/wai/REGISTRY.md @@ -54,7 +54,11 @@ Two further tables hold strings that look like capabilities and are not: `wai.quantum.circuit2`; `wai.world.sim.*`, the simulation steps of the feed and avatar capabilities); - **unregistered labels** are strings the reference implementation uses as labels - that no revision registers, each with the reason. + that no revision registers, each with what it names: the receipt kinds and the + modules of the quantum crates, the kernels and corpora a fabric certificate names, the + revision a circuit contract names, the documents that have no schema file, the domains + digests start with, and the strings the tests and corpora give a reader to see it + refuse them. A third holds the **wire identifiers**: the names the container, its delivery bindings ([http-delivery](extensions/http-delivery.md), @@ -78,6 +82,18 @@ defines it, and whether it is defined, provisional (test material only until registered) or proposed (not registered). A library test checks that each is written in the section it names. +Every `wai.quantum.*` string in the tree is accounted for: registered, an unregistered +label or a wire identifier here, or the name of a document a quantum crate writes, +`wai.quantum./`, whose JSON Schema the crate keeps as +`schemas/.v.json` with that name as its `title` +([wai-quantum/VERSIONING.md](wai-quantum/VERSIONING.md), *The schemas*). A name such a +schema gives as the `const` of a member, a document carried inside another, is accounted +for the same way, so a new document adds its schema file and no line here. +`scripts/check-wai-quantum-names.py`, in the repository checks, reads the export and the +schema files, and names the file and line of any other string, a schema file whose +`title` is not the name its file name gives, and a quantum label that nothing outside the +registry uses. It does not read the changelog, which keeps names as they were. + ## Status - **registered** — the payload format (for a record or derivation, the @@ -350,6 +366,75 @@ and a role are fixed once registered. | `wai.quantum.rearrange` | a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record | | `wai.quantum.qbom` | a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record | | `wai.quantum.fabric` | a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record | +| `wai.quantum.toolchain` | a module label: wai-quantum's `quantum_toolchain`, the toolchain's compute core (its backends, the algorithm library, OpenQASM 3 in and out) | +| `wai.quantum.sv` | a module label: wai-quantum's `quantum_sv`, the dense state vector, any gate at any angle | +| `wai.quantum.sv.metal` | a module label: wai-quantum's `quantum_sv_metal`, the dense state vector on the platform's GPU, in single precision | +| `wai.quantum.stabilizer` | a module label: wai-quantum's `quantum_stabilizer`, the stabilizer (CHP) backend | +| `wai.quantum.tableau` | a module label: wai-quantum's `quantum_tableau`, wide stabilizer simulation | +| `wai.quantum.stabrank` | a module label: wai-quantum's `quantum_stabrank`, Clifford+T circuits as sums of stabilizer states | +| `wai.quantum.cutrank.metal` | a module label: wai-quantum's `quantum_cutrank_metal`, the cut-rank table on the platform's GPU, in single precision | +| `wai.quantum.mps` | a module label: wai-quantum's `quantum_mps`, the matrix product state backend | +| `wai.quantum.mpsim` | a module label: wai-quantum's `quantum_mpsim`, matrix product state simulation of circuits with any angles | +| `wai.quantum.tn` | a module label: wai-quantum's `quantum_tn`, tensor-network contraction | +| `wai.quantum.bptn` | a module label: wai-quantum's `quantum_bptn`, tensor-network states on a device's coupling graph, read through belief-propagation environments | +| `wai.quantum.pauli` | a module label: wai-quantum's `quantum_pauli`, sparse-Pauli (Heisenberg) propagation of an observable | +| `wai.quantum.spd` | a module label: wai-quantum's `quantum_spd` and `quantum_spd_receipt`, sparse Pauli dynamics and its signed receipts | +| `wai.quantum.noisy` | a module label: wai-quantum's `quantum_noisy`, noisy circuits | +| `wai.quantum.frame` | a module label: wai-quantum's `quantum_frame`, noisy Clifford circuits at error-correction scale | +| `wai.quantum.gbs` | a module label: wai-quantum's `quantum_gbs`, Gaussian boson sampling, exactly | +| `wai.quantum.cal.rabi` | a module label: wai-quantum's `quantum_cal`, autonomous qubit calibration | +| `wai.quantum.cal.spectroscopy` | a module label: wai-quantum's `quantum_control`, noise spectroscopy | +| `wai.quantum.cal.robust_ff` | a module label: wai-quantum's `quantum_control`, filter-function robust control | +| `wai.quantum.cal.noise_learn` | a module label: wai-quantum's `quantum_noise`, noise learning (cycle benchmarking, sparse Pauli-Lindblad models) | +| `wai.quantum.ldpc` | a module label: wai-quantum's `quantum_ldpc`, quantum LDPC memory at circuit level | +| `wai.quantum.match` | a module label: wai-quantum's `quantum_match`, exact minimum-weight perfect-matching decoding | +| `wai.quantum.uf` | a module label: wai-quantum's `quantum_uf`, union-find decoding | +| `wai.quantum.window` | a module label: wai-quantum's `quantum_window`, decoding as the syndrome arrives | +| `wai.quantum.color` | a module label: wai-quantum's `quantum_color`, colour codes decoded by restriction to matching | +| `wai.quantum.distance` | a module label: wai-quantum's `quantum_distance`, a code's distance certificates | +| `wai.quantum.qec_text` | a module label: wai-quantum's `quantum_qec_text`, the error-correction text formats (noisy Clifford circuits, detector error models), read and written back | +| `wai.quantum.resource` | a module label: wai-quantum's `quantum_resource` and `quantum_resource_receipt`, fault-tolerant resource estimation and its signed estimates | +| `wai.quantum.arch` | a module label: wai-quantum's `quantum_arch`, architecture-level resource estimation | +| `wai.quantum.chem` | a module label: wai-quantum's `quantum_chem`, molecules by DMRG | +| `wai.quantum.dmrg` | a module label: wai-quantum's `quantum_dmrg`, ground states of spin chains by DMRG | +| `wai.quantum.tdvp` | a module label: wai-quantum's `quantum_tdvp`, time evolution of spin chains by TDVP | +| `wai.quantum.nqs` | a module label: wai-quantum's `quantum_nqs`, neural quantum states | +| `wai.quantum.qio` | a module label: wai-quantum's `quantum_qio`, quantum-inspired optimisation | +| `wai.quantum.phasor` | a module label: wai-quantum's `quantum_phasor` and `quantum_phasor_meter`, the phasor bridge and its energy-accounted receipts | +| `wai.quantum.kernel` | a module label: wai-quantum's `quantum_kernel`, the quantum kernel deployed as phasor features; also the method a phasor receipt names for it | +| `wai.quantum.qfhrr` | a module label: wai-quantum's `quantum_qfhrr`, the Born machine on the qFHRR phasor substrate | +| `wai.quantum.vml` | a module label: wai-quantum's `quantum_vml`, variational quantum machine learning | +| `wai.quantum.qdata` | a module label: wai-quantum's `quantum_qdata`, learning from quantum data | +| `wai.quantum.born` | the method a phasor receipt names for the generative Born machine (`quantum_phasor_meter`) | +| `wai.quantum.estimate` | the member of a routine document's `meta` that holds what wai-quantum's resource estimate came from (`engine::estimate::interchange`) | +| `wai.quantum.circuit/apply` | a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit's phase table | +| `wai.quantum.circuit2/apply` | a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit2's phase table | +| `wai.quantum.circuit/sample` | a fabric kernel: sampling, in wai.quantum.circuit's gateset | +| `wai.quantum.circuit2/sample` | a fabric kernel: sampling, in wai.quantum.circuit2's gateset | +| `wai.quantum.circuit/random-v1` | a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit's gateset | +| `wai.quantum.circuit2/random-v1` | a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit2's gateset | +| `wai.quantum.circuit/fabric-v1` | a fabric corpus: the random circuits, then wide circuits of 11 to 17 qubits from the same stream, that every member is certified on, in wai.quantum.circuit's gateset | +| `wai.quantum.circuit2/fabric-v1` | a fabric corpus: the same circuits as wai.quantum.circuit/fabric-v1, in wai.quantum.circuit2's gateset | +| `wai.quantum.sv/run` | a fabric kernel: a gate list run on a dense f64 state, the kernel a statevector job's placement runs | +| `wai.quantum.sv/run-wide` | a fabric kernel: the same run with gates on four to six qubits at once, certified on a corpus of its own | +| `wai.quantum.spd/propagate` | a fabric kernel: an observable propagated through a rotation circuit and truncated, the kernel a pauli job's placement runs | +| `wai.quantum.circuit/1` | a contract revision: the `ext` of a wai.quantum.circuit payload's contract (quantum-sim §2.1), a part of the capability's definition | +| `wai.quantum.circuit2/1` | a contract revision: the `ext` of a wai.quantum.circuit2 payload's contract (quantum-sim §2.1), a part of the capability's definition | +| `wai.quantum.job-record/1` | a document with no schema file: the record a job service's store keeps a job in (wai-quantum-service) | +| `wai.quantum.provider-job/1` | a document with no schema file: the record wai-quantum-qpu keeps of a job on a person's provider, written before the job is sent | +| `wai.quantum.optimize-checkpoint/1` | a document with no schema file: an optimisation's checkpoint (wai-quantum's `engine::variational`) | +| `wai.quantum.qec_text.vectors/1` | a document with no schema file: the corpus of the error-correction text formats (quantum-conformance/qec-text) | +| `wai.quantum.docs-manifest/1` | a document with no schema file: the list of documents tools/quantum-docs checks | +| `wai.quantum.job-key/1` | a digest domain: the digest a job service keeps a client's idempotency key under, the client's name beside the key (wai-quantum-service) | +| `wai.quantum.trace/1` | a digest domain: an optimisation trace's first link is BLAKE3 of it and the request's canonical text (wai-quantum's `engine::variational`) | +| `wai.quantum.circuit3` | refused on purpose: not a capability; the circuit core's test gives it to see no gateset read from it | +| `wai.quantum.other` | refused on purpose: not a kernel; the fabric's test puts it in a certificate to see the placement refuse that certificate | +| `wai.quantum.x/one` | refused on purpose: not a schema's name, its major not a number; the schema module's test gives it to see no file named for it | +| `wai.quantum.job-result/2` | refused on purpose: a major of the job result's schema that no text defines; a test writes it into a sealed result to see the receipt fail | +| `wai.quantum.target/2` | refused on purpose: a major of the device target's schema that no text defines; the targets' test gives it to see the document refused | +| `wai.quantum.provider/2` | refused on purpose: a version of the provider protocol that no text defines; the reference provider's test sends it to see it answered unsupported_version (quantum-providers §10) | +| `wai.quantum.provider/9` | refused on purpose: a version of the provider protocol that no text defines; the protocol schema's test sends it to see it answered unsupported_version (quantum-providers §10) | +| `wai.quantum.provider/999` | refused on purpose: a version of the provider protocol that no text defines; the provider conformance corpus sends it to see it answered unsupported_version (quantum-providers §10) | | wire identifier (not a capability) | kind | status | defined in | |---|---|---|---| diff --git a/wai/changes/2026-11-05-every-quantum-string-accounted-for.md b/wai/changes/2026-11-05-every-quantum-string-accounted-for.md new file mode 100644 index 000000000..8c5d67353 --- /dev/null +++ b/wai/changes/2026-11-05-every-quantum-string-accounted-for.md @@ -0,0 +1,23 @@ +### Every `wai.quantum.*` string is registered, listed with what it names, or a schema's name + +- **The registry lists the quantum labels no revision registers** + ([REGISTRY.md](REGISTRY.md)). Beside the receipt kinds wai-quantum seals, its unregistered + labels now hold the modules of wai-quantum (`wai.quantum.toolchain`, the + `wai.quantum.cal.*` family and the rest), the names a record's members carry, the kernels + and corpora a fabric member's certificate names (`wai.quantum.circuit/apply`, + `wai.quantum.sv/run-wide`), the revision a circuit contract names in its `ext` + (`wai.quantum.circuit2/1`, quantum-sim §2.1), the documents the quantum crates write that + have no schema file, the domains a digest starts with, and the strings the tests and the + provider conformance corpus give a reader to see it refuse them. Each says what it names, + in a group of the strings it is like. +- **A document's name is its schema file.** `wai.quantum./` is accounted for + when a quantum crate keeps its schema as `schemas/.v.json` with that name + as its `title` (wai-quantum/VERSIONING.md), and so is a name such a schema gives as the + `const` of a member, so a new document adds its file and no line in the registry. +- **CI: the repository checks fail on a string not accounted for.** + `scripts/check-wai-quantum-names.py` reads the registry export and the schema files, and + every text file but the changelog, and names the file and line of a `wai.quantum.*` string + neither accounts for, a `wai.quantum..*` pattern that matches none, a schema file + whose `title` is not the name its file name gives, a quantum label nothing outside the + registry uses, and a string the registry holds twice. Its self-test plants each in a + scratch repository and requires the check to fail, naming it. diff --git a/wai/registry/capabilities.json b/wai/registry/capabilities.json index 071a6ffdc..624a3277d 100644 --- a/wai/registry/capabilities.json +++ b/wai/registry/capabilities.json @@ -2599,29 +2599,305 @@ } ], "unregistered_labels": [ + { + "label": "wai.quantum.arch", + "reason": "a module label: wai-quantum's `quantum_arch`, architecture-level resource estimation" + }, + { + "label": "wai.quantum.born", + "reason": "the method a phasor receipt names for the generative Born machine (`quantum_phasor_meter`)" + }, + { + "label": "wai.quantum.bptn", + "reason": "a module label: wai-quantum's `quantum_bptn`, tensor-network states on a device's coupling graph, read through belief-propagation environments" + }, + { + "label": "wai.quantum.cal.noise_learn", + "reason": "a module label: wai-quantum's `quantum_noise`, noise learning (cycle benchmarking, sparse Pauli-Lindblad models)" + }, + { + "label": "wai.quantum.cal.rabi", + "reason": "a module label: wai-quantum's `quantum_cal`, autonomous qubit calibration" + }, + { + "label": "wai.quantum.cal.robust_ff", + "reason": "a module label: wai-quantum's `quantum_control`, filter-function robust control" + }, + { + "label": "wai.quantum.cal.spectroscopy", + "reason": "a module label: wai-quantum's `quantum_control`, noise spectroscopy" + }, + { + "label": "wai.quantum.chem", + "reason": "a module label: wai-quantum's `quantum_chem`, molecules by DMRG" + }, + { + "label": "wai.quantum.circuit/1", + "reason": "a contract revision: the `ext` of a wai.quantum.circuit payload's contract (quantum-sim §2.1), a part of the capability's definition" + }, + { + "label": "wai.quantum.circuit/apply", + "reason": "a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit's phase table" + }, + { + "label": "wai.quantum.circuit/fabric-v1", + "reason": "a fabric corpus: the random circuits, then wide circuits of 11 to 17 qubits from the same stream, that every member is certified on, in wai.quantum.circuit's gateset" + }, + { + "label": "wai.quantum.circuit/random-v1", + "reason": "a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit's gateset" + }, + { + "label": "wai.quantum.circuit/sample", + "reason": "a fabric kernel: sampling, in wai.quantum.circuit's gateset" + }, + { + "label": "wai.quantum.circuit2/1", + "reason": "a contract revision: the `ext` of a wai.quantum.circuit2 payload's contract (quantum-sim §2.1), a part of the capability's definition" + }, + { + "label": "wai.quantum.circuit2/apply", + "reason": "a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit2's phase table" + }, + { + "label": "wai.quantum.circuit2/fabric-v1", + "reason": "a fabric corpus: the same circuits as wai.quantum.circuit/fabric-v1, in wai.quantum.circuit2's gateset" + }, + { + "label": "wai.quantum.circuit2/random-v1", + "reason": "a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit2's gateset" + }, + { + "label": "wai.quantum.circuit2/sample", + "reason": "a fabric kernel: sampling, in wai.quantum.circuit2's gateset" + }, + { + "label": "wai.quantum.circuit3", + "reason": "refused on purpose: not a capability; the circuit core's test gives it to see no gateset read from it" + }, + { + "label": "wai.quantum.color", + "reason": "a module label: wai-quantum's `quantum_color`, colour codes decoded by restriction to matching" + }, { "label": "wai.quantum.compile", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" }, + { + "label": "wai.quantum.cutrank.metal", + "reason": "a module label: wai-quantum's `quantum_cutrank_metal`, the cut-rank table on the platform's GPU, in single precision" + }, { "label": "wai.quantum.decode", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" }, + { + "label": "wai.quantum.distance", + "reason": "a module label: wai-quantum's `quantum_distance`, a code's distance certificates" + }, + { + "label": "wai.quantum.dmrg", + "reason": "a module label: wai-quantum's `quantum_dmrg`, ground states of spin chains by DMRG" + }, + { + "label": "wai.quantum.docs-manifest/1", + "reason": "a document with no schema file: the list of documents tools/quantum-docs checks" + }, + { + "label": "wai.quantum.estimate", + "reason": "the member of a routine document's `meta` that holds what wai-quantum's resource estimate came from (`engine::estimate::interchange`)" + }, { "label": "wai.quantum.fabric", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" }, + { + "label": "wai.quantum.frame", + "reason": "a module label: wai-quantum's `quantum_frame`, noisy Clifford circuits at error-correction scale" + }, + { + "label": "wai.quantum.gbs", + "reason": "a module label: wai-quantum's `quantum_gbs`, Gaussian boson sampling, exactly" + }, + { + "label": "wai.quantum.job-key/1", + "reason": "a digest domain: the digest a job service keeps a client's idempotency key under, the client's name beside the key (wai-quantum-service)" + }, + { + "label": "wai.quantum.job-record/1", + "reason": "a document with no schema file: the record a job service's store keeps a job in (wai-quantum-service)" + }, + { + "label": "wai.quantum.job-result/2", + "reason": "refused on purpose: a major of the job result's schema that no text defines; a test writes it into a sealed result to see the receipt fail" + }, + { + "label": "wai.quantum.kernel", + "reason": "a module label: wai-quantum's `quantum_kernel`, the quantum kernel deployed as phasor features; also the method a phasor receipt names for it" + }, + { + "label": "wai.quantum.ldpc", + "reason": "a module label: wai-quantum's `quantum_ldpc`, quantum LDPC memory at circuit level" + }, + { + "label": "wai.quantum.match", + "reason": "a module label: wai-quantum's `quantum_match`, exact minimum-weight perfect-matching decoding" + }, { "label": "wai.quantum.mitigate", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" }, + { + "label": "wai.quantum.mps", + "reason": "a module label: wai-quantum's `quantum_mps`, the matrix product state backend" + }, + { + "label": "wai.quantum.mpsim", + "reason": "a module label: wai-quantum's `quantum_mpsim`, matrix product state simulation of circuits with any angles" + }, + { + "label": "wai.quantum.noisy", + "reason": "a module label: wai-quantum's `quantum_noisy`, noisy circuits" + }, + { + "label": "wai.quantum.nqs", + "reason": "a module label: wai-quantum's `quantum_nqs`, neural quantum states" + }, + { + "label": "wai.quantum.optimize-checkpoint/1", + "reason": "a document with no schema file: an optimisation's checkpoint (wai-quantum's `engine::variational`)" + }, + { + "label": "wai.quantum.other", + "reason": "refused on purpose: not a kernel; the fabric's test puts it in a certificate to see the placement refuse that certificate" + }, + { + "label": "wai.quantum.pauli", + "reason": "a module label: wai-quantum's `quantum_pauli`, sparse-Pauli (Heisenberg) propagation of an observable" + }, + { + "label": "wai.quantum.phasor", + "reason": "a module label: wai-quantum's `quantum_phasor` and `quantum_phasor_meter`, the phasor bridge and its energy-accounted receipts" + }, + { + "label": "wai.quantum.provider-job/1", + "reason": "a document with no schema file: the record wai-quantum-qpu keeps of a job on a person's provider, written before the job is sent" + }, + { + "label": "wai.quantum.provider/2", + "reason": "refused on purpose: a version of the provider protocol that no text defines; the reference provider's test sends it to see it answered unsupported_version (quantum-providers §10)" + }, + { + "label": "wai.quantum.provider/9", + "reason": "refused on purpose: a version of the provider protocol that no text defines; the protocol schema's test sends it to see it answered unsupported_version (quantum-providers §10)" + }, + { + "label": "wai.quantum.provider/999", + "reason": "refused on purpose: a version of the provider protocol that no text defines; the provider conformance corpus sends it to see it answered unsupported_version (quantum-providers §10)" + }, { "label": "wai.quantum.qbom", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" }, + { + "label": "wai.quantum.qdata", + "reason": "a module label: wai-quantum's `quantum_qdata`, learning from quantum data" + }, + { + "label": "wai.quantum.qec_text", + "reason": "a module label: wai-quantum's `quantum_qec_text`, the error-correction text formats (noisy Clifford circuits, detector error models), read and written back" + }, + { + "label": "wai.quantum.qec_text.vectors/1", + "reason": "a document with no schema file: the corpus of the error-correction text formats (quantum-conformance/qec-text)" + }, + { + "label": "wai.quantum.qfhrr", + "reason": "a module label: wai-quantum's `quantum_qfhrr`, the Born machine on the qFHRR phasor substrate" + }, + { + "label": "wai.quantum.qio", + "reason": "a module label: wai-quantum's `quantum_qio`, quantum-inspired optimisation" + }, { "label": "wai.quantum.rearrange", "reason": "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record" + }, + { + "label": "wai.quantum.resource", + "reason": "a module label: wai-quantum's `quantum_resource` and `quantum_resource_receipt`, fault-tolerant resource estimation and its signed estimates" + }, + { + "label": "wai.quantum.spd", + "reason": "a module label: wai-quantum's `quantum_spd` and `quantum_spd_receipt`, sparse Pauli dynamics and its signed receipts" + }, + { + "label": "wai.quantum.spd/propagate", + "reason": "a fabric kernel: an observable propagated through a rotation circuit and truncated, the kernel a pauli job's placement runs" + }, + { + "label": "wai.quantum.stabilizer", + "reason": "a module label: wai-quantum's `quantum_stabilizer`, the stabilizer (CHP) backend" + }, + { + "label": "wai.quantum.stabrank", + "reason": "a module label: wai-quantum's `quantum_stabrank`, Clifford+T circuits as sums of stabilizer states" + }, + { + "label": "wai.quantum.sv", + "reason": "a module label: wai-quantum's `quantum_sv`, the dense state vector, any gate at any angle" + }, + { + "label": "wai.quantum.sv.metal", + "reason": "a module label: wai-quantum's `quantum_sv_metal`, the dense state vector on the platform's GPU, in single precision" + }, + { + "label": "wai.quantum.sv/run", + "reason": "a fabric kernel: a gate list run on a dense f64 state, the kernel a statevector job's placement runs" + }, + { + "label": "wai.quantum.sv/run-wide", + "reason": "a fabric kernel: the same run with gates on four to six qubits at once, certified on a corpus of its own" + }, + { + "label": "wai.quantum.tableau", + "reason": "a module label: wai-quantum's `quantum_tableau`, wide stabilizer simulation" + }, + { + "label": "wai.quantum.target/2", + "reason": "refused on purpose: a major of the device target's schema that no text defines; the targets' test gives it to see the document refused" + }, + { + "label": "wai.quantum.tdvp", + "reason": "a module label: wai-quantum's `quantum_tdvp`, time evolution of spin chains by TDVP" + }, + { + "label": "wai.quantum.tn", + "reason": "a module label: wai-quantum's `quantum_tn`, tensor-network contraction" + }, + { + "label": "wai.quantum.toolchain", + "reason": "a module label: wai-quantum's `quantum_toolchain`, the toolchain's compute core (its backends, the algorithm library, OpenQASM 3 in and out)" + }, + { + "label": "wai.quantum.trace/1", + "reason": "a digest domain: an optimisation trace's first link is BLAKE3 of it and the request's canonical text (wai-quantum's `engine::variational`)" + }, + { + "label": "wai.quantum.uf", + "reason": "a module label: wai-quantum's `quantum_uf`, union-find decoding" + }, + { + "label": "wai.quantum.vml", + "reason": "a module label: wai-quantum's `quantum_vml`, variational quantum machine learning" + }, + { + "label": "wai.quantum.window", + "reason": "a module label: wai-quantum's `quantum_window`, decoding as the syndrome arrives" + }, + { + "label": "wai.quantum.x/one", + "reason": "refused on purpose: not a schema's name, its major not a number; the schema module's test gives it to see no file named for it" } ], "wire_identifiers": [ diff --git a/wai/wai-rs/src/codecs/registry.rs b/wai/wai-rs/src/codecs/registry.rs index 06c2a1f5f..0184fb7d6 100644 --- a/wai/wai-rs/src/codecs/registry.rs +++ b/wai/wai-rs/src/codecs/registry.rs @@ -1006,7 +1006,7 @@ pub const WIRE_IDENTIFIERS: &[WireIdentifier] = &[ ]; /// A string with the shape of a capability that the reference implementation uses -/// as a label but that no revision registers, and why. +/// as a label but that no revision registers, and why: what it names. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct UnregisteredLabel { pub label: &'static str, @@ -1015,9 +1015,21 @@ pub struct UnregisteredLabel { const QUANTUM_RECORD_LABEL: &str = "a receipt-kind label the wai-quantum crate seals; no revision of SPEC or of an extension registers it, so it is not a registered record"; -/// Every [`UnregisteredLabel`]. The strings are copies of +const fn label(label: &'static str, reason: &'static str) -> UnregisteredLabel { + UnregisteredLabel { label, reason } +} + +/// Every [`UnregisteredLabel`], grouped by what the strings name, each group in the +/// order its strings build on each other. The receipt kinds are copies of /// `wai_quantum::quantum_ops::CAP_QUANTUM_{MITIGATE,DECODE,COMPILE,REARRANGE,QBOM,FABRIC}`; /// a test under the `quantum_ops` feature holds them equal. +/// +/// Every `wai.quantum.*` string of the tree is registered, listed here or among the wire +/// identifiers, or the name of a document a quantum crate keeps a schema of +/// (`schemas/.v.json`): +/// `scripts/check-wai-quantum-names.py`, in the repository checks, reads the export and +/// names the file and line of any other. A new string goes into the group of the strings +/// it is like, beside the one it builds on. pub const UNREGISTERED_LABELS: &[UnregisteredLabel] = &[ UnregisteredLabel { label: "wai.quantum.mitigate", reason: QUANTUM_RECORD_LABEL }, UnregisteredLabel { label: "wai.quantum.decode", reason: QUANTUM_RECORD_LABEL }, @@ -1025,6 +1037,83 @@ pub const UNREGISTERED_LABELS: &[UnregisteredLabel] = &[ UnregisteredLabel { label: "wai.quantum.rearrange", reason: QUANTUM_RECORD_LABEL }, UnregisteredLabel { label: "wai.quantum.qbom", reason: QUANTUM_RECORD_LABEL }, UnregisteredLabel { label: "wai.quantum.fabric", reason: QUANTUM_RECORD_LABEL }, + // The modules of wai-quantum, each named in its module's documentation. + label("wai.quantum.toolchain", "a module label: wai-quantum's `quantum_toolchain`, the toolchain's compute core (its backends, the algorithm library, OpenQASM 3 in and out)"), + label("wai.quantum.sv", "a module label: wai-quantum's `quantum_sv`, the dense state vector, any gate at any angle"), + label("wai.quantum.sv.metal", "a module label: wai-quantum's `quantum_sv_metal`, the dense state vector on the platform's GPU, in single precision"), + label("wai.quantum.stabilizer", "a module label: wai-quantum's `quantum_stabilizer`, the stabilizer (CHP) backend"), + label("wai.quantum.tableau", "a module label: wai-quantum's `quantum_tableau`, wide stabilizer simulation"), + label("wai.quantum.stabrank", "a module label: wai-quantum's `quantum_stabrank`, Clifford+T circuits as sums of stabilizer states"), + label("wai.quantum.cutrank.metal", "a module label: wai-quantum's `quantum_cutrank_metal`, the cut-rank table on the platform's GPU, in single precision"), + label("wai.quantum.mps", "a module label: wai-quantum's `quantum_mps`, the matrix product state backend"), + label("wai.quantum.mpsim", "a module label: wai-quantum's `quantum_mpsim`, matrix product state simulation of circuits with any angles"), + label("wai.quantum.tn", "a module label: wai-quantum's `quantum_tn`, tensor-network contraction"), + label("wai.quantum.bptn", "a module label: wai-quantum's `quantum_bptn`, tensor-network states on a device's coupling graph, read through belief-propagation environments"), + label("wai.quantum.pauli", "a module label: wai-quantum's `quantum_pauli`, sparse-Pauli (Heisenberg) propagation of an observable"), + label("wai.quantum.spd", "a module label: wai-quantum's `quantum_spd` and `quantum_spd_receipt`, sparse Pauli dynamics and its signed receipts"), + label("wai.quantum.noisy", "a module label: wai-quantum's `quantum_noisy`, noisy circuits"), + label("wai.quantum.frame", "a module label: wai-quantum's `quantum_frame`, noisy Clifford circuits at error-correction scale"), + label("wai.quantum.gbs", "a module label: wai-quantum's `quantum_gbs`, Gaussian boson sampling, exactly"), + label("wai.quantum.cal.rabi", "a module label: wai-quantum's `quantum_cal`, autonomous qubit calibration"), + label("wai.quantum.cal.spectroscopy", "a module label: wai-quantum's `quantum_control`, noise spectroscopy"), + label("wai.quantum.cal.robust_ff", "a module label: wai-quantum's `quantum_control`, filter-function robust control"), + label("wai.quantum.cal.noise_learn", "a module label: wai-quantum's `quantum_noise`, noise learning (cycle benchmarking, sparse Pauli-Lindblad models)"), + label("wai.quantum.ldpc", "a module label: wai-quantum's `quantum_ldpc`, quantum LDPC memory at circuit level"), + label("wai.quantum.match", "a module label: wai-quantum's `quantum_match`, exact minimum-weight perfect-matching decoding"), + label("wai.quantum.uf", "a module label: wai-quantum's `quantum_uf`, union-find decoding"), + label("wai.quantum.window", "a module label: wai-quantum's `quantum_window`, decoding as the syndrome arrives"), + label("wai.quantum.color", "a module label: wai-quantum's `quantum_color`, colour codes decoded by restriction to matching"), + label("wai.quantum.distance", "a module label: wai-quantum's `quantum_distance`, a code's distance certificates"), + label("wai.quantum.qec_text", "a module label: wai-quantum's `quantum_qec_text`, the error-correction text formats (noisy Clifford circuits, detector error models), read and written back"), + label("wai.quantum.resource", "a module label: wai-quantum's `quantum_resource` and `quantum_resource_receipt`, fault-tolerant resource estimation and its signed estimates"), + label("wai.quantum.arch", "a module label: wai-quantum's `quantum_arch`, architecture-level resource estimation"), + label("wai.quantum.chem", "a module label: wai-quantum's `quantum_chem`, molecules by DMRG"), + label("wai.quantum.dmrg", "a module label: wai-quantum's `quantum_dmrg`, ground states of spin chains by DMRG"), + label("wai.quantum.tdvp", "a module label: wai-quantum's `quantum_tdvp`, time evolution of spin chains by TDVP"), + label("wai.quantum.nqs", "a module label: wai-quantum's `quantum_nqs`, neural quantum states"), + label("wai.quantum.qio", "a module label: wai-quantum's `quantum_qio`, quantum-inspired optimisation"), + label("wai.quantum.phasor", "a module label: wai-quantum's `quantum_phasor` and `quantum_phasor_meter`, the phasor bridge and its energy-accounted receipts"), + label("wai.quantum.kernel", "a module label: wai-quantum's `quantum_kernel`, the quantum kernel deployed as phasor features; also the method a phasor receipt names for it"), + label("wai.quantum.qfhrr", "a module label: wai-quantum's `quantum_qfhrr`, the Born machine on the qFHRR phasor substrate"), + label("wai.quantum.vml", "a module label: wai-quantum's `quantum_vml`, variational quantum machine learning"), + label("wai.quantum.qdata", "a module label: wai-quantum's `quantum_qdata`, learning from quantum data"), + // The names a member of a record carries. + label("wai.quantum.born", "the method a phasor receipt names for the generative Born machine (`quantum_phasor_meter`)"), + label("wai.quantum.estimate", "the member of a routine document's `meta` that holds what wai-quantum's resource estimate came from (`engine::estimate::interchange`)"), + // The kernels and corpora a fabric member's certificate names (wai-quantum's + // `quantum_fabric`, `quantum_spd::device`). + label("wai.quantum.circuit/apply", "a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit's phase table"), + label("wai.quantum.circuit2/apply", "a fabric kernel: one controlled one-qubit gate applied to the fixed-point state vector, with wai.quantum.circuit2's phase table"), + label("wai.quantum.circuit/sample", "a fabric kernel: sampling, in wai.quantum.circuit's gateset"), + label("wai.quantum.circuit2/sample", "a fabric kernel: sampling, in wai.quantum.circuit2's gateset"), + label("wai.quantum.circuit/random-v1", "a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit's gateset"), + label("wai.quantum.circuit2/random-v1", "a fabric corpus: the random circuits a member's lanes are certified on, in wai.quantum.circuit2's gateset"), + label("wai.quantum.circuit/fabric-v1", "a fabric corpus: the random circuits, then wide circuits of 11 to 17 qubits from the same stream, that every member is certified on, in wai.quantum.circuit's gateset"), + label("wai.quantum.circuit2/fabric-v1", "a fabric corpus: the same circuits as wai.quantum.circuit/fabric-v1, in wai.quantum.circuit2's gateset"), + label("wai.quantum.sv/run", "a fabric kernel: a gate list run on a dense f64 state, the kernel a statevector job's placement runs"), + label("wai.quantum.sv/run-wide", "a fabric kernel: the same run with gates on four to six qubits at once, certified on a corpus of its own"), + label("wai.quantum.spd/propagate", "a fabric kernel: an observable propagated through a rotation circuit and truncated, the kernel a pauli job's placement runs"), + // The revision a circuit contract names in its `ext` member (quantum-sim §2.1). + label("wai.quantum.circuit/1", "a contract revision: the `ext` of a wai.quantum.circuit payload's contract (quantum-sim §2.1), a part of the capability's definition"), + label("wai.quantum.circuit2/1", "a contract revision: the `ext` of a wai.quantum.circuit2 payload's contract (quantum-sim §2.1), a part of the capability's definition"), + // Documents the quantum crates write that have no schema file. + label("wai.quantum.job-record/1", "a document with no schema file: the record a job service's store keeps a job in (wai-quantum-service)"), + label("wai.quantum.provider-job/1", "a document with no schema file: the record wai-quantum-qpu keeps of a job on a person's provider, written before the job is sent"), + label("wai.quantum.optimize-checkpoint/1", "a document with no schema file: an optimisation's checkpoint (wai-quantum's `engine::variational`)"), + label("wai.quantum.qec_text.vectors/1", "a document with no schema file: the corpus of the error-correction text formats (quantum-conformance/qec-text)"), + label("wai.quantum.docs-manifest/1", "a document with no schema file: the list of documents tools/quantum-docs checks"), + // The domains a digest starts with. + label("wai.quantum.job-key/1", "a digest domain: the digest a job service keeps a client's idempotency key under, the client's name beside the key (wai-quantum-service)"), + label("wai.quantum.trace/1", "a digest domain: an optimisation trace's first link is BLAKE3 of it and the request's canonical text (wai-quantum's `engine::variational`)"), + // Strings a reader refuses, which the tests and the corpora give it to see the refusal. + label("wai.quantum.circuit3", "refused on purpose: not a capability; the circuit core's test gives it to see no gateset read from it"), + label("wai.quantum.other", "refused on purpose: not a kernel; the fabric's test puts it in a certificate to see the placement refuse that certificate"), + label("wai.quantum.x/one", "refused on purpose: not a schema's name, its major not a number; the schema module's test gives it to see no file named for it"), + label("wai.quantum.job-result/2", "refused on purpose: a major of the job result's schema that no text defines; a test writes it into a sealed result to see the receipt fail"), + label("wai.quantum.target/2", "refused on purpose: a major of the device target's schema that no text defines; the targets' test gives it to see the document refused"), + label("wai.quantum.provider/2", "refused on purpose: a version of the provider protocol that no text defines; the reference provider's test sends it to see it answered unsupported_version (quantum-providers §10)"), + label("wai.quantum.provider/9", "refused on purpose: a version of the provider protocol that no text defines; the protocol schema's test sends it to see it answered unsupported_version (quantum-providers §10)"), + label("wai.quantum.provider/999", "refused on purpose: a version of the provider protocol that no text defines; the provider conformance corpus sends it to see it answered unsupported_version (quantum-providers §10)"), ]; /// One registered string with every property the registry gives it. @@ -1848,6 +1937,11 @@ mod tests { for l in UNREGISTERED_LABELS { assert_eq!(capability_kind(l.label), None, "{}", l.label); } + let mut labels: Vec<&str> = UNREGISTERED_LABELS.iter().map(|l| l.label).collect(); + labels.sort_unstable(); + for w in labels.windows(2) { + assert_ne!(w[0], w[1], "the label {} is listed twice", w[0]); + } for r in registrations() { assert!(r.registered.len() == 10 && r.registered.as_bytes()[4] == b'-', "{}", r.capability); assert!(r.registered >= "2026-06-12", "{}: before the specification entered the repository", r.capability); @@ -2268,15 +2362,17 @@ mod tests { } } - /// The record and label strings copied from wai-quantum equal its constants. + /// The record and receipt-kind label strings copied from wai-quantum equal its + /// constants. #[cfg(feature = "quantum_ops")] #[test] fn quantum_strings_equal_the_wai_quantum_constants() { use wai_quantum::quantum_ops as q; assert_eq!(CAP_QUANTUM_CALIBRATION, q::CAP_QUANTUM_CALIBRATION); assert_eq!(CAP_QUANTUM_JOB, q::CAP_QUANTUM_JOB); - let labels: Vec<&str> = UNREGISTERED_LABELS.iter().map(|l| l.label).collect(); - assert_eq!(labels, [q::CAP_QUANTUM_MITIGATE, q::CAP_QUANTUM_DECODE, q::CAP_QUANTUM_COMPILE, - q::CAP_QUANTUM_REARRANGE, q::CAP_QUANTUM_QBOM, q::CAP_QUANTUM_FABRIC]); + let receipt_kinds: Vec<&str> = + UNREGISTERED_LABELS.iter().filter(|l| l.reason == QUANTUM_RECORD_LABEL).map(|l| l.label).collect(); + assert_eq!(receipt_kinds, [q::CAP_QUANTUM_MITIGATE, q::CAP_QUANTUM_DECODE, q::CAP_QUANTUM_COMPILE, + q::CAP_QUANTUM_REARRANGE, q::CAP_QUANTUM_QBOM, q::CAP_QUANTUM_FABRIC]); } } diff --git a/wai/wai-rs/tests/fixtures/dev-stack/fake-stack.py b/wai/wai-rs/tests/fixtures/dev-stack/fake-stack.py index cce944f03..f8c7a71e4 100755 --- a/wai/wai-rs/tests/fixtures/dev-stack/fake-stack.py +++ b/wai/wai-rs/tests/fixtures/dev-stack/fake-stack.py @@ -15,6 +15,7 @@ import json import os import re import socket +import socketserver import sys import threading import time @@ -55,6 +56,14 @@ class Room(http.server.BaseHTTPRequestHandler): pass +class Server(http.server.ThreadingHTTPServer): + """HTTPServer looks up a name for its address before it listens, and nothing here reads the + name. On some hosts that lookup takes 35 s, past what `wai dev` waits for a service.""" + + def server_bind(self): + socketserver.TCPServer.server_bind(self) + + def main(argv): if argv[:1] in (["keygen"], ["relay-lines"]): open(argv[1], "a").close() @@ -73,7 +82,7 @@ def main(argv): while True: c, _ = s.accept() c.close() - http.server.ThreadingHTTPServer(listen_addr(config, "listen"), Room).serve_forever() + Server(listen_addr(config, "listen"), Room).serve_forever() return 0