wai-quantum: methods, passes, noise channels and formats behind traits, every built-in registered through them, a host's own components checked and marked #560

Merged
dcharlot merged 4 commits from wai/quantum-registration into main 2026-11-01 03:37:29 -05:00
Owner

The engine's simulation methods, compiler passes, noise channels and file formats now sit behind four traits, and every built-in registers through them. A host program can register its own components in-process, and the engine checks what each gives before it reaches a result. A result a registered component took part in names it, marked uncertified, and the receipt seals that. A result of built-ins alone gives the bytes it gave before.

What it adds

Four traits and one registry (engine::registry)

  • Method: its name, version, accuracy classes, descriptor, models_noise, auto_rank, takes(channel), plan (admits the job or refuses it, and states its memory and work) and run.
  • Pass: the gates it takes and gives (GateSet) and how it is checked: Check::Ladder or Check::Fidelity { max_distance }, never a hash.
  • Channel: parameters with ranges, arity, Kraus operators, an optional Pauli form, and taken_by(method).
  • FrontEnd: read to OpenQASM 3, and write.
  • Registry::with_builtins() and register(Component::…) are explicit and stay in the process. Registry::builtins() is the shared static.
  • The planner, the run, the compile, the conversions and the verdict go through it. catalog::plan, read, describe and noise_of, run::run, run_with_provenance, compile::compile and call, formats::read, convert, convert_json and expand, and the verdict's functions keep their signatures as thin wrappers.
  • Every built-in registers through the same trait a host's own implements: the twelve methods and the pulse simulator, the eight passes, the five channels, and OpenQASM, QIR and jeff. The order is fixed by registration, and auto's ranks give the order it had.
  • engine::registry re-exports serde_json's Value and json, so a component needs no other dependency.

What a registered component can do

  • A pass runs in a compile when the request names it in compile.passes, after the level's passes and before twirling and dynamical decoupling.
  • A channel can be named in a job's noise, as a value or as {param: v}. The density matrix applies it through its Kraus operators.
  • A front end reads a job's source.

What the engine checks

  • A method's result carries a class it declared, and leaves the members the engine writes untouched.
  • A pass's output is held to its input on the whole circuit, by the equivalence ladder (equality on random inputs alone is rejected) or by its dense distance within its bound and the remaining ε.
  • A channel is completely positive and trace preserving at each job's values, and its Pauli form equals its Kraus channel.
  • A front end's output reads as OpenQASM 3.

Identity

  • Each component has a name, a version, and the BLAKE3 digest of its canonical descriptor.
  • A result a registered component took part in carries components (front end, passes, channels, method). Registered entries are marked "origin": "registered", "certified": false, and the receipt seals them. Forging or dropping them breaks verify.
  • Compile answers (and the pass record's component) and conversions carry it too.
  • A result of built-ins alone carries no components, and its bytes are what they were: the eight pinned job digests hold through the built-in registry and through one holding host components. Registry::components_of derives the list for any result.

Refusal codes, in docs/job-refusals.md:

  • J060: an unknown pass named in a request.
  • J061: a channel the method cannot take. This now covers noise on a method that models none, which was J011, and amplitude damping on the stabilizer method. J011's meaning is narrowed to match.
  • J062: a channel that fails the validity check.
  • J063: a registration refused.
  • J064: a registered component breaking the contract.
  • J065: an intent on a job with a registered channel.

Two small behaviour changes, in the changelog: an unknown method is always J010, and a channel value that is not a number is refused with J003 where it used to be read as no noise.

Surfaces

  • CLI: wai-quantum components, with --json adding each descriptor. Its summary is translated in locales/zh-CN.json.
  • Both MCP servers: list_components, its answer tools.v1.json#/$defs/components.
  • Service: the built-ins only, nothing loaded from a request. GET /v1 and quantum_service_info list components.
  • Example: examples/extension_points.rs ([[example]] test = true): a method basis_table, a pass cancel_pairs, a channel bit_flip and a front end gate_list, written against public items only, run end to end, with 3 tests.
  • Docs: the new page docs/extension-points.md, with a runnable Rust block that registers a channel and runs it; sections in the engine README (and zh-CN), the CLI README (and zh-CN) and the service README; the changelog.
  • Schemas: job-result, compile-result, tools.v1.json (components, component) and the service's info gain optional members. schema::FILES is unchanged.
  • CI: wai-quantum-registry.yml, a native job on linux and linux-arm64 (the registry tests under full and contract features, 12 required by name; the engine's job, refusal, compile and formats tests; the example tested and run) and a wasip2 job under wasmtime.

Checked

Where Result
Linux build host Engine contract set (--no-default-features --features quantum_engine,quantum_receipt,quantum_qec,quantum_noise --lib): 818 passed. Engine --features full --lib: 1174 passed. engine::registry::: 12 passed under full, 12 under the contract set, and 12 under wasm32-wasip2 with wasmtime 49.0.2. The 8 pinned job digests unchanged. Integration tests under full: formats_conformance 2, formats_mutation 1, intent_conformance 2, answer_conformance 2, qasm3_conformance 2. The example: 3 passed, and its run printed the three lines the workflow looks for. CLI: every target passed (72 in the main suite); clippy -D warnings with and without default features; smoke, every check held. Service: 37 + 1; clippy; smoke against a local instance, every check held. wai-web native quantum_engine::: 29 passed; wasm32 under Node: 21 passed; both pins unchanged. Breaking gate: only additions, no unacknowledged break. Repository checks: every line ok. check_docs.py --rust over the 7 touched pages: passed. check_schemas.py: 33 schema files, 51 local and 30 service tools, 48 tool answers including list_components.
After rebasing onto the GPU PR at its head, the board measured again (Linux build host) The views page rebuilt with wai/wai-quantum-views/build.sh in catthehacker/ubuntu:act-22.04 with Rust 1.98.0: the same bytes as the committed page, and build-views --check passed. Engine --features full --lib --tests: 1174 lib tests passed (engine::registry 12, engine::fabric 6, engine::fabric_measured 4) and every test binary. Engine contract set: 818 passed, the registry's 12 among them. The example: 3 passed, and its walk-through ran to its end, 4 of its lines naming what was registered. CLI: 72 passed (bin) and every integration target; clippy -D warnings clean with and without default features. Service: 37 + 1. wai-web native: 29 passed. CLI and service smoke: every check held. Breaking gate: no unacknowledged break. Repository checks: all 10 lines ok.
With the scale-out PR's notebook fix under it (Linux build host, in catthehacker/ubuntu:act-22.04) wai-quantum-py/ci/check.sh: 78 passed, 5 of 5 notebooks ran and matched (36 code cells), smoke passed.
With the GPU PR's feature-gate fix (d4cdbb7da) under it (macOS build host) Every cargo check line of the pulse, error-correction and variational workflows, and quantum_lang, quantum_toolchain, quantum_fabric and full --lib --tests: clean under -D warnings. engine::registry: 12 passed under full and 12 under the contract set.
On main b1d7a3532 This PR's commits sit on the GPU PR as merged, with its feature-gate fix (d4cdbb7da), and main's tree is that commit's: nothing else has landed. This PR's CI runs every leg.

Not done

  • Results made by built-ins alone carry no components. Adding it would change every built-in result's bytes, the pinned digests and the stored notebook outputs; such a result is already identified by its method, passes, channels and engine.version, all sealed.
  • The stabilizer and trajectories methods refuse registered channels (J061): taking them would change the public FrameStep and NoiseModel. Intents (J065) and mitigation (J008) on jobs with registered channels are refused, because those checks model the built-in channels.
  • Device-target jobs, sets and sweeps run on the built-in components only.
  • Adapters for other SDKs.

Breaking

None. The breaking gate lists only additions. J011's narrower meaning and the two behaviour changes above are in the changelog.

🤖 Generated with Claude Code

The engine's simulation methods, compiler passes, noise channels and file formats now sit behind four traits, and every built-in registers through them. A host program can register its own components in-process, and the engine checks what each gives before it reaches a result. A result a registered component took part in names it, marked uncertified, and the receipt seals that. A result of built-ins alone gives the bytes it gave before. ## What it adds **Four traits and one registry** (`engine::registry`) - `Method`: its name, version, accuracy classes, descriptor, `models_noise`, `auto_rank`, `takes(channel)`, `plan` (admits the job or refuses it, and states its memory and work) and `run`. - `Pass`: the gates it takes and gives (`GateSet`) and how it is checked: `Check::Ladder` or `Check::Fidelity { max_distance }`, never a hash. - `Channel`: parameters with ranges, arity, Kraus operators, an optional Pauli form, and `taken_by(method)`. - `FrontEnd`: `read` to OpenQASM 3, and `write`. - `Registry::with_builtins()` and `register(Component::…)` are explicit and stay in the process. `Registry::builtins()` is the shared static. - The planner, the run, the compile, the conversions and the verdict go through it. `catalog::plan`, `read`, `describe` and `noise_of`, `run::run`, `run_with_provenance`, `compile::compile` and `call`, `formats::read`, `convert`, `convert_json` and `expand`, and the verdict's functions keep their signatures as thin wrappers. - Every built-in registers through the same trait a host's own implements: the twelve methods and the pulse simulator, the eight passes, the five channels, and OpenQASM, QIR and jeff. The order is fixed by registration, and `auto`'s ranks give the order it had. - `engine::registry` re-exports `serde_json`'s `Value` and `json`, so a component needs no other dependency. **What a registered component can do** - A pass runs in a compile when the request names it in `compile.passes`, after the level's passes and before twirling and dynamical decoupling. - A channel can be named in a job's `noise`, as a value or as `{param: v}`. The density matrix applies it through its Kraus operators. - A front end reads a job's `source`. **What the engine checks** - A method's result carries a class it declared, and leaves the members the engine writes untouched. - A pass's output is held to its input on the whole circuit, by the equivalence ladder (equality on random inputs alone is rejected) or by its dense distance within its bound and the remaining ε. - A channel is completely positive and trace preserving at each job's values, and its Pauli form equals its Kraus channel. - A front end's output reads as OpenQASM 3. **Identity** - Each component has a name, a version, and the BLAKE3 digest of its canonical descriptor. - A result a registered component took part in carries `components` (front end, passes, channels, method). Registered entries are marked `"origin": "registered", "certified": false`, and the receipt seals them. Forging or dropping them breaks `verify`. - Compile answers (and the pass record's `component`) and conversions carry it too. - A result of built-ins alone carries no `components`, and its bytes are what they were: the eight pinned job digests hold through the built-in registry and through one holding host components. `Registry::components_of` derives the list for any result. **Refusal codes**, in `docs/job-refusals.md`: - `J060`: an unknown pass named in a request. - `J061`: a channel the method cannot take. This now covers noise on a method that models none, which was `J011`, and amplitude damping on the stabilizer method. `J011`'s meaning is narrowed to match. - `J062`: a channel that fails the validity check. - `J063`: a registration refused. - `J064`: a registered component breaking the contract. - `J065`: an intent on a job with a registered channel. Two small behaviour changes, in the changelog: an unknown method is always `J010`, and a channel value that is not a number is refused with `J003` where it used to be read as no noise. **Surfaces** - CLI: `wai-quantum components`, with `--json` adding each descriptor. Its summary is translated in `locales/zh-CN.json`. - Both MCP servers: `list_components`, its answer `tools.v1.json#/$defs/components`. - Service: the built-ins only, nothing loaded from a request. `GET /v1` and `quantum_service_info` list `components`. - Example: `examples/extension_points.rs` (`[[example]] test = true`): a method `basis_table`, a pass `cancel_pairs`, a channel `bit_flip` and a front end `gate_list`, written against public items only, run end to end, with 3 tests. - Docs: the new page `docs/extension-points.md`, with a runnable Rust block that registers a channel and runs it; sections in the engine README (and zh-CN), the CLI README (and zh-CN) and the service README; the changelog. - Schemas: `job-result`, `compile-result`, `tools.v1.json` (`components`, `component`) and the service's `info` gain optional members. `schema::FILES` is unchanged. - CI: `wai-quantum-registry.yml`, a native job on linux and linux-arm64 (the registry tests under full and contract features, 12 required by name; the engine's job, refusal, compile and formats tests; the example tested and run) and a wasip2 job under wasmtime. ## Checked | Where | Result | |---|---| | Linux build host | Engine contract set (`--no-default-features --features quantum_engine,quantum_receipt,quantum_qec,quantum_noise --lib`): 818 passed. Engine `--features full --lib`: 1174 passed. `engine::registry::`: 12 passed under full, 12 under the contract set, and 12 under wasm32-wasip2 with wasmtime 49.0.2. The 8 pinned job digests unchanged. Integration tests under full: `formats_conformance` 2, `formats_mutation` 1, `intent_conformance` 2, `answer_conformance` 2, `qasm3_conformance` 2. The example: 3 passed, and its run printed the three lines the workflow looks for. CLI: every target passed (72 in the main suite); clippy `-D warnings` with and without default features; smoke, every check held. Service: 37 + 1; clippy; smoke against a local instance, every check held. wai-web native `quantum_engine::`: 29 passed; wasm32 under Node: 21 passed; both pins unchanged. Breaking gate: only additions, no unacknowledged break. Repository checks: every line ok. `check_docs.py --rust` over the 7 touched pages: passed. `check_schemas.py`: 33 schema files, 51 local and 30 service tools, 48 tool answers including `list_components`. | | After rebasing onto the GPU PR at its head, the board measured again (Linux build host) | The views page rebuilt with `wai/wai-quantum-views/build.sh` in `catthehacker/ubuntu:act-22.04` with Rust 1.98.0: the same bytes as the committed page, and `build-views --check` passed. Engine `--features full --lib --tests`: 1174 lib tests passed (`engine::registry` 12, `engine::fabric` 6, `engine::fabric_measured` 4) and every test binary. Engine contract set: 818 passed, the registry's 12 among them. The example: 3 passed, and its walk-through ran to its end, 4 of its lines naming what was registered. CLI: 72 passed (bin) and every integration target; clippy `-D warnings` clean with and without default features. Service: 37 + 1. wai-web native: 29 passed. CLI and service smoke: every check held. Breaking gate: no unacknowledged break. Repository checks: all 10 lines ok. | | With the scale-out PR's notebook fix under it (Linux build host, in `catthehacker/ubuntu:act-22.04`) | `wai-quantum-py/ci/check.sh`: 78 passed, 5 of 5 notebooks ran and matched (36 code cells), smoke passed. | | With the GPU PR's feature-gate fix (`d4cdbb7da`) under it (macOS build host) | Every `cargo check` line of the pulse, error-correction and variational workflows, and `quantum_lang`, `quantum_toolchain`, `quantum_fabric` and `full --lib --tests`: clean under `-D warnings`. `engine::registry`: 12 passed under full and 12 under the contract set. | | On main `b1d7a3532` | This PR's commits sit on the GPU PR as merged, with its feature-gate fix (`d4cdbb7da`), and main's tree is that commit's: nothing else has landed. This PR's CI runs every leg. | ## Not done - Results made by built-ins alone carry no `components`. Adding it would change every built-in result's bytes, the pinned digests and the stored notebook outputs; such a result is already identified by its method, passes, channels and `engine.version`, all sealed. - The `stabilizer` and `trajectories` methods refuse registered channels (`J061`): taking them would change the public `FrameStep` and `NoiseModel`. Intents (`J065`) and mitigation (`J008`) on jobs with registered channels are refused, because those checks model the built-in channels. - Device-target jobs, sets and sweeps run on the built-in components only. - Adapters for other SDKs. ## Breaking None. The breaking gate lists only additions. `J011`'s narrower meaning and the two behaviour changes above are in the changelog. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Method, Pass, Channel and FrontEnd, and one registry the planner, the run,
the compile, the conversions and the verdict go through. Every built-in
registers through the same trait a host's own implements: the twelve
methods and the pulse simulator, the eight passes, the five channels and
the three formats. Registry::with_builtins() and register(...) are
explicit and stay in the process.

The engine checks what a registered component gives: a method's class and
the members the engine writes, a pass's output against its input on the
whole circuit by the ladder or a distance bound, a channel's Kraus
operators completely positive and trace preserving at each job's values,
a format's program reading. A result a registered component took part in
carries `components`, each identity (name, version, descriptor digest)
marked registered and certified false, sealed by its receipt; a result of
built-ins alone gives the bytes it gave, the eight pinned job digests
holding through any registry. Refusal codes J060 to J065. The example
examples/extension_points.rs, docs/extension-points.md, and the CI leg
wai-quantum-registry.yml.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
`wai-quantum components` (`--json` with each descriptor), the MCP tool
list_components on both servers (its answer tools.v1.json#/$defs/components),
and the service's GET /v1 and quantum_service_info list every method, pass,
noise channel and format with its version, origin and descriptor digest:
the built-ins alone, nothing loaded from a request. The tool lists' tests,
the smoke checks and the second schema checker take the new tool; the agent
docs are blessed from both servers; the command's summary is translated;
the READMEs and the changelog say what the extension points are.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The docs check holds a block that cannot run here to the workflow named:
the example's test and run, with --locked, as wai-quantum-registry.yml
runs them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-quantum engine::refusal: J011 no longer names noise, which J061 now covers
All checks were successful
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 9s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 4m42s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (pull_request) Successful in 1m30s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m14s
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m24s
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (pull_request) Successful in 1m53s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 16m34s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 1m1s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m6s
wai-quantum views in agent hosts / views · the page and its engine (pull_request) Successful in 3m26s
wai-quantum views in agent hosts / views · a scripted host (pull_request) Successful in 3m19s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m38s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 23m1s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m19s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 24m41s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m41s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 16m28s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 11s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 31s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m5s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 12m16s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 1m3s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 29s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 19m31s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 1m43s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 24s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 2m14s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 3m26s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 3m35s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h17m52s
4f901247c7
Noise a method cannot take is refused with J061 since the registry, so J011's meaning stops listing
it and points there; the docs page's table, which a test holds to the code's, says the same.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!560
No description provided.