semantic_memory/quantize_governed.rs
1//! Governed compression pipeline integration for semantic-memory.
2//!
3//! This module provides the `encode_governed` function that routes embedding
4//! vectors through the quant-governor policy evaluation + scr-runtime-compression
5//! adapter pipeline. It is only available when the `turbo-quant-codec` feature
6//! is enabled.
7
8#[cfg(feature = "turbo-quant-codec")]
9pub mod governed {
10 use quant_governor::{
11 AdmissibilityClass, CodecProfile, ContentType, GovernancePolicy, GovernanceRequest,
12 };
13 use scr_runtime_compression::{build_adapter, CodecDispatch};
14
15 /// Result of governed encoding — compressed bytes plus pipeline metadata.
16 #[derive(Debug, Clone)]
17 pub struct GovernedEncodeResult {
18 /// Compressed byte representation of the embedding.
19 pub compressed_bytes: Vec<u8>,
20 /// Which codec profile was selected by the governance policy.
21 pub codec_profile: CodecProfile,
22 /// Governance receipt ID for audit trail.
23 pub governance_receipt_id: String,
24 /// Allowed degradation budget from the policy decision.
25 pub degradation_budget: f64,
26 }
27
28 /// Encode an embedding vector through the governed compression pipeline.
29 ///
30 /// The pipeline:
31 /// 1. Evaluates the governance policy against the embedding's size and
32 /// accuracy requirements to select an appropriate codec profile.
33 /// 2. Routes the raw bytes through the compression adapter selected by
34 /// the governance decision.
35 /// 3. Returns the compressed bytes plus governance metadata for storage
36 /// alongside the artifact.
37 ///
38 /// # Errors
39 ///
40 /// Returns a string error if policy evaluation fails or the codec adapter
41 /// returns an error during encoding.
42 pub fn encode_governed(
43 embedding: &[f32],
44 policy: &GovernancePolicy,
45 ) -> Result<GovernedEncodeResult, String> {
46 let raw_bytes: Vec<u8> = bytemuck::cast_slice(embedding).to_vec();
47 let request = GovernanceRequest {
48 content_type: ContentType::Structured,
49 size_bytes: raw_bytes.len() as u64,
50 accuracy_requirement: 0.99,
51 latency_tolerance_ms: 500,
52 admissibility: AdmissibilityClass::Standard,
53 };
54
55 let decision = policy.evaluate(request).map_err(|e| e.to_string())?;
56
57 // CMP-001: Build adapter from the governance decision's selected codec.
58 // Q8/Q4 are not real codecs and will error during decode.
59 let adapter = build_adapter::<Vec<u8>>(CodecDispatch::Force(match decision.codec {
60 CodecProfile::Raw => scr_runtime_compression::CodecId::Uncompressed,
61 CodecProfile::Q8 | CodecProfile::Q4 => {
62 // CMP-001: Q8/Q4 have no real decoder. Return error.
63 return Err(format!(
64 "codec profile {:?} is not implemented - no real decoder available",
65 decision.codec
66 ));
67 }
68 CodecProfile::Turbo => scr_runtime_compression::CodecId::TurboQuant,
69 CodecProfile::Fib => scr_runtime_compression::CodecId::FibQuant,
70 }));
71
72 // Encode through the adapter.
73 let compressed = adapter
74 .decode_exact(
75 match decision.codec {
76 CodecProfile::Raw => scr_runtime_compression::CodecId::Uncompressed,
77 CodecProfile::Q8 | CodecProfile::Q4 => {
78 // Already handled above — this is unreachable.
79 return Err("unreachable: Q8/Q4 handled above".to_string());
80 }
81 CodecProfile::Turbo => scr_runtime_compression::CodecId::TurboQuant,
82 CodecProfile::Fib => scr_runtime_compression::CodecId::FibQuant,
83 },
84 &raw_bytes,
85 )
86 .map_err(|e| format!("encode failed: {e}"))?;
87
88 Ok(GovernedEncodeResult {
89 compressed_bytes: compressed,
90 codec_profile: decision.codec,
91 governance_receipt_id: format!("gr-{}", uuid::Uuid::new_v4()),
92 degradation_budget: decision.degradation_budget,
93 })
94 }
95
96 /// Encode with governance using a default policy.
97 ///
98 /// Convenience wrapper that uses `GovernancePolicy::default()` for cases
99 /// where custom policy tuning is not required.
100 pub fn encode_governed_default(embedding: &[f32]) -> Result<GovernedEncodeResult, String> {
101 encode_governed(embedding, &GovernancePolicy::default())
102 }
103}
104
105#[cfg(not(feature = "turbo-quant-codec"))]
106pub mod governed {
107 //! Stub module when `turbo-quant-codec` is not enabled.
108 //!
109 //! All functions in this module return errors indicating the feature is disabled.
110 //! Note: we intentionally avoid quant_governor types here so this stub compiles
111 //! even when the optional dep is not available.
112
113 /// Stub result type — codec_profile is a string when feature is disabled.
114 #[derive(Debug, Clone)]
115 pub struct GovernedEncodeResult {
116 pub compressed_bytes: Vec<u8>,
117 pub codec_profile: String,
118 pub governance_receipt_id: String,
119 pub degradation_budget: f64,
120 }
121
122 /// Returns an error indicating the turbo-quant-codec feature is not enabled.
123 pub fn encode_governed(
124 _embedding: &[f32],
125 _policy: (),
126 ) -> Result<GovernedEncodeResult, String> {
127 Err("turbo-quant-codec feature is not enabled".to_string())
128 }
129
130 /// Returns an error indicating the turbo-quant-codec feature is not enabled.
131 pub fn encode_governed_default(_embedding: &[f32]) -> Result<GovernedEncodeResult, String> {
132 Err("turbo-quant-codec feature is not enabled".to_string())
133 }
134}
135
136// Re-export for convenience
137pub use governed::{encode_governed, encode_governed_default, GovernedEncodeResult};