Skip to main content

maple_runtime/invariants/
mod.rs

1//! Invariant enforcement - The 8 Canonical Invariants
2//!
3//! These invariants MUST hold in ALL conformant implementations.
4//! Violation of ANY invariant constitutes non-conformance.
5
6use crate::config::InvariantConfig;
7use crate::types::*;
8
9/// Enforces the Resonance Architecture's 8 canonical invariants
10pub struct InvariantGuard {
11    invariants: Vec<ArchitecturalInvariant>,
12    config: InvariantConfig,
13}
14
15/// The 8 canonical invariants from Resonance Architecture
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum ArchitecturalInvariant {
18    /// 1. Presence precedes meaning
19    /// A Resonator must be present before it can form or receive meaning.
20    PresencePrecedesMeaning,
21
22    /// 2. Meaning precedes intent
23    /// Intent cannot be formed without sufficient meaning.
24    MeaningPrecedesIntent,
25
26    /// 3. Intent precedes commitment
27    /// Commitments cannot be created without stabilized intent.
28    IntentPrecedesCommitment,
29
30    /// 4. Commitment precedes consequence
31    /// No consequence may occur without an explicit commitment.
32    CommitmentPrecedesConsequence,
33
34    /// 5. Coupling is bounded by attention
35    /// Coupling strength cannot exceed available attention.
36    CouplingBoundedByAttention,
37
38    /// 6. Safety overrides optimization
39    /// Safety constraints take precedence over performance/efficiency.
40    SafetyOverridesOptimization,
41
42    /// 7. Human agency cannot be bypassed
43    /// Human Resonators must always be able to disengage.
44    HumanAgencyCannotBeBypassed,
45
46    /// 8. Failure must be explicit, never silent
47    /// All failures must be surfaced, never hidden.
48    FailureMustBeExplicit,
49}
50
51impl InvariantGuard {
52    pub fn new(config: &InvariantConfig) -> Self {
53        let invariants = vec![
54            ArchitecturalInvariant::PresencePrecedesMeaning,
55            ArchitecturalInvariant::MeaningPrecedesIntent,
56            ArchitecturalInvariant::IntentPrecedesCommitment,
57            ArchitecturalInvariant::CommitmentPrecedesConsequence,
58            ArchitecturalInvariant::CouplingBoundedByAttention,
59            ArchitecturalInvariant::SafetyOverridesOptimization,
60            ArchitecturalInvariant::HumanAgencyCannotBeBypassed,
61            ArchitecturalInvariant::FailureMustBeExplicit,
62        ];
63
64        Self {
65            invariants,
66            config: config.clone(),
67        }
68    }
69
70    /// Check all invariants before an operation
71    pub fn check(
72        &self,
73        operation: &Operation,
74        state: &SystemState,
75    ) -> Result<(), InvariantViolation> {
76        if !self.config.enabled {
77            return Ok(());
78        }
79
80        for invariant in &self.invariants {
81            self.check_invariant(*invariant, operation, state)?;
82        }
83
84        Ok(())
85    }
86
87    fn check_invariant(
88        &self,
89        invariant: ArchitecturalInvariant,
90        operation: &Operation,
91        state: &SystemState,
92    ) -> Result<(), InvariantViolation> {
93        match invariant {
94            ArchitecturalInvariant::PresencePrecedesMeaning => {
95                if let Operation::FormMeaning { resonator, .. } = operation {
96                    if !state.is_present(resonator) {
97                        tracing::error!(
98                            "Invariant violation: Presence required for meaning formation"
99                        );
100                        return Err(InvariantViolation::PresenceRequired);
101                    }
102                }
103            }
104
105            ArchitecturalInvariant::MeaningPrecedesIntent => {
106                if let Operation::StabilizeIntent { meaning, .. } = operation {
107                    if meaning.confidence < 0.1 {
108                        tracing::error!(
109                            "Invariant violation: Insufficient meaning for intent stabilization"
110                        );
111                        return Err(InvariantViolation::InsufficientMeaning);
112                    }
113                }
114            }
115
116            ArchitecturalInvariant::IntentPrecedesCommitment => {
117                if let Operation::CreateCommitment { intent, .. } = operation {
118                    if !intent.is_stabilized() {
119                        tracing::error!(
120                            "Invariant violation: Intent not stabilized before commitment"
121                        );
122                        return Err(InvariantViolation::UnstabilizedIntent);
123                    }
124                }
125            }
126
127            ArchitecturalInvariant::CommitmentPrecedesConsequence => {
128                if let Operation::ProduceConsequence { commitment_id, .. } = operation {
129                    if !state.commitment_exists(commitment_id) {
130                        tracing::error!("Invariant violation: No commitment for consequence");
131                        return Err(InvariantViolation::NoCommitment);
132                    }
133                }
134            }
135
136            ArchitecturalInvariant::CouplingBoundedByAttention => {
137                if let Operation::EstablishCoupling {
138                    source,
139                    attention_cost,
140                    ..
141                } = operation
142                {
143                    if state.available_attention(source) < *attention_cost {
144                        tracing::error!("Invariant violation: Attention capacity exceeded");
145                        return Err(InvariantViolation::AttentionExceeded);
146                    }
147                }
148            }
149
150            ArchitecturalInvariant::SafetyOverridesOptimization => {
151                if operation.is_optimization() && state.safety_concern_active() {
152                    tracing::error!("Invariant violation: Safety priority violated");
153                    return Err(InvariantViolation::SafetyPriority);
154                }
155            }
156
157            ArchitecturalInvariant::HumanAgencyCannotBeBypassed => {
158                if let Operation::ForceAction { target, .. } = operation {
159                    if state.is_human_resonator(target) {
160                        tracing::error!("Invariant violation: Human agency cannot be bypassed");
161                        return Err(InvariantViolation::HumanAgencyViolation);
162                    }
163                }
164            }
165
166            ArchitecturalInvariant::FailureMustBeExplicit => {
167                // This is enforced by result types, not runtime checks
168            }
169        }
170
171        Ok(())
172    }
173
174    /// Get list of enabled invariants
175    pub fn enabled_invariants(&self) -> &[ArchitecturalInvariant] {
176        &self.invariants
177    }
178}
179
180/// Operations that can be checked against invariants
181#[derive(Debug, Clone)]
182pub enum Operation {
183    FormMeaning {
184        resonator: ResonatorId,
185    },
186    StabilizeIntent {
187        meaning: MeaningContext,
188    },
189    CreateCommitment {
190        intent: IntentContext,
191    },
192    ProduceConsequence {
193        commitment_id: CommitmentId,
194    },
195    EstablishCoupling {
196        source: ResonatorId,
197        target: ResonatorId,
198        attention_cost: u64,
199    },
200    ForceAction {
201        target: ResonatorId,
202    },
203    Optimization,
204}
205
206impl Operation {
207    pub fn is_optimization(&self) -> bool {
208        matches!(self, Operation::Optimization)
209    }
210}
211
212/// System state for invariant checking
213#[derive(Debug, Clone)]
214pub struct SystemState {
215    present_resonators: std::collections::HashSet<ResonatorId>,
216    human_resonators: std::collections::HashSet<ResonatorId>,
217    commitments: std::collections::HashSet<CommitmentId>,
218    attention_budgets: std::collections::HashMap<ResonatorId, u64>,
219    safety_concerns: bool,
220}
221
222impl SystemState {
223    pub fn new() -> Self {
224        Self {
225            present_resonators: std::collections::HashSet::new(),
226            human_resonators: std::collections::HashSet::new(),
227            commitments: std::collections::HashSet::new(),
228            attention_budgets: std::collections::HashMap::new(),
229            safety_concerns: false,
230        }
231    }
232
233    pub fn is_present(&self, resonator: &ResonatorId) -> bool {
234        self.present_resonators.contains(resonator)
235    }
236
237    pub fn is_human_resonator(&self, resonator: &ResonatorId) -> bool {
238        self.human_resonators.contains(resonator)
239    }
240
241    pub fn commitment_exists(&self, commitment_id: &CommitmentId) -> bool {
242        self.commitments.contains(commitment_id)
243    }
244
245    pub fn available_attention(&self, resonator: &ResonatorId) -> u64 {
246        self.attention_budgets.get(resonator).copied().unwrap_or(0)
247    }
248
249    pub fn safety_concern_active(&self) -> bool {
250        self.safety_concerns
251    }
252}
253
254impl Default for SystemState {
255    fn default() -> Self {
256        Self::new()
257    }
258}
259
260/// Meaning context (placeholder)
261#[derive(Debug, Clone)]
262pub struct MeaningContext {
263    pub confidence: f64,
264}
265
266/// Intent context (placeholder)
267#[derive(Debug, Clone)]
268pub struct IntentContext {
269    stabilized: bool,
270}
271
272impl IntentContext {
273    pub fn is_stabilized(&self) -> bool {
274        self.stabilized
275    }
276}
277
278// Re-export InvariantViolation from types module so it's accessible
279pub use crate::types::InvariantViolation;