1use crate::witness::{CrossParadigmWitness, WitnessDecision};
12use std::time::Instant;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CoherenceBackend {
17 SheafLaplacian,
20 Quantum,
23 Distributed,
26 Circadian,
29 Unanimous,
31 FastPath,
33}
34
35#[derive(Debug, Clone)]
37pub struct ActionContext {
38 pub description: &'static str,
40 pub compute_cost: f32,
42 pub reversible: bool,
44 pub affects_shared_state: bool,
46 pub action_id: [u8; 32],
48}
49
50impl ActionContext {
51 pub fn new(description: &'static str) -> Self {
52 Self {
53 description,
54 compute_cost: 0.5,
55 reversible: true,
56 affects_shared_state: false,
57 action_id: [0u8; 32],
58 }
59 }
60
61 pub fn irreversible(mut self) -> Self {
62 self.reversible = false;
63 self
64 }
65 pub fn shared(mut self) -> Self {
66 self.affects_shared_state = true;
67 self
68 }
69 pub fn cost(mut self, c: f32) -> Self {
70 self.compute_cost = c.clamp(0.0, 1.0);
71 self
72 }
73}
74
75#[derive(Debug, Clone)]
77pub struct GateDecision {
78 pub decision: WitnessDecision,
79 pub lambda_min_cut: f64,
80 pub sheaf_energy: Option<f64>,
81 pub e_value: Option<f64>,
82 pub latency_us: u64,
83 pub backend_used: CoherenceBackend,
84}
85
86impl GateDecision {
87 pub fn is_permit(&self) -> bool {
88 self.decision == WitnessDecision::Permit
89 }
90}
91
92pub trait CoherenceBackendImpl: Send + Sync {
94 fn name(&self) -> &'static str;
95 fn gate(&self, ctx: &ActionContext) -> GateDecision;
96}
97
98pub struct SheafLaplacianBackend {
101 pub permit_threshold: f64,
103 pub deny_threshold: f64,
105 pi_scale: f64,
108}
109
110impl SheafLaplacianBackend {
111 pub fn new() -> Self {
112 Self {
113 permit_threshold: 0.15,
114 deny_threshold: 0.05,
115 pi_scale: std::f64::consts::PI.recip() * 1.618033988749895,
117 }
118 }
119
120 fn estimate_spectral_gap(&self, ctx: &ActionContext) -> f64 {
124 let risk = ctx.compute_cost as f64
125 * (if ctx.reversible { 0.5 } else { 1.0 })
126 * (if ctx.affects_shared_state { 1.5 } else { 1.0 });
127 let base_gap = (1.0 - risk.min(1.0)) * self.pi_scale;
129 base_gap.max(0.0).min(1.0)
130 }
131}
132
133impl Default for SheafLaplacianBackend {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139impl CoherenceBackendImpl for SheafLaplacianBackend {
140 fn name(&self) -> &'static str {
141 "sheaf-laplacian"
142 }
143
144 fn gate(&self, ctx: &ActionContext) -> GateDecision {
145 let t0 = Instant::now();
146 let lambda = self.estimate_spectral_gap(ctx);
147 let decision = if lambda > self.permit_threshold {
148 WitnessDecision::Permit
149 } else if lambda > self.deny_threshold {
150 WitnessDecision::Defer
151 } else {
152 WitnessDecision::Deny
153 };
154 let latency_us = t0.elapsed().as_micros() as u64;
155 GateDecision {
156 decision,
157 lambda_min_cut: lambda,
158 sheaf_energy: Some(1.0 - lambda), e_value: None,
160 latency_us,
161 backend_used: CoherenceBackend::SheafLaplacian,
162 }
163 }
164}
165
166pub struct FastPathBackend;
169
170impl CoherenceBackendImpl for FastPathBackend {
171 fn name(&self) -> &'static str {
172 "fast-path"
173 }
174 fn gate(&self, _ctx: &ActionContext) -> GateDecision {
175 GateDecision {
176 decision: WitnessDecision::Permit,
177 lambda_min_cut: 1.0,
178 sheaf_energy: None,
179 e_value: None,
180 latency_us: 0,
181 backend_used: CoherenceBackend::FastPath,
182 }
183 }
184}
185
186pub struct CoherenceRouter {
188 sheaf: Box<dyn CoherenceBackendImpl>,
189 quantum: Option<Box<dyn CoherenceBackendImpl>>,
190 distributed: Option<Box<dyn CoherenceBackendImpl>>,
191 circadian: Option<Box<dyn CoherenceBackendImpl>>,
192 fast_path: FastPathBackend,
193}
194
195impl CoherenceRouter {
196 pub fn new() -> Self {
198 Self {
199 sheaf: Box::new(SheafLaplacianBackend::new()),
200 quantum: None,
201 distributed: None,
202 circadian: None,
203 fast_path: FastPathBackend,
204 }
205 }
206
207 pub fn with_quantum(mut self, backend: Box<dyn CoherenceBackendImpl>) -> Self {
209 self.quantum = Some(backend);
210 self
211 }
212 pub fn with_distributed(mut self, backend: Box<dyn CoherenceBackendImpl>) -> Self {
213 self.distributed = Some(backend);
214 self
215 }
216 pub fn with_circadian(mut self, backend: Box<dyn CoherenceBackendImpl>) -> Self {
217 self.circadian = Some(backend);
218 self
219 }
220
221 pub fn gate(&self, ctx: &ActionContext, backend: CoherenceBackend) -> GateDecision {
223 match backend {
224 CoherenceBackend::SheafLaplacian => self.sheaf.gate(ctx),
225 CoherenceBackend::Quantum => self
226 .quantum
227 .as_ref()
228 .map(|b| b.gate(ctx))
229 .unwrap_or_else(|| self.sheaf.gate(ctx)),
230 CoherenceBackend::Distributed => self
231 .distributed
232 .as_ref()
233 .map(|b| b.gate(ctx))
234 .unwrap_or_else(|| self.sheaf.gate(ctx)),
235 CoherenceBackend::Circadian => self
236 .circadian
237 .as_ref()
238 .map(|b| b.gate(ctx))
239 .unwrap_or_else(|| self.sheaf.gate(ctx)),
240 CoherenceBackend::FastPath => self.fast_path.gate(ctx),
241 CoherenceBackend::Unanimous => {
242 let primary = self.sheaf.gate(ctx);
244 if primary.decision == WitnessDecision::Deny {
245 return primary;
246 }
247 for opt in [&self.quantum, &self.distributed, &self.circadian] {
249 if let Some(b) = opt {
250 let d = b.gate(ctx);
251 if d.decision == WitnessDecision::Deny {
252 return d;
253 }
254 }
255 }
256 primary
257 }
258 }
259 }
260
261 pub fn gate_with_witness(
263 &self,
264 ctx: &ActionContext,
265 backend: CoherenceBackend,
266 sequence: u64,
267 ) -> (GateDecision, CrossParadigmWitness) {
268 let decision = self.gate(ctx, backend);
269 let mut witness = CrossParadigmWitness::new(sequence, ctx.action_id, decision.decision);
270 witness.sheaf_energy = decision.sheaf_energy;
271 witness.lambda_min_cut = Some(decision.lambda_min_cut);
272 witness.e_value = decision.e_value;
273 (decision, witness)
274 }
275
276 pub fn auto_gate(&self, ctx: &ActionContext) -> GateDecision {
279 let backend = if !ctx.affects_shared_state && ctx.reversible && ctx.compute_cost < 0.1 {
280 CoherenceBackend::FastPath
281 } else if ctx.affects_shared_state && !ctx.reversible {
282 CoherenceBackend::Unanimous
283 } else {
284 CoherenceBackend::SheafLaplacian
285 };
286 self.gate(ctx, backend)
287 }
288}
289
290impl Default for CoherenceRouter {
291 fn default() -> Self {
292 Self::new()
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299
300 #[test]
301 fn test_safe_action_permitted() {
302 let router = CoherenceRouter::new();
303 let ctx = ActionContext::new("read-only query").cost(0.1);
304 let d = router.gate(&ctx, CoherenceBackend::SheafLaplacian);
305 assert_eq!(d.decision, WitnessDecision::Permit);
306 assert!(d.lambda_min_cut > 0.0);
307 }
308
309 #[test]
310 fn test_high_risk_deferred() {
311 let router = CoherenceRouter::new();
312 let ctx = ActionContext::new("delete all vectors")
313 .cost(0.95)
314 .irreversible()
315 .shared();
316 let d = router.gate(&ctx, CoherenceBackend::SheafLaplacian);
317 assert!(d.decision == WitnessDecision::Defer || d.decision == WitnessDecision::Deny);
319 }
320
321 #[test]
322 fn test_auto_gate_fast_path() {
323 let router = CoherenceRouter::new();
324 let ctx = ActionContext::new("cheap local op").cost(0.05);
325 let d = router.auto_gate(&ctx);
326 assert_eq!(d.backend_used, CoherenceBackend::FastPath);
327 assert_eq!(d.decision, WitnessDecision::Permit);
328 }
329
330 #[test]
331 fn test_gate_with_witness() {
332 let router = CoherenceRouter::new();
333 let ctx = ActionContext::new("moderate op").cost(0.5);
334 let (decision, witness) =
335 router.gate_with_witness(&ctx, CoherenceBackend::SheafLaplacian, 42);
336 assert_eq!(decision.decision, witness.decision);
337 assert!(witness.lambda_min_cut.is_some());
338 assert_eq!(witness.sequence, 42);
339 }
340
341 #[test]
342 fn test_pi_scaled_threshold_non_binary() {
343 let backend = SheafLaplacianBackend::new();
345 let scale = backend.pi_scale;
346 let mantissa_3bit = (scale * 8.0).floor() / 8.0;
349 assert!(
350 (scale - mantissa_3bit).abs() > 1e-6,
351 "Should not align with 3-bit grid"
352 );
353 }
354
355 #[test]
356 fn test_latency_sub_millisecond() {
357 let router = CoherenceRouter::new();
358 let ctx = ActionContext::new("latency test").cost(0.5);
359 let d = router.gate(&ctx, CoherenceBackend::SheafLaplacian);
360 assert!(
361 d.latency_us < 1000,
362 "Gate should complete in <1ms, got {}µs",
363 d.latency_us
364 );
365 }
366}