### wai-quantum: extension points, registration traits for methods, passes, noise channels and formats

- **`engine::registry`**: four traits a component implements, and one registry the engine goes through. `Method`
  (its name, version, accuracy classes and descriptor, whether it models noise, where `auto` tries it, its `plan`
  that admits a job or refuses it and estimates its memory and work, and its `run`); `Pass` (the gates it takes and
  gives, and its check: `Check::Ladder`, the equivalence ladder, or `Check::Fidelity`, a distance bound on dense
  unitaries; never a hash); `Channel` (its parameters and ranges, its arity, its Kraus operators and its Pauli form
  where it is one, and how each noisy method takes it); `FrontEnd` (a format read to OpenQASM 3 and written from the
  engine's program). `Registry::with_builtins()` holds every built-in, each registered through the same trait: the
  twelve methods and the pulse simulator, the eight compile passes, the five noise channels and the three formats.
  `register(Component::…)` adds a host's own in its process; nothing is loaded from a file, a path or a request.
- **The engine through the registry.** `catalog::plan`, `catalog::read`, `run::run`, `compile::compile`,
  `compile::call`, `formats::convert`, `formats::convert_json`, `formats::expand` and `verdict::of_run` keep their
  signatures and run through the built-in registry; `Registry::plan`, `run`, `plan_and_run`, `job`, `compile`,
  `compile_call`, `convert_json` and `expand` run through a host's. `auto` tries methods by rank (the built-ins at
  10, 20, 30, … in the order they always had), and the methods list is each method's own entry. A compile takes
  `passes`, the names of passes to run after its level's and before twirling and decoupling; a job's `noise` takes
  a registered channel by its value or its parameters (`{"name": {"p": …}}`), which the density matrix applies as
  its Kraus operators after each gate.
- **The engine checks what a registered component gives.** A method's result must carry an accuracy class it
  declared and leave the members the engine writes as they were; a pass's output is held to its input on the whole
  circuit by the check it declares, within its bound and what is left of the ε budget, or left out (`rejected`) and
  the program goes on as it was; a channel's Kraus operators are checked completely positive and trace preserving at
  every job's values (`registry::validate`), and its Pauli form a distribution that is its operators' channel; a
  format's program must read. The built-in channels and passes are held by tests to what they declare.
- **Identity.** A component's identity is its kind, name, version and the BLAKE3 digest of its descriptor
  (`registry::digest_of`). A result made by built-ins alone is the result it always was: the eight pinned job
  digests hold through the built-in registry and through one that holds a host's components beside them. A result
  a registered component took part in carries `components`, every component that made it (its format, its
  compile's passes, its noise's channels, its method), each registered one marked `"origin": "registered"` and
  `"certified": false`, sealed by its receipt; so does a compile's answer (and its pass's record, `component`) and a
  conversion's. A name a built-in holds is never registered. `components` is in `wai.quantum.job-result/1`,
  `wai.quantum.compile-result/1` and the conversion's answer (optional), and `wai.quantum.tools/1` gains the
  listing's `components` and `component`.
- **Refusal codes, a decade of their own:** `J060` a pass a request names that this host does not hold, `J061` a
  noise channel the method cannot take (a method that models no noise, which was `J011`, and amplitude damping on
  the stabilizer's frames among them), `J062` a channel whose operators fail the validity check, `J063` a
  registration the registry does not take, `J064` a registered component's answer that breaks the contract, `J065`
  an intent on a job whose noise names a registered channel. A method a job names that does not exist is `J010`
  whatever else the job asks, and a channel's value that is not a number or an object of its parameters is refused
  (`J003`), where it was read as no noise.
- **Surfaces:** `wai-quantum components` (with `--json`, each one's descriptor); the MCP tool `list_components`
  on both servers; the job service lists its components in `GET /v1` and `quantum_service_info`, the built-ins
  alone.
- **The example** `examples/extension_points.rs`: a method (`basis_table`, for circuits that permute basis states),
  a pass (`cancel_pairs`), a channel (`bit_flip`) and a format (`gate_list`), written against the public traits
  alone, registered and run end to end, with its tests; `docs/extension-points.md` says how to write one, with a
  channel registered and run. CI: `wai-quantum-registry.yml`, on both Linux architectures and under
  wasm32-wasip2.
- `engine::fabric_measured`'s test of the measured circuit's job runs where the fabric is built (`quantum_fabric`),
  so the contract workflow's feature set passes every test it builds.

