### wai-quantum: Python and notebooks, in-process

WAI Quantum from Python and notebooks, with the same answers and receipts as every other surface: the shared job engine in the process, a client for the job service, and notebook widgets.

- **`wai/wai-quantum-py`** (Python module `wai_quantum`): a pyo3 extension module over the shared job engine, built by maturin into one abi3 wheel per platform, Python 3.9 on.
  - The engine's functions: `run`, `plan`, `lint`, `draw` (text and SVG), `layout`, `critique`, `improve`, `shortcuts`, `equivalent`, `verify`, `seal`, `canonical`, `digest`, `methods`, `accuracy_classes` and `history`, and `bloch`: each qubit's reduced state from the engine's expectation values of X, Y and Z.
  - Answers are plain dicts and lists. A job is the service's form, with helpers: `counts`, `probabilities()` (the sampled frequencies), `expectations`, `amplitudes`, `method`, `accuracy` and `receipt`.
  - Values cross one to one with JSON's: NaN, infinities, integers past 64 bits and keys that are not strings are refused, never guessed at.
  - A refusal raises `EngineError` with the engine's message and the line it names; its `code` is the reader's stable diagnostic code (`Q103`) when the refusal is the reader's.
- **Keys:** a result is sealed with the key the caller passes (`Key`), by default this user's key, which the command line also signs with. The demo key and the key files are the command line's, so the same key signs on both.
- **`Service`:** a client in the standard library alone for the job service (`submit`, `status`, `result`, `cancel`, `run`). It names itself `wai-quantum-python/<version>` in each request, and checks each receipt in the process, offline.
- **Widgets** (the `widgets` extra): `Circuit`, `Result`, `Receipt` and `Bloch`, each a plain ES module. Each draws the engine's answer and computes nothing of its own, and each has a static HTML fallback (`Circuit` also SVG) for a notebook without the widget extension.
- **`engine::svg`:** a program's circuit as a standalone SVG drawing, with the Studio's geometry and classes, the same bytes on every platform. Each gate can be marked with whose hand it is in.
- **Docs as code:** five notebooks (getting started, a Bell pair and its receipt, equivalence, a noisy run, a job on a local service), run in CI and held to their stored outputs.
- **Tests:** 62 pytest tests hold the package to the other surfaces:
  - a job run in Python equals the command line's and the service's, except for each host's time and its word on energy;
  - the plans, lints, critiques, drawings, method catalogue, equivalence verdicts and improvements are the command line's;
  - receipts verify both ways, and the digest recomputed from Python's canonical bytes is the command line's;
  - the 3,000-odd ECMAScript number vectors reach the engine bit for bit;
  - the widgets' front ends run under node on the payloads the package builds.
- **CI:**
  - `wai-quantum-py.yml` runs `ci/check.sh` on `linux` and `macos`: the wheel, pytest with every test required, the notebooks, and a smoke check on Python 3.9 with the wheel alone.
  - `wai-quantum-py-release.yml` builds the wheels on a `wai-quantum-cli-v*` tag: macOS arm64 and x86_64, Linux x86_64 and arm64 (manylinux2014, linked with zig) and Windows x86_64. It attaches them to the forge release with their SHA-256 and publishes nothing to a package index.

