Repository navigation
feat(qsearch): Nano q-search service for Predator Drive - #45
Merged
Merged
Conversation
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
pair02 on heron_heavy_hex (d3, 19 physical qubits), opt 3, seed 11: ordinary logical_2q 30 / native_2q 112 / native_depth 85; joint5 (four greedy nuclei) logical_2q 46 / native_2q 87 / native_depth 66. auto keeps joint5. Deviations from the plan code, both forced by qiskit 2.3.1: - CouplingMap.distance is a read-only method, so the code distance is recovered from the map size by _heavy_hex_distance (the plan's fallback). - Unnamed circuits get a process-global counter name that QPY serializes, which made the plan digest differ between two compiles of the same job; the QPY hash is taken over a copy with a fixed name. Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Two compiles of pair02 produced equal ISA circuits but different QPY bytes: the TranspileLayout stored in QPY places idle ancilla qubits differently from run to run (also across processes). The qpy_sha256 is now taken over a layout-free copy (same registers, instructions, global phase, metadata, fixed name). Checked stable over 8 compiles in each of two processes for pair02 and job_4var; measurement_map in the plan still records the physical qubit read into each classical bit. Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
Engine code is the plan's Step 3 unchanged. Measured (qiskit-aer 0.17.2): pair02 joint5 on heavy_hex_d3: statevector tvd_ideal 0.0288, MPS tvd_ideal 0.0339 (|diff| 0.0051 <= 0.01), MPS chi_reached 6 of 64, mean_energy_sample -0.7035 vs mean_energy_ideal -0.7072, best sample energy equals classical_min_energy -18.0327 (to 4e-15). job_4var: tvd_ideal 0.0475 (sv) / 0.0664 (mps), chi_reached 2, best -1.6. One CLI child run (job_4var, statevector) about 4.4 s wall. Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
The nano package is deterministic by contract (tests/test_determinism_guards.py: no clock, env, subprocess or network, one optional third-party import). The q-search service is a host process, so it lives beside nano/, not inside it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Job parsing: overflowing ints are QUBO errors instead of OverflowError, symmetry is exact equality, seeds may be negative (Predator allows them; the service refuses out-of-range seeds with a receipt), and parse_job is split into per-section helpers with unchanged error codes. Receipts: ok_receipt re-derives every sample energy from the job, requires best to be their minimum and not below the classical floor, and raises ReceiptAuditError otherwise. verify_seal maps an uncanonical body to SealError. NOT_RUN/REFUSED reasons are capped at 200 chars. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JobStore.complete is one conditional UPDATE (KeyError if unknown, ValueError if already DONE, the stored receipt untouched); mark_attempt raises KeyError for an unknown digest; busy_timeout=5000. Auth tests pin the AuthError code per tamper case. conftest appends sibling paths and fails loudly on a non-directory; regen.py writes LF and exits 2 without NANO_QSEARCH_PREDATOR_PATH. Docstrings: MemoryNonceStore is tests-only; canonical refuses Enum/dataclass on purpose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd recovery Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pyproject: nano-qsearch-serve script, quantum extra (qiskit 2.3.1, qiskit-aer 0.17.2, numpy), engine/integration markers. docs/qsearch-service.md: config and caps, auth, responses, chi_source, recovery, package location, and the Predator-side signing opener (exercised by a test against a live service). Also: the HTTP handler drains small bodies on 404 so Windows does not reset the client, and the 413 test sends headers only (an unread oversized body can reset the connection by design). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…afe child runs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r bind Request socket timeout (NANO_QSEARCH_REQUEST_TIMEOUT_S, default 30 s); exclusive qsearch.lock per data dir (DataDirLocked, exit 2); prepare() binds before recover(); a complete() ValueError returns the stored DONE receipt; nonce-store errors are 503; BoundedSemaphore cap on runtime calls (NANO_QSEARCH_MAX_CONCURRENT, default 2); runtime kind stored at accept (migrated jobs.kind column) and used by recovery; 404 for every non-POST method, empty-body HEAD; submit gets SUBMIT_PATH; generic 401 body with the code logged only when verbose. Tests for each, plus the review's missing cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nup pinned Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e one line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… server Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also: the recovery reason for hardware jobs now reads 'never run from recovery', which is true whether or not the run had started. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Strip legacy IBM and Predator key variables from the engine child, report unreadable key files by class only, document logical-circuit sampling, the Fez target dependency and the IBM delegate stub, replace local paths in the plan, and add a changelog entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
nano_qsearch, the q-search service that Predator Drive'sNanoRuntimeQSearchBackendcalls (V2 lane L3, gate G-W3). It takes the exactQSearchJobV1.to_payload()body onPOST /qsearch/v1/submitand answers with apredator.qsearch.receipt.v1that Predator's ownQSearchReceiptV1.from_payloadaccepts. The wire contract is unchanged.X-Aether-Qsearch-Authcarries an HMAC-SHA256 over method, path, body hash, timestamp and nonce, with its own key file. The window is ±120 s and nonces are durable. Unauthenticated or replayed requests get a generic 401 and no receipt.canonical_digestpins the encoding.job_digest, so an identical resubmit returns the stored receipt. After a crash, restart re-runs an accepted job once, with the same seed and the backend recorded at accept time. Hardware jobs are never run from recovery. The data directory is locked to one instance.build_nucleus_programcompiles ordinary and joint5 (viafind_nuclei), transpiles to Heron{cz, rz, sx, x}on heavy-hex and keeps the smaller native 2Q count. Qiskit Aer then samples on statevector (n ≤ 20) or MPS, in a child process withOMP_NUM_THREADS=1, five tries and a per-job wall budget. A failure becomesNOT_RUNwith a class-name reason. MPS reports the peak bond dimension from Aer's log. Every receipt here is classical simulation.AETHER_AQRC_HW_GO=1, an authority file, QPU seconds and a Fez target. Even then the ATLAScampaign_runtimedelegate refuses, because no q-search purpose is qualified there yet.nano_qsearch/package besidenano/, becausetests/test_determinism_guards.pykeeps clocks, environment, subprocesses and third-party imports out ofnano/. The base install stays dependency-free. qiskit 2.3.1, qiskit-aer 0.17.2 and numpy come with the newaether-nano[quantum]extra, and the CLI isnano-qsearch-serve. Operator guide:docs/qsearch-service.md. Plan, evidence and hand-off notes:docs/superpowers/plans/2026-10-21-l3-qsearch-service.md.Needs a Predator change (raised in the hand-off notes, not made here). Predator's default opener sends no auth header, so it gets
NOT_RUN transport: HTTPErroruntil Predator gains a signing opener and a request-key setting.Tests. GitHub Actions is not running on private Aether repos right now, so these are local results. They were run from the repo root on Windows with system Python 3.12.10, qiskit 2.3.1, qiskit-aer 0.17.2, SQLite 3.49.1, ATLAS
feat/qcompiler-find-nucleiand Predator-Morigin/main17ee3368:tests/test_provenance.pyhas 7 failures that predate this branch: the installedaether_protocol_crejects float fields. Neither that file nornano/bridgeis touched.pytestandpip install -e ., the suite gives1370 passed, 4 skipped. The engine tests skip there.python -m nano_qsearchproduced:recovered=1, a single re-run on the recorded backend, andattempts 2;ATLAS counterpart: AetherAI3/AETHER-ATLAS#177.
🤖 Generated with Claude Code