Protocol changelog
The kernel WebSocket protocol is at v2 (unreleased; v1 clients must add the authenticate handshake). v1 shipped since the protocol stabilized; the protocol is documented in the Kernel API section.
Evolution policy
Section titled “Evolution policy”- Additive changes — new message types, new optional request fields, new fields on responses — can land in any release without notice. Clients must ignore unknown fields and unknown response types.
- Breaking changes — removing or renaming fields, changing semantics of existing messages — ship only with a protocol version bump and an entry in this table.
- Every protocol-relevant change is also announced in the repo CHANGELOG.
History
Section titled “History”| App version | Protocol change |
|---|---|
| Unreleased | Additive: runtime files are multi-kernel safe. Besides kernel.json (now the “most recent kernel” pointer, last writer wins), each kernel writes kernel-<port>.json with the same {url, port, pid, token} payload, 0600 in a 0700 directory, written atomically and removed on clean shutdown (SIGTERM/SIGINT); if the exiting kernel owned the pointer it is re-pointed at the newest live kernel. Clients that know the port should read kernel-<port>.json; kernel.json keeps working unchanged for single-kernel setups. Also: qec_explain’s nondeterministic payload gains cause, sensitivities, target_count and targets_omitted (all flagged detectors are listed, bounded at 20). See Authentication and QEC messages. |
| Unreleased | Additive: new message qec_explain → qec_explain_result — static analysis of a Stim circuit’s text: why a detector or observable is non-deterministic (indices, anticommuting operation, tick, qubits, source and declaration lines, Stim’s detector-slice SVG) and a minimum-weight undetected logical error with each fault located. Failures arrive as an error with phase: "qec_explain" (missing_dependency when Stim is absent). Replies echo an optional request_id. See QEC messages. |
| 0.14.1 | Protocol v2, breaking (plus the additive server proof below): every connection must authenticate. The first frame must be {"type": "authenticate", "token": "<token>"} (answered by {"type": "authenticated"}); otherwise the kernel closes the connection (4401 authentication failed/required, 4403 forbidden Origin/Host; foreign Origin/Host handshakes are refused with HTTP 403). The kernel refuses to start without NUCLEI_KERNEL_TOKEN unless NUCLEI_KERNEL_INSECURE_DEV=1. Migration for external clients: read the token from ~/.nuclei/runtime/kernel.json (or $NUCLEI_KERNEL_TOKEN) and send the authenticate frame first. Mutual authentication (additive): the authenticate frame may carry a client nonce (32 random bytes, hex); when it does, the authenticated ack carries proof = hex HMAC-SHA256 keyed by the token over the nonce string, and the app’s own client requires it (so a program squatting the port, or an old unauthenticated kernel, cannot pass as the kernel). Frames without a nonce are still accepted and acknowledged without a proof; a malformed nonce is refused with 4401. See Server proof and Authentication. |
| 0.14.0 | Protocol v1.3 (PRD 14, all additive): the Quantum AI Lab. Trainability Lab: trainability_inspect → trainability_inspected, trainability_lint → trainability_lint_result, trainability_start → trainability_started / trainability_progress / trainability_partial / trainability_result (with a provenance block for the Trainability Certificate) and trainability_cancel → trainability_cancelled. Discovery Engine: discovery_evaluators → discovery_evaluators_result, discovery_evaluate → discovery_evaluate_accepted then discovery_evaluation, discovery_cancel → discovery_cancelled, discovery_mutate → discovery_mutations. Red Queen: discovery_audit → discovery_audit_accepted then discovery_audit_result, discovery_audit_cancel → discovery_audit_cancelled. Conjecture Engine: discovery_conjecture_schema → discovery_conjecture_schema_result, discovery_conjecture_test → discovery_conjecture_started / _progress / _evidence / _result, discovery_conjecture_cancel → discovery_conjecture_cancelled. Errors use phase: "trainability" or phase: "discovery" and may carry job_id, run_id, candidate_id, path or column. discovery_evaluators entries carry an additive available flag (plus missing and install when an optional package such as Stim is absent), and discovery_evaluate / discovery_audit for an unavailable evaluator answer with a missing_dependency error. Clients that never send these messages see no change. See Quantum AI Lab messages. |
| 0.13.0 | Additive: new messages lint → lint_result (ruff diagnostics for the buffer) and format → format_result (ruff-formatted text). Python-only; both degrade to empty/no-op when ruff is absent, never blocking. See execution messages. |
| 0.12.0 | Additive: new message debug_trace → debug_trace_result — the Quantum Debugger’s per-gate state trajectory. Returns one step per gate (plus an initial ` |
| 0.11.0 | Additive: new message transpile → transpile_result — runs a Qiskit preset PassManager for a target (optional basis_gates, optional coupling_map, optimization_level 0–3) and returns before/after CircuitSnapshots, depth/two-qubit/gate-count deltas, and pass-by-pass data (each pass that changed the circuit, with the signed gate counts it added — routing SWAPs, basis rewrites). Qiskit-only (the only framework with an introspectable compiler); a non-Qiskit circuit answers with a transpile_unsupported_framework error. Powers the Transpiler Explorer. See execution messages. |
| 0.10.0 | Additive: qec_snapshot’s payload gains an optional dem_text field — the flattened detector error model as text (str(dem.flattened())), present only when the graph is truncated. It lets a client parse and render the full detector graph itself, with no kernel-side edge cap (Nuclei does this with a WebAssembly parser). Absent when the graph fits, so the common case pays nothing. See QEC messages. |
| 0.7.0 | Protocol v1.2 (PRD 10 Phase F): new message qec_estimate → qec_estimate_result — Azure Quantum Resource Estimator over Q# source or OpenQASM 3, returning physical-qubit/runtime/code-distance/T-factory headline numbers plus the full estimator document. See QEC messages. |
| 0.7.0 | Protocol v1.2 (PRD 10 Phase C): new message qec_materialize → qec_circuits — runs a campaign entry source’s nuclei_circuits(noise) and returns its labeled circuit texts. Experiment schema v2 lands app-side (type: sweep unchanged, type: qec_campaign added; schema-1 files remain valid forever). See QEC messages. |
| 0.7.0 | Protocol v1.2 (PRD 10 Phase B): sinter campaigns as managed kernel jobs — qec_campaign_start (ack qec_campaign_started; streaming qec_campaign_progress throttled to progress_interval_s, default 1s; final qec_campaign_result with sinter-native csv), qec_campaign_cancel (ack qec_campaign_cancelled, then a partial result), and qec_decode_sample (one decoded shot for the detector-graph overlay). One campaign at a time per kernel (campaign_already_running); resume via existing_stats_csv never re-samples completed tasks; campaigns deliberately take no seed (sinter has no seeding API). See QEC messages. |
| 0.7.0 | Protocol v1.2 (PRD 10 Phase A, all additive): Stim stabilizer circuits are a kernel framework — Python code building stim.Circuit objects routes through the normal pipeline, and a new language: "stim" value on parse/execute treats code as raw .stim text (parsed by stim.Circuit(text), never Python exec). Stim results honestly report sampler-only output: empty state_vector/probabilities/bloch_coords. See QEC messages. |
| 0.7.0 | Protocol v1.2: new message qec_generate → qec_generated (built-in QEC circuit text from stim’s generator set) and new message/sidecar qec_snapshot — sent automatically between snapshot and result for Stim circuits, and requestable on demand with an adjustable DEM edge cap (5,000 default, explicit truncated flag, never silent). The environment response’s packages may now include stim, sinter, pymatching, and fusion_blossom. |
| 0.6.0 | Protocol v1.1 (PRD 09 Phase B, all additive — old clients keep working unchanged): execute gains two optional request fields, params ({string: number}) and seed (integer). params is injected into the Python exec namespace as params (always a dict, {} when omitted); for Q# it binds by name to the entry operation’s declared arguments (Double/Int only — see Q# parameter binding). seed requests reproducible sampling from the underlying simulator and seeds Python’s random/numpy.random before exec. See execution messages. |
| 0.6.0 | Protocol v1.1: execute’s result response gains two optional fields — metrics ({string: float}, always present, populated via the newly-injected record_metric(name, value) Python function; empty when nothing was recorded) and seed_honored (boolean, present only when the request carried a seed, omitted otherwise). See schemas. |
| 0.6.0 | Protocol v1.1: new message type environment → response environment, reporting the kernel’s Python version, platform string, and installed framework versions (qiskit, qiskit_aer, cirq, cudaq, qsharp — absent keys mean “not installed”). See the message catalog. |
| 0.5.1 | hardware_dismiss request added (additive): removes a job record from the kernel’s registry and the persistent job store without cancelling provider-side work. Reply is hardware_job_dismissed; unknown ids succeed (already-gone semantics). See the message catalog. |
| 0.5.0 | Optional language field ("python" | "qsharp") added to parse, execute, and hardware_submit requests. Omitted by older clients, in which case framework detection stays regex-based — fully backward compatible. |
| 0.5.0 | Q# source-mode routing: when language is "qsharp", or the source matches Q# syntax, code routes to the QDK adapter instead of Python exec. |
| 0.5.0 | Reset added to the canonical gate vocabulary in CircuitSnapshot (emitted by the Q# adapter for mid-circuit |0⟩ preparation). |
| 0.5.0 | hardware_submit semantics for Q#: source compiles to QIR before submission, with the profile selected per target — see submitting Q#. Provider allowlist for Q# is simulator and azure — every other provider answers with an error message. |
| ≤ 0.4.x | Protocol v1 baseline: parse / execute / run_python plus the hardware_* family as documented in the message catalog. |