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::types::*;
7use crate::config::InvariantConfig;
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!(
131                            "Invariant violation: No commitment for consequence"
132                        );
133                        return Err(InvariantViolation::NoCommitment);
134                    }
135                }
136            }
137
138            ArchitecturalInvariant::CouplingBoundedByAttention => {
139                if let Operation::EstablishCoupling {
140                    source,
141                    attention_cost,
142                    ..
143                } = operation
144                {
145                    if state.available_attention(source) < *attention_cost {
146                        tracing::error!(
147                            "Invariant violation: Attention capacity exceeded"
148                        );
149                        return Err(InvariantViolation::AttentionExceeded);
150                    }
151                }
152            }
153
154            ArchitecturalInvariant::SafetyOverridesOptimization => {
155                if operation.is_optimization() && state.safety_concern_active() {
156                    tracing::error!(
157                        "Invariant violation: Safety priority violated"
158                    );
159                    return Err(InvariantViolation::SafetyPriority);
160                }
161            }
162
163            ArchitecturalInvariant::HumanAgencyCannotBeBypassed => {
164                if let Operation::ForceAction { target, .. } = operation {
165                    if state.is_human_resonator(target) {
166                        tracing::error!(
167                            "Invariant violation: Human agency cannot be bypassed"
168                        );
169                        return Err(InvariantViolation::HumanAgencyViolation);
170                    }
171                }
172            }
173
174            ArchitecturalInvariant::FailureMustBeExplicit => {
175                // This is enforced by result types, not runtime checks
176            }
177        }
178
179        Ok(())
180    }
181
182    /// Get list of enabled invariants
183    pub fn enabled_invariants(&self) -> &[ArchitecturalInvariant] {
184        &self.invariants
185    }
186}
187
188/// Operations that can be checked against invariants
189#[derive(Debug, Clone)]
190pub enum Operation {
191    FormMeaning {
192        resonator: ResonatorId,
193    },
194    StabilizeIntent {
195        meaning: MeaningContext,
196    },
197    CreateCommitment {
198        intent: IntentContext,
199    },
200    ProduceConsequence {
201        commitment_id: CommitmentId,
202    },
203    EstablishCoupling {
204        source: ResonatorId,
205        target: ResonatorId,
206        attention_cost: u64,
207    },
208    ForceAction {
209        target: ResonatorId,
210    },
211    Optimization,
212}
213
214impl Operation {
215    pub fn is_optimization(&self) -> bool {
216        matches!(self, Operation::Optimization)
217    }
218}
219
220/// System state for invariant checking
221#[derive(Debug, Clone)]
222pub struct SystemState {
223    present_resonators: std::collections::HashSet<ResonatorId>,
224    human_resonators: std::collections::HashSet<ResonatorId>,
225    commitments: std::collections::HashSet<CommitmentId>,
226    attention_budgets: std::collections::HashMap<ResonatorId, u64>,
227    safety_concerns: bool,
228}
229
230impl SystemState {
231    pub fn new() -> Self {
232        Self {
233            present_resonators: std::collections::HashSet::new(),
234            human_resonators: std::collections::HashSet::new(),
235            commitments: std::collections::HashSet::new(),
236            attention_budgets: std::collections::HashMap::new(),
237            safety_concerns: false,
238        }
239    }
240
241    pub fn is_present(&self, resonator: &ResonatorId) -> bool {
242        self.present_resonators.contains(resonator)
243    }
244
245    pub fn is_human_resonator(&self, resonator: &ResonatorId) -> bool {
246        self.human_resonators.contains(resonator)
247    }
248
249    pub fn commitment_exists(&self, commitment_id: &CommitmentId) -> bool {
250        self.commitments.contains(commitment_id)
251    }
252
253    pub fn available_attention(&self, resonator: &ResonatorId) -> u64 {
254        self.attention_budgets.get(resonator).copied().unwrap_or(0)
255    }
256
257    pub fn safety_concern_active(&self) -> bool {
258        self.safety_concerns
259    }
260}
261
262impl Default for SystemState {
263    fn default() -> Self {
264        Self::new()
265    }
266}
267
268/// Meaning context (placeholder)
269#[derive(Debug, Clone)]
270pub struct MeaningContext {
271    pub confidence: f64,
272}
273
274/// Intent context (placeholder)
275#[derive(Debug, Clone)]
276pub struct IntentContext {
277    stabilized: bool,
278}
279
280impl IntentContext {
281    pub fn is_stabilized(&self) -> bool {
282        self.stabilized
283    }
284}
285
286// Re-export InvariantViolation from types module so it's accessible
287pub use crate::types::InvariantViolation;