CI/CD quality gates for quantum circuits. Statistically validate probabilistic output, across simulators and real QPUs, defined entirely as code.
| Assertion | Result | Detail |
|---|---|---|
| chi_square p ≥ 0.01 | PASS | χ²=0.41 dof=1 p=0.52 |
| distribution_tvd ≤ 0.03 | PASS | distance 0.0043 |
| hellinger_fidelity ≥ 0.99 | PASS | fidelity 1.0000 |
| allowed_states ⊆ {00,11} | PASS | leakage 0.0000 |
| state_probability 00 | PASS | 0.4957 ∈ [0.45, 0.55] |
apiVersion: shotgate.dev/v1alpha1 kind: QuantumWorkflow metadata: name: bell-state defaults: backend: { provider: local-aer, shots: 8192 } jobs: - name: bell-pair circuit: { format: qasm2, path: bell.qasm } assertions: - type: chi_square # χ² goodness-of-fit expected: { "00": 0.5, "11": 0.5 } significance: 0.01 - type: allowed_states # |01⟩,|10⟩ forbidden states: ["00", "11"] max_leakage: 0.0
Circuits, shots, and statistical assertions live in a QuantumWorkflow file, versioned next to your code.
podman pull and go: pinned dependencies, no host Python, identical locally and in CI.
Verdicts map to exit codes; a failed assertion fails the build. JUnit XML output drops into any CI dashboard.
Quantum output is probabilistic; exact-match testing is meaningless. Each oracle bounds a distribution property, or the circuit's own structure, instead.
Total variation distance between observed and expected counts, bounded above. Interpretable, shot-count agnostic.
Classical fidelity, bounded below. Deprecation candidate (ADR-0018): the number moves onto distribution_tvd's result.
Pearson goodness-of-fit, gated on a p-value. Simulator-only: fails closed on real hardware.
Kullback-Leibler divergence from expected, bounded above (bits). Auto readout-aware on a QPU.
Marginal probability of one outcome, held inside a window. The simplest hardware-friendly gate.
The modal measured outcome must be a given state, optionally above a probability. For single-answer algorithms.
Shannon entropy of the measured distribution, held inside a min/max window (bits).
Pauli-Z product expectation ⟨Z..Z⟩ in [-1, 1], via a window or a target. A Bell pair gives +1.
Probability mass observed outside the allowed support set; catches states that should never appear.
Bound the authored circuit's depth in a min/max window. Static and output-independent.
Require the circuit to use only an allowed set of gate names. Static, runs every commit.
Total variation distance against another job's counts, not a declared expected. Gates a circuit with no closed-form answer.
v0.2 gates passed on a real QPU: Bell, GHZ, and Grover on ibm_fez at 4096 shots, 2026-06-11. The measured baseline lives in hardware-validation.
jobs: validate-circuits: runs-on: ubuntu-latest container: ghcr.io/coldqubit/shotgate:latest steps: - uses: actions/checkout@v4 - run: shotgate run workflow.yaml --junit report.xml
All assertions passed. The pipeline proceeds.
A statistical gate failed. The build stops here.
Bad configuration or runtime error, fix the workflow, not the circuit.