# EXAMPLE: a NoETL harness for verifiable quantum circuit search `playbook.yaml` sketches how a team entering the Google Quantum AI [Verifiable Quantum Circuit Compilation](https://www.kaggle.com/competitions/google-verifiable-quantum-circuit-compilation) competition could run an AI-assisted circuit search under NoETL. **NoETL does not compile, optimise, or verify circuits.** The open-source kickmix library builds the circuits, and the competition's standalone verifiers check them. NoETL runs those programs, retries them when they crash, records what each one was given and what it returned, and decides what runs next. This is an example, not a tested entry. It has not been run against the competition, and it never uploads anything to Kaggle. ## Steps | Step | Tool kinds | What it does | | --- | --- | --- | | `start` | postgres | Creates `vqcc_candidate` and `vqcc_bundle` and sets `ctx.round = 1`. | | `propose_candidates` | http, python | Asks a model for generator settings as JSON, then keeps only settings that name a declared generator and stay inside its ranges, capped at `candidates_per_round`. | | `build_and_verify` | python, postgres | Parallel loop over the candidates (`max_in_flight: 8`). Each iteration runs the team's generator, hashes what it wrote, runs the verifier wrapper, and inserts one row. A crash is retried. A circuit that fails verification is recorded and not retried. | | `score_round` | postgres, python | Reads the cheapest verified candidate per benchmark across all rounds and computes a local proxy score. | | `package_submission` | python | Builds the submission layout (`invsqrt.kmb`/`.kmx`, `dqi.kmb`/`.kmx`, `dfthcsos/angle_k_0..n-1`, `dfthcsos/submission.npz`). It checks that the angle files are numbered with no gaps and that the npz holds the required arrays, then zips and hashes the bundle. | | `leaderboard_gate` | python, postgres | Compares the bundle's proxy score with the last submitted one. A better bundle is recorded as `ready_for_review`; otherwise the search runs another round while rounds remain. | | `finish` | python | Summarises the run. A person reviews the bundle and uploads it. | ## What you supply - `kickmix_python`: an interpreter with kickmix installed, available on every worker in the pool that runs this playbook. - `artifact_root`: a path every one of those workers mounts, such as a ReadWriteMany volume or an object-store mount. Generators write there, and the packaging step reads from there. - One generator script per benchmark. Each takes `--out DIR` plus the knobs listed under `workload.generators` and writes its circuit files into `DIR`. - `verify_and_report.py`: a thin wrapper around the official verifier that prints one JSON line, `{"passed", "qubits", "gate_cost", "cost"}`. - Credential aliases `pg_auth` and `gcp_auth`, and a Secret Manager path for the model API key. The playbook names the secrets by reference, because the server refuses a playbook that contains secret material inline. ## Schema notes The playbook uses only fields the NoETL source defines: - Step, loop, `next.spec` and `next.arcs`, and keychain fields: [`orchestrate-core/src/playbook.rs`](https://github.com/noetl/server/blob/cdb1e25704d5373821fc18c242ffd6dbe2fab4b0/orchestrate-core/src/playbook.rs) in noetl/server. - `spec.policy.rules` with `do: retry | jump | continue | fail`, `attempts`, `backoff`, `delay`, `set`, and `_attempt`: [`src/tools/task_sequence.rs`](https://github.com/noetl/tools/blob/89302ccf1d611ecdce64984940e4729a6b5b8691/src/tools/task_sequence.rs#L816) in noetl/tools. - Python `python:` and `timeout_seconds`: [`src/tools/python.rs`](https://github.com/noetl/tools/blob/89302ccf1d611ecdce64984940e4729a6b5b8691/src/tools/python.rs#L192). - The model call is an `http` task. `agent` and `mcp` are not tool kinds the server accepts: registration rejects them ([`validate_tool_kinds`](https://github.com/noetl/server/blob/cdb1e25704d5373821fc18c242ffd6dbe2fab4b0/src/services/catalog.rs#L571)). The file was checked by deserialising it into `orchestrate-core`'s `Playbook` type and applying the same checks as `src/playbook/parser.rs`: a `start` step, unique step names, known `next` targets, valid policy actions, and known tool kinds. Every template also compiles in minijinja. That check confirms the shape. It does not show that the playbook runs end to end. ## Delivery Delivery is at-least-once. Every insert uses `ON CONFLICT ... DO NOTHING` on a key that includes the candidate or round, so a redelivered iteration does not add a second row. Generators write to a per-candidate directory, and the packaging step starts from a clean directory, so a retry overwrites rather than accumulates.