7.6 KiB
Sub-plan 1 — Foundation (Tasks 1–3)
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans.
Goal: Cargo bootstrap + error types + domain newtypes + Backend trait hierarchy. Produces a compiling skeleton with all dependencies resolved.
Starting state: Greenfield — only CLAUDE.md, .gitignore, and docs/ exist. No src/, no Cargo.toml.
Deliverable: cargo test exits 0. Three commits in git history.
Tech Stack: Rust 2021, rmcp (git), oq3_semantics 0.7, spinoza 0.5, tokio, serde, thiserror 2, tracing.
Main plan reference: docs/superpowers/plans/2026-04-28-quantum-bridge-mcp-v1.md Tasks 1–3.
Task 1: Bootstrap
Files:
-
Create:
Cargo.toml -
Create:
src/main.rs(viacargo new) -
Step 1: Initialise project
cd /home/vincent/src/misc/quantum-bridge-mcp
cargo new --name quantum-bridge-mcp .
Expected: src/main.rs and Cargo.toml created.
- Step 2: Write Cargo.toml
Run
cargo search spinozaandcargo search oq3_semanticsto confirm latest patch versions before pinning.
[package]
name = "quantum-bridge-mcp"
version = "0.1.0"
edition = "2021"
description = "Zero-dependency MCP server for local OpenQASM 3.0 quantum circuit simulation"
license = "MIT"
[dependencies]
rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", features = ["server", "transport-io", "macros"] }
oq3_semantics = "0.7"
spinoza = "0.5"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
schemars = "0.8"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
anyhow = "1"
[dev-dependencies]
proptest = "1"
criterion = { version = "0.5", features = ["html_reports"] }
[[bench]]
name = "simulation"
harness = false
- Step 3: Write minimal src/main.rs
fn main() {
println!("quantum-bridge-mcp");
}
- Step 4: Verify dependencies compile
cargo build
Expected: success (first run ~200 MB). If a version constraint fails, run cargo search <crate> and adjust.
- Step 5: Commit
git add Cargo.toml Cargo.lock src/main.rs
git commit -m "chore: bootstrap project with all V1 dependencies"
Task 2: Foundation — Error types and domain newtypes
Files:
-
Create:
src/error.rs -
Create:
src/types.rs -
Modify:
src/main.rs -
Step 1: Write src/error.rs
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BridgeError {
#[error("parse error at line {line}, col {col}: {message}")]
Parse { line: usize, col: usize, message: String },
#[error("gate '{gate}' is not supported at line {line} — supported: {supported}")]
UnsupportedGate { gate: String, line: usize, supported: String },
#[error("qubit index {index} is out of range (circuit declares {declared} qubits)")]
QubitOutOfRange { index: usize, declared: usize },
#[error("circuit requires {requested} qubits, exceeds the local simulator limit of {limit}")]
QubitLimitExceeded { requested: usize, limit: usize },
#[error("simulation failed: {0}")]
Simulation(String),
#[error("measure at line {line} maps to an undeclared classical bit")]
MeasurementMapping { line: usize },
}
- Step 2: Write src/types.rs
use std::collections::HashMap;
/// Newtype for qubit indices — prevents mixing with plain usizes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct QubitIndex(pub usize);
/// Newtype for shot count — enforces range and intent at type level.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ShotCount(pub u32);
impl ShotCount {
pub const DEFAULT: ShotCount = ShotCount(1024);
pub const MAX: ShotCount = ShotCount(100_000);
}
/// Wraps an OpenQASM 3.0 source string.
#[derive(Debug, Clone)]
pub struct CircuitSource(pub String);
#[derive(Debug, Clone)]
pub enum DiagnosticSeverity {
Error,
Warning,
}
#[derive(Debug, Clone)]
pub struct ValidationDiagnostic {
pub line: usize,
pub column: usize,
pub message: String,
pub severity: DiagnosticSeverity,
}
#[derive(Debug, Clone)]
pub struct ValidationResult {
pub is_valid: bool,
pub diagnostics: Vec<ValidationDiagnostic>,
pub num_qubits: Option<usize>,
pub num_gates: Option<usize>,
}
#[derive(Debug, Clone)]
pub struct SimulationResult {
/// Bitstring → count, e.g. `{"00": 512, "11": 512}`.
pub counts: HashMap<String, u64>,
pub shots: u32,
pub execution_time_ms: f64,
/// Optional full statevector as (real, imag) pairs per basis state.
pub statevector: Option<Vec<(f64, f64)>>,
}
- Step 3: Update src/main.rs
mod error;
mod types;
fn main() {
println!("quantum-bridge-mcp");
}
- Step 4: Verify
cargo build
Expected: no warnings.
- Step 5: Commit
git add src/error.rs src/types.rs src/main.rs
git commit -m "feat: add error types and domain newtypes"
Task 3: Backend Traits
Files:
-
Create:
src/executor.rs(traits + constants only —LocalSimulatorcomes in sub-plan 3) -
Step 1: Write src/executor.rs
use crate::error::BridgeError;
use crate::types::{CircuitSource, ShotCount, SimulationResult, ValidationResult};
pub const MAX_LOCAL_QUBITS: usize = 28;
pub const SUPPORTED_GATES: &[&str] = &[
"h", "x", "y", "z", "s", "t", "sdg", "tdg",
"rx", "ry", "rz", "cx", "cz", "swap", "ccx",
"measure",
];
pub trait CanIntrospect {
fn name(&self) -> &str;
fn max_qubits(&self) -> usize;
fn supported_gates(&self) -> &[&str];
}
pub trait CanValidate {
fn validate(&self, circuit: &CircuitSource) -> Result<ValidationResult, BridgeError>;
}
pub trait CanExecute {
fn run(
&self,
circuit: &CircuitSource,
shots: ShotCount,
return_statevector: bool,
) -> Result<SimulationResult, BridgeError>;
}
/// Marker trait combining all three capabilities. V1.5 IBM backend will impl this too.
pub trait Backend: CanIntrospect + CanValidate + CanExecute + Send + Sync {}
#[cfg(test)]
mod tests {
use super::*;
struct MockBackend;
impl CanIntrospect for MockBackend {
fn name(&self) -> &str { "mock" }
fn max_qubits(&self) -> usize { 4 }
fn supported_gates(&self) -> &[&str] { SUPPORTED_GATES }
}
impl CanValidate for MockBackend {
fn validate(&self, _: &CircuitSource) -> Result<ValidationResult, BridgeError> {
Ok(ValidationResult { is_valid: true, diagnostics: vec![], num_qubits: None, num_gates: None })
}
}
impl CanExecute for MockBackend {
fn run(&self, _: &CircuitSource, _: ShotCount, _: bool) -> Result<SimulationResult, BridgeError> {
Ok(SimulationResult { counts: Default::default(), shots: 0, execution_time_ms: 0.0, statevector: None })
}
}
impl Backend for MockBackend {}
#[test]
fn mock_backend_satisfies_trait_bounds() {
let b = MockBackend;
assert_eq!(b.name(), "mock");
assert_eq!(b.max_qubits(), 4);
}
}
- Step 2: Declare module and run tests
Add to src/main.rs:
mod executor;
cargo test
Expected: 1 test passes (mock_backend_satisfies_trait_bounds).
- Step 3: Commit
git add src/executor.rs src/main.rs
git commit -m "feat: define Backend trait hierarchy (CanIntrospect/CanValidate/CanExecute)"
Final verification
cargo fmt --check && cargo clippy -- -D warnings && cargo test
Expected: all green. Sub-plan 1 complete — hand off to sub-plan 2.