### wai-quantum: a durable job service with sets, sweeps and dry runs, run yourself

The job service keeps what it answered across its restarts, runs many programs as one job, says what a job would take before it runs, and can be run on your own premises from an image (`wai-quantum-service/docs/self-host.md`). The free hosted service still takes no account and no key.

- **A durable store** (`wai-quantum-service/src/store.rs`): programs, requests, results and receipts kept under the BLAKE3 digests of their bytes, behind a `Store` trait, with a files store (each file written whole, synced and renamed, under a lock) and a memory one. Every job is in the store before its submission is answered, and at each change of its status. On start the service reloads it: finished jobs served as they were, their receipts verifying; a job that was running comes back `interrupted`, with the reason; queued ones queued again. Retention stays configurable (`WAI_QSVC_RETAIN_SECS`, a day by default). A record names its client by a keyed hash, never its address. A worker whose service has gone stops itself. A test kills the service mid-job and restarts it (`tests/restart.rs`).
- **Sets and sweeps** (`engine::sets`): `"programs"`, a list of programs or jobs, or `"sweep"`, values for the program's integer, float and angle inputs (every combination; the reader binds a real-valued input with `qasm::bind`). At most 100 items, each a plain job with its own result and receipt; the set's receipt seals its head, which holds the Merkle root of every item's leaf under the crate's Merkle domains, and each item carries its path. `POST /v1/verify` and `wai-quantum verify` check a set whole. `J007` is a set that does not read.
- **Dry runs**: `"dry_run": true` returns the method, memory, estimated time and energy (each with its basis: this service's own timings and readings, or the planner's nominal rate, `catalog::nominal_rate`), the bounds that apply, where the client stands, and whether the service would take the job now, or the refusal it would give. It runs nothing.
- **Status and limits**: `GET /v1/jobs/{id}/events` (server-sent events to the job's end) and `?wait=S` on the poll; every answer carries `RateLimit-Policy` and `RateLimit`, and a refusal past the limits `Retry-After`.
- **Receipt keys**: the key set at `/.well-known/wai-quantum-receipt-keys`, each key with its validity window; `wai-quantum-service rotate-key` retires a key with a transition statement both keys sign, and the old key stays published.
- **Energy on Linux** (`engine::energy::Packages`): the processor packages' counters, opened only when every package zone reads and is live, the figure the packages' energy over the job's window with no attribution to the job and the jobs beside it named, its uncertainty covering the two reads and the update edges measured at start; otherwise `unmetered` with the reason (no interface, no privilege, not live), never zero.
- **Provenance** (`engine::run::run_with_provenance`, `wai-quantum-service/docs/provenance.md`): each new result carries the program's digest, the method, each pass its compile ran with its check's verdict and the certificate's digest, the shots, seed and plan, and the engine's and host's versions, mapped to the categories provenance surveys use. Results without it verify as they did, and the engine's own results are unchanged.
- **Self-hosting**: an OCI image (`wai-quantum-service/deploy/Containerfile`: two stages, each base pinned by digest, a locked build with paths remapped and the timestamp fixed, an unprivileged user) and `deploy/check-image.sh`, which builds it, runs it, holds it to the smoke checks and removes it, pushing nothing. Optional API keys for a private deployment (`WAI_QSVC_API_KEYS`, off by default; `J033`), counted by key, stored as digests.
- **A scheduler's resource**: `wai-quantum task` (target, acquire, start, status, wait, result, stop, release), the interface a batch scheduler's prologue, job and epilogue call (`wai-quantum-service/docs/scheduler.md`).
- **Surfaces**: the service's MCP tools `run_quantum_set` and `dry_run_quantum_job`; the command line's `--program` and `--sweep` on `run`, `plan` and `submit`, and `submit --dry-run`, `--detach` and `--api-key`, `submit` following the job's status; the OpenAPI document, both smoke tests, the READMEs and the generated agent docs.
- **Schemas** (the version contract): a set's result (`wai.quantum.set/1`, the head named as the engine's, inside what its receipt seals), a result's provenance (`wai.quantum.provenance/1`; its compilation names the gate set compiled to as `basis`), the service's receipt key set (`wai.quantum.receipt-keys/1`, with its signed transitions) and the command line's scheduler lease (`wai.quantum.lease/1`). The job request names `programs`, `sweep` and `dry_run`, a job's result may be a set's, an energy figure may be the processor packages', and a job names its store digests. `run_quantum_set` and `dry_run_quantum_job` answer to their output schemas, each with its verdict, refused or not, and a run asked as a dry run answers as one. The service keeps its store in `~/.local/share/wai-quantum-service/store` unless `WAI_QSVC_STORE` names another (or `memory`); every CI leg and test that starts it names one in its own scratch.

