Skip to main content

st/mem8/
safety.rs

1//! Safety mechanisms for MEM8 consciousness simulation
2//! Implements critical protections against cognitive instability
3//! Based on MEM8 paper section: Safety Mechanisms and Consciousness Stability
4
5use crate::mem8::wave::MemoryWave;
6use std::collections::{HashMap, VecDeque};
7use std::sync::{Arc, RwLock};
8use std::time::{Duration, Instant};
9
10/// The Custodian: Memory guard system preventing overload and instability
11pub struct Custodian {
12    /// Safe repetition threshold
13    pub safe_threshold: f32,
14    /// Critical repetition threshold
15    pub critical_threshold: f32,
16    /// Memory pattern history
17    pattern_history: RwLock<HashMap<u64, PatternTracker>>,
18    /// Global resource limits
19    resource_limits: ResourceLimits,
20}
21
22/// Pattern tracking for repetition detection
23struct PatternTracker {
24    /// Pattern hash
25    hash: u64,
26    /// Repetition count
27    count: usize,
28    /// Last seen timestamp
29    last_seen: Instant,
30    /// Repetition intervals
31    intervals: VecDeque<Duration>,
32}
33
34/// Resource limits to prevent overload
35struct ResourceLimits {
36    /// Maximum active memories
37    max_active_memories: usize,
38    /// Maximum processing cycles per second
39    max_cycles_per_second: usize,
40    /// Maximum memory growth rate
41    max_growth_rate: f32,
42}
43
44impl Default for Custodian {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl Custodian {
51    pub fn new() -> Self {
52        Self {
53            safe_threshold: 5.0,
54            critical_threshold: 10.0,
55            pattern_history: RwLock::new(HashMap::new()),
56            resource_limits: ResourceLimits {
57                max_active_memories: 10_000,
58                max_cycles_per_second: 1_000,
59                max_growth_rate: 1.5,
60            },
61        }
62    }
63
64    /// Guard memory access based on repetition score
65    pub fn guard_memory(&self, memory: &MemoryWave) -> GuardDecision {
66        let pattern_hash = self.calculate_pattern_hash(memory);
67        let repetition_score = self.calculate_repetition_score(pattern_hash);
68
69        if repetition_score < self.safe_threshold {
70            GuardDecision::Allow
71        } else if repetition_score < self.critical_threshold {
72            GuardDecision::Throttle(self.calculate_throttle_factor(repetition_score))
73        } else {
74            GuardDecision::Block(BlockReason::ExcessiveRepetition)
75        }
76    }
77
78    /// Calculate hash for memory pattern
79    fn calculate_pattern_hash(&self, memory: &MemoryWave) -> u64 {
80        use std::collections::hash_map::DefaultHasher;
81        use std::hash::{Hash, Hasher};
82
83        let mut hasher = DefaultHasher::new();
84
85        // Hash key characteristics
86        ((memory.frequency * 100.0) as u32).hash(&mut hasher);
87        ((memory.amplitude * 100.0) as u32).hash(&mut hasher);
88        ((memory.valence * 100.0) as i32).hash(&mut hasher);
89
90        hasher.finish()
91    }
92
93    /// Calculate repetition score for a pattern
94    fn calculate_repetition_score(&self, pattern_hash: u64) -> f32 {
95        let mut history = self.pattern_history.write().unwrap();
96        let now = Instant::now();
97
98        let tracker = history
99            .entry(pattern_hash)
100            .or_insert_with(|| PatternTracker {
101                hash: pattern_hash,
102                count: 0,
103                last_seen: now,
104                intervals: VecDeque::with_capacity(10),
105            });
106
107        // Update tracker
108        let interval = now.duration_since(tracker.last_seen);
109        tracker.intervals.push_back(interval);
110        if tracker.intervals.len() > 10 {
111            tracker.intervals.pop_front();
112        }
113        tracker.count += 1;
114        tracker.last_seen = now;
115
116        // Calculate score based on frequency and interval pattern
117        let frequency_factor = tracker.count as f32 / 10.0;
118        let interval_factor = if tracker.intervals.len() > 1 {
119            let avg_interval = tracker
120                .intervals
121                .iter()
122                .map(|d| d.as_secs_f32())
123                .sum::<f32>()
124                / tracker.intervals.len() as f32;
125
126            // Penalize rapid repetition
127            (1.0 / (avg_interval + 0.1)).min(10.0)
128        } else {
129            1.0
130        };
131
132        frequency_factor * interval_factor
133    }
134
135    /// Calculate throttle factor based on repetition score
136    fn calculate_throttle_factor(&self, score: f32) -> f32 {
137        let normalized =
138            (score - self.safe_threshold) / (self.critical_threshold - self.safe_threshold);
139        normalized.clamp(0.1, 0.9)
140    }
141
142    /// Check resource limits
143    pub fn check_resources(&self, active_count: usize, growth_rate: f32) -> GuardDecision {
144        if active_count > self.resource_limits.max_active_memories {
145            GuardDecision::Block(BlockReason::MemoryOverload)
146        } else if growth_rate > self.resource_limits.max_growth_rate {
147            GuardDecision::Throttle(0.5)
148        } else {
149            GuardDecision::Allow
150        }
151    }
152}
153
154/// Guard decision types
155#[derive(Debug, Clone)]
156pub enum GuardDecision {
157    /// Allow memory operation
158    Allow,
159    /// Throttle with factor (0.0 to 1.0)
160    Throttle(f32),
161    /// Block operation with reason
162    Block(BlockReason),
163}
164
165/// Reasons for blocking memory operations
166#[derive(Debug, Clone)]
167pub enum BlockReason {
168    ExcessiveRepetition,
169    MemoryOverload,
170    CognitiveLoop,
171    ResourceExhaustion,
172}
173
174/// Repetition poisoning prevention system
175pub struct RepetitionPrevention {
176    /// Pattern breaking threshold
177    break_threshold: f32,
178    /// Pattern history
179    patterns: RwLock<Vec<PatternInstance>>,
180    /// Noise generator for pattern breaking
181    noise_level: f32,
182}
183
184#[derive(Clone)]
185struct PatternInstance {
186    pattern: Vec<f32>,
187    repeat_count: usize,
188    last_seen: Instant,
189}
190
191impl Default for RepetitionPrevention {
192    fn default() -> Self {
193        Self::new()
194    }
195}
196
197impl RepetitionPrevention {
198    pub fn new() -> Self {
199        Self {
200            break_threshold: 0.8,
201            patterns: RwLock::new(Vec::new()),
202            noise_level: 0.1,
203        }
204    }
205
206    /// Check if pattern breaking is needed
207    pub fn check_pattern(&self, wave_sequence: &[f32]) -> PatternBreakDecision {
208        let mut patterns = self.patterns.write().unwrap();
209
210        // Look for matching patterns
211        for pattern in patterns.iter_mut() {
212            if self.patterns_match(&pattern.pattern, wave_sequence) {
213                pattern.repeat_count += 1;
214                pattern.last_seen = Instant::now();
215
216                // Calculate break probability
217                let p_break = self.calculate_break_probability(pattern.repeat_count);
218
219                if p_break > self.break_threshold {
220                    return PatternBreakDecision::BreakPattern {
221                        noise_level: self.noise_level,
222                        shift_attention: true,
223                        suppress_duration: Duration::from_secs(5),
224                    };
225                }
226            }
227        }
228
229        // Add new pattern
230        patterns.push(PatternInstance {
231            pattern: wave_sequence.to_vec(),
232            repeat_count: 1,
233            last_seen: Instant::now(),
234        });
235
236        // Clean old patterns
237        patterns.retain(|p| p.last_seen.elapsed() < Duration::from_secs(300));
238
239        PatternBreakDecision::Continue
240    }
241
242    /// Check if two patterns match
243    fn patterns_match(&self, p1: &[f32], p2: &[f32]) -> bool {
244        if p1.len() != p2.len() {
245            return false;
246        }
247
248        let tolerance = 0.1;
249        p1.iter()
250            .zip(p2.iter())
251            .all(|(a, b)| (a - b).abs() < tolerance)
252    }
253
254    /// Calculate probability of breaking pattern
255    fn calculate_break_probability(&self, repeat_count: usize) -> f32 {
256        let threshold_count = 5.0;
257        let lambda = 0.5;
258
259        if repeat_count as f32 <= threshold_count {
260            0.0
261        } else {
262            let excess = repeat_count as f32 - threshold_count;
263            1.0 - (-lambda * excess * excess).exp()
264        }
265    }
266}
267
268/// Decision on pattern breaking
269#[derive(Debug)]
270pub enum PatternBreakDecision {
271    /// Continue normal processing
272    Continue,
273    /// Break the pattern
274    BreakPattern {
275        noise_level: f32,
276        shift_attention: bool,
277        suppress_duration: Duration,
278    },
279}
280
281/// High-emotional memory reintroduction system
282pub struct EmotionalMemoryTherapy {
283    /// Target emotional level
284    target_emotional_level: f32,
285    /// Therapy time constant
286    therapy_tau: Duration,
287    /// Safety bounds
288    max_amplification: f32,
289    /// Active therapy sessions
290    sessions: RwLock<HashMap<u64, TherapySession>>,
291}
292
293struct TherapySession {
294    memory_id: u64,
295    start_time: Instant,
296    initial_amplitude: f32,
297    target_amplitude: f32,
298    current_phase: TherapyPhase,
299}
300
301#[derive(Debug, Clone)]
302enum TherapyPhase {
303    Assessment,
304    GradualExposure,
305    Integration,
306    Resolution,
307}
308
309impl Default for EmotionalMemoryTherapy {
310    fn default() -> Self {
311        Self::new()
312    }
313}
314
315impl EmotionalMemoryTherapy {
316    pub fn new() -> Self {
317        Self {
318            target_emotional_level: 0.7,
319            therapy_tau: Duration::from_secs(300),
320            max_amplification: 2.0,
321            sessions: RwLock::new(HashMap::new()),
322        }
323    }
324
325    /// Calculate reintroduction amplitude for therapeutic processing
326    pub fn calculate_reintroduction(&self, memory: &MemoryWave, memory_id: u64) -> f32 {
327        let mut sessions = self.sessions.write().unwrap();
328
329        let session = sessions.entry(memory_id).or_insert_with(|| TherapySession {
330            memory_id,
331            start_time: Instant::now(),
332            initial_amplitude: memory.amplitude,
333            target_amplitude: memory.amplitude * self.target_emotional_level,
334            current_phase: TherapyPhase::Assessment,
335        });
336
337        let elapsed = session.start_time.elapsed().as_secs_f32();
338        let tau = self.therapy_tau.as_secs_f32();
339
340        // Graduated exposure formula
341        let base_amplitude = session.initial_amplitude;
342        let exposure_factor = 1.0 - (-elapsed / tau).exp();
343        let emotion_ratio =
344            (self.target_emotional_level / memory.arousal.max(0.1)).min(self.max_amplification);
345
346        base_amplitude * exposure_factor * emotion_ratio
347    }
348
349    /// Check if memory needs therapeutic reintroduction
350    pub fn needs_therapy(&self, memory: &MemoryWave) -> bool {
351        // High emotional content with potential for blocking
352        memory.arousal > 0.8 && memory.valence.abs() > 0.7
353    }
354
355    /// Update therapy phase
356    pub fn update_phase(&self, memory_id: u64, processing_success: bool) {
357        let mut sessions = self.sessions.write().unwrap();
358
359        if let Some(session) = sessions.get_mut(&memory_id) {
360            session.current_phase = match (&session.current_phase, processing_success) {
361                (TherapyPhase::Assessment, true) => TherapyPhase::GradualExposure,
362                (TherapyPhase::GradualExposure, true) => TherapyPhase::Integration,
363                (TherapyPhase::Integration, true) => TherapyPhase::Resolution,
364                (TherapyPhase::Resolution, _) => {
365                    // Therapy complete, remove session
366                    sessions.remove(&memory_id);
367                    return;
368                }
369                _ => session.current_phase.clone(), // No phase change on failure
370            };
371        }
372    }
373}
374
375/// Temporal blanket reintroduction for memory recovery
376pub struct TemporalBlanketRecovery {
377    /// Suppression history
378    suppression_history: RwLock<HashMap<u64, SuppressionRecord>>,
379    /// Recovery parameters
380    alpha: f32,
381    beta: f32,
382}
383
384struct SuppressionRecord {
385    memory_id: u64,
386    suppression_time: Instant,
387    original_blanket: f32,
388    suppression_reason: String,
389}
390
391impl Default for TemporalBlanketRecovery {
392    fn default() -> Self {
393        Self::new()
394    }
395}
396
397impl TemporalBlanketRecovery {
398    pub fn new() -> Self {
399        Self {
400            suppression_history: RwLock::new(HashMap::new()),
401            alpha: 0.1, // Decay rate for suppression
402            beta: 0.5,  // Need-based amplification
403        }
404    }
405
406    /// Record memory suppression
407    pub fn record_suppression(&self, memory_id: u64, original_blanket: f32, reason: String) {
408        let mut history = self.suppression_history.write().unwrap();
409
410        history.insert(
411            memory_id,
412            SuppressionRecord {
413                memory_id,
414                suppression_time: Instant::now(),
415                original_blanket,
416                suppression_reason: reason,
417            },
418        );
419    }
420
421    /// Calculate restored temporal blanket value
422    pub fn restore_blanket(&self, memory_id: u64, contextual_need: f32) -> Option<f32> {
423        let history = self.suppression_history.read().unwrap();
424
425        if let Some(record) = history.get(&memory_id) {
426            let elapsed = record.suppression_time.elapsed().as_secs_f32();
427
428            // Restoration formula from paper
429            let decay_factor = (-self.alpha * elapsed).exp();
430            let need_factor = self.beta * contextual_need;
431
432            let restored = record.original_blanket * decay_factor + need_factor;
433
434            Some(restored.clamp(0.0, 1.0))
435        } else {
436            None
437        }
438    }
439
440    /// Check if memory should be restored
441    pub fn should_restore(&self, memory_id: u64, contextual_importance: f32) -> bool {
442        let history = self.suppression_history.read().unwrap();
443
444        if let Some(record) = history.get(&memory_id) {
445            // Restore if sufficient time has passed and context demands it
446            let min_suppression_time = Duration::from_secs(60);
447            record.suppression_time.elapsed() > min_suppression_time && contextual_importance > 0.7
448        } else {
449            false
450        }
451    }
452}
453
454/// Divergence tracking for anomaly detection
455pub struct DivergenceTracker {
456    /// Baseline measurements
457    baseline: RwLock<SystemBaseline>,
458    /// Current measurements
459    current: RwLock<SystemMeasurement>,
460    /// Divergence thresholds
461    thresholds: DivergenceThresholds,
462}
463
464#[derive(Clone)]
465struct SystemBaseline {
466    relationship_values: HashMap<String, f32>,
467    activity_levels: HashMap<String, f32>,
468    emotional_state: EmotionalBaseline,
469    established_at: Instant,
470}
471
472#[derive(Clone)]
473pub struct SystemMeasurement {
474    pub relationship_values: HashMap<String, f32>,
475    pub activity_levels: HashMap<String, f32>,
476    pub emotional_state: EmotionalState,
477    pub measured_at: Instant,
478}
479
480#[derive(Clone)]
481struct EmotionalBaseline {
482    valence: f32,
483    arousal: f32,
484    coherence: f32,
485}
486
487#[derive(Clone)]
488pub struct EmotionalState {
489    pub valence: f32,
490    pub arousal: f32,
491    pub coherence: f32,
492    pub divergence: f32,
493}
494
495struct DivergenceThresholds {
496    normal_max: f32,    // 0-50
497    unusual_max: f32,   // 51-150
498    high_risk_min: f32, // 151-255
499}
500
501impl Default for DivergenceTracker {
502    fn default() -> Self {
503        Self::new()
504    }
505}
506
507impl DivergenceTracker {
508    pub fn new() -> Self {
509        Self {
510            baseline: RwLock::new(SystemBaseline {
511                relationship_values: HashMap::new(),
512                activity_levels: HashMap::new(),
513                emotional_state: EmotionalBaseline {
514                    valence: 0.0,
515                    arousal: 0.5,
516                    coherence: 0.8,
517                },
518                established_at: Instant::now(),
519            }),
520            current: RwLock::new(SystemMeasurement {
521                relationship_values: HashMap::new(),
522                activity_levels: HashMap::new(),
523                emotional_state: EmotionalState {
524                    valence: 0.0,
525                    arousal: 0.5,
526                    coherence: 0.8,
527                    divergence: 0.0,
528                },
529                measured_at: Instant::now(),
530            }),
531            thresholds: DivergenceThresholds {
532                normal_max: 50.0,
533                unusual_max: 150.0,
534                high_risk_min: 151.0,
535            },
536        }
537    }
538
539    /// Calculate divergence score (0-255)
540    pub fn calculate_divergence(&self) -> u8 {
541        let baseline = self.baseline.read().unwrap();
542        let current = self.current.read().unwrap();
543
544        let mut total_divergence = 0.0;
545
546        // Relationship divergence
547        for (key, baseline_val) in &baseline.relationship_values {
548            if let Some(current_val) = current.relationship_values.get(key) {
549                let r_diff = (current_val - baseline_val).abs();
550                total_divergence += 2.0 * r_diff;
551            }
552        }
553
554        // Activity divergence
555        for (key, baseline_val) in &baseline.activity_levels {
556            if let Some(current_val) = current.activity_levels.get(key) {
557                let a_diff = (current_val - baseline_val).abs();
558                total_divergence += a_diff;
559            }
560        }
561
562        // Emotional divergence
563        let e_diff = ((current.emotional_state.valence - baseline.emotional_state.valence).abs()
564            + (current.emotional_state.arousal - baseline.emotional_state.arousal).abs()
565            + (baseline.emotional_state.coherence - current.emotional_state.coherence).abs())
566            / 3.0;
567
568        total_divergence += e_diff * 50.0;
569
570        total_divergence.min(255.0) as u8
571    }
572
573    /// Get divergence category
574    pub fn get_divergence_category(&self) -> DivergenceCategory {
575        let score = self.calculate_divergence();
576
577        match score {
578            0..=50 => DivergenceCategory::Normal,
579            51..=150 => DivergenceCategory::Unusual,
580            151..=255 => DivergenceCategory::HighRisk,
581        }
582    }
583
584    /// Update measurement
585    pub fn update_measurement(&self, measurement: SystemMeasurement) {
586        let mut current = self.current.write().unwrap();
587        *current = measurement;
588    }
589
590    /// Reset baseline
591    pub fn reset_baseline(&self) {
592        let current = self.current.read().unwrap();
593        let mut baseline = self.baseline.write().unwrap();
594
595        baseline.relationship_values = current.relationship_values.clone();
596        baseline.activity_levels = current.activity_levels.clone();
597        baseline.emotional_state = EmotionalBaseline {
598            valence: current.emotional_state.valence,
599            arousal: current.emotional_state.arousal,
600            coherence: current.emotional_state.coherence,
601        };
602        baseline.established_at = Instant::now();
603    }
604}
605
606#[derive(Debug, Clone)]
607pub enum DivergenceCategory {
608    Normal,   // Safe variance
609    Unusual,  // Monitoring required
610    HighRisk, // Immediate intervention
611}
612
613/// Collective emotional state tracker
614pub struct CollectiveEmotionalIntelligence {
615    /// Individual emotional states
616    individuals: RwLock<HashMap<String, IndividualState>>,
617    /// Group psychological safety threshold
618    safety_threshold: f32,
619    /// Harmony calculator
620    harmony_weights: HarmonyWeights,
621}
622
623#[derive(Clone)]
624struct IndividualState {
625    id: String,
626    emotional_state: EmotionalState,
627    safety_level: f32,
628    trust_coefficient: f32,
629    last_update: Instant,
630}
631
632struct HarmonyWeights {
633    emotional_resonance: f32, // 0.3
634    interaction_pattern: f32, // 0.25
635    trust_coefficient: f32,   // 0.25
636    adaptation_rate: f32,     // 0.2
637}
638
639impl Default for CollectiveEmotionalIntelligence {
640    fn default() -> Self {
641        Self::new()
642    }
643}
644
645impl CollectiveEmotionalIntelligence {
646    pub fn new() -> Self {
647        Self {
648            individuals: RwLock::new(HashMap::new()),
649            safety_threshold: 200.0 / 255.0, // From paper
650            harmony_weights: HarmonyWeights {
651                emotional_resonance: 0.3,
652                interaction_pattern: 0.25,
653                trust_coefficient: 0.25,
654                adaptation_rate: 0.2,
655            },
656        }
657    }
658
659    /// Calculate collective emotional state
660    pub fn calculate_collective_state(&self) -> CollectiveState {
661        let individuals = self.individuals.read().unwrap();
662
663        if individuals.is_empty() {
664            return CollectiveState::default();
665        }
666
667        // Calculate average emotional state
668        let mut total_valence = 0.0;
669        let mut total_arousal = 0.0;
670        let mut min_safety: f32 = 1.0;
671
672        for individual in individuals.values() {
673            total_valence += individual.emotional_state.valence;
674            total_arousal += individual.emotional_state.arousal;
675            min_safety = min_safety.min(individual.safety_level);
676        }
677
678        let n = individuals.len() as f32;
679        let avg_valence = total_valence / n;
680        let avg_arousal = total_arousal / n;
681
682        // Apply minimum safety as limiting factor (from paper)
683        let collective_emotion = (avg_valence * min_safety, avg_arousal * min_safety);
684
685        CollectiveState {
686            emotional_valence: collective_emotion.0,
687            emotional_arousal: collective_emotion.1,
688            psychological_safety: min_safety,
689            group_size: individuals.len(),
690            harmony_score: self.calculate_harmony(),
691        }
692    }
693
694    /// Calculate group harmony score
695    fn calculate_harmony(&self) -> f32 {
696        let individuals = self.individuals.read().unwrap();
697
698        if individuals.len() < 2 {
699            return 1.0; // Perfect harmony with self
700        }
701
702        // Calculate components
703        let emotional_resonance = self.calculate_emotional_resonance(&individuals);
704        let interaction_quality = 0.8; // Placeholder - would track actual interactions
705        let avg_trust = individuals
706            .values()
707            .map(|i| i.trust_coefficient)
708            .sum::<f32>()
709            / individuals.len() as f32;
710        let adaptation_rate = 0.7; // Placeholder - would track learning rate
711
712        // Weighted harmony score
713        self.harmony_weights.emotional_resonance * emotional_resonance
714            + self.harmony_weights.interaction_pattern * interaction_quality
715            + self.harmony_weights.trust_coefficient * avg_trust
716            + self.harmony_weights.adaptation_rate * adaptation_rate
717    }
718
719    /// Calculate emotional resonance between individuals
720    fn calculate_emotional_resonance(&self, individuals: &HashMap<String, IndividualState>) -> f32 {
721        let states: Vec<_> = individuals.values().collect();
722        let n = states.len();
723
724        if n < 2 {
725            return 1.0;
726        }
727
728        let mut total_similarity = 0.0;
729        let mut pairs = 0;
730
731        for i in 0..n {
732            for j in i + 1..n {
733                let valence_diff =
734                    (states[i].emotional_state.valence - states[j].emotional_state.valence).abs();
735                let arousal_diff =
736                    (states[i].emotional_state.arousal - states[j].emotional_state.arousal).abs();
737
738                let similarity = 1.0 - (valence_diff + arousal_diff) / 2.0;
739                total_similarity += similarity;
740                pairs += 1;
741            }
742        }
743
744        total_similarity / pairs as f32
745    }
746
747    /// Update individual state
748    pub fn update_individual(
749        &self,
750        id: String,
751        emotional_state: EmotionalState,
752        safety_level: f32,
753    ) {
754        let mut individuals = self.individuals.write().unwrap();
755
756        if let Some(individual) = individuals.get_mut(&id) {
757            individual.emotional_state = emotional_state;
758            individual.safety_level = safety_level;
759            individual.last_update = Instant::now();
760
761            // Update trust coefficient based on consistency
762            individual.trust_coefficient = (individual.trust_coefficient * 0.9 + 0.1).min(1.0);
763        } else {
764            individuals.insert(
765                id.clone(),
766                IndividualState {
767                    id,
768                    emotional_state,
769                    safety_level,
770                    trust_coefficient: 0.5, // Start at neutral trust
771                    last_update: Instant::now(),
772                },
773            );
774        }
775    }
776
777    /// Check if psychological safety is maintained
778    pub fn is_psychologically_safe(&self) -> bool {
779        let collective = self.calculate_collective_state();
780        collective.psychological_safety >= self.safety_threshold
781    }
782}
783
784#[derive(Debug, Default)]
785pub struct CollectiveState {
786    pub emotional_valence: f32,
787    pub emotional_arousal: f32,
788    pub psychological_safety: f32,
789    pub group_size: usize,
790    pub harmony_score: f32,
791}
792
793/// Integrated safety system combining all mechanisms
794pub struct SafetySystem {
795    pub custodian: Arc<Custodian>,
796    pub repetition_prevention: Arc<RepetitionPrevention>,
797    pub emotional_therapy: Arc<EmotionalMemoryTherapy>,
798    pub temporal_recovery: Arc<TemporalBlanketRecovery>,
799    pub divergence_tracker: Arc<DivergenceTracker>,
800    pub collective_intelligence: Arc<CollectiveEmotionalIntelligence>,
801}
802
803impl Default for SafetySystem {
804    fn default() -> Self {
805        Self::new()
806    }
807}
808
809impl SafetySystem {
810    pub fn new() -> Self {
811        Self {
812            custodian: Arc::new(Custodian::new()),
813            repetition_prevention: Arc::new(RepetitionPrevention::new()),
814            emotional_therapy: Arc::new(EmotionalMemoryTherapy::new()),
815            temporal_recovery: Arc::new(TemporalBlanketRecovery::new()),
816            divergence_tracker: Arc::new(DivergenceTracker::new()),
817            collective_intelligence: Arc::new(CollectiveEmotionalIntelligence::new()),
818        }
819    }
820
821    /// Comprehensive safety check for memory operations
822    pub fn check_memory_safety(&self, memory: &MemoryWave, memory_id: u64) -> SafetyAssessment {
823        // Check with Custodian
824        let guard_decision = self.custodian.guard_memory(memory);
825
826        // Check divergence
827        let divergence = self.divergence_tracker.get_divergence_category();
828
829        // Check collective safety
830        let collectively_safe = self.collective_intelligence.is_psychologically_safe();
831
832        // Check if therapeutic intervention needed
833        let needs_therapy = self.emotional_therapy.needs_therapy(memory);
834
835        SafetyAssessment {
836            guard_decision,
837            divergence_category: divergence,
838            collectively_safe,
839            needs_therapy,
840            recommendations: self.generate_recommendations(memory, memory_id),
841        }
842    }
843
844    /// Generate safety recommendations
845    fn generate_recommendations(
846        &self,
847        memory: &MemoryWave,
848        memory_id: u64,
849    ) -> Vec<SafetyRecommendation> {
850        let mut recommendations = Vec::new();
851
852        // Check if memory was previously suppressed
853        if self
854            .temporal_recovery
855            .should_restore(memory_id, memory.amplitude)
856        {
857            recommendations.push(SafetyRecommendation::RestoreSuppressedMemory);
858        }
859
860        // Check if pattern breaking needed
861        let pattern_check = self
862            .repetition_prevention
863            .check_pattern(&[memory.frequency, memory.amplitude]);
864        if matches!(pattern_check, PatternBreakDecision::BreakPattern { .. }) {
865            recommendations.push(SafetyRecommendation::InjectNoiseToBreakPattern);
866        }
867
868        // Check if emotional therapy needed
869        if memory.arousal > 0.9 && memory.valence.abs() > 0.8 {
870            recommendations.push(SafetyRecommendation::ApplyGraduatedExposure);
871        }
872
873        recommendations
874    }
875}
876
877#[derive(Debug)]
878pub struct SafetyAssessment {
879    pub guard_decision: GuardDecision,
880    pub divergence_category: DivergenceCategory,
881    pub collectively_safe: bool,
882    pub needs_therapy: bool,
883    pub recommendations: Vec<SafetyRecommendation>,
884}
885
886#[derive(Debug, Clone)]
887pub enum SafetyRecommendation {
888    RestoreSuppressedMemory,
889    InjectNoiseToBreakPattern,
890    ApplyGraduatedExposure,
891    ReduceSystemLoad,
892    IncreaseMonitoring,
893}
894
895#[cfg(test)]
896mod tests {
897    use super::*;
898
899    #[test]
900    fn test_custodian_repetition_detection() {
901        let custodian = Custodian::new();
902        let mut wave = MemoryWave::new(440.0, 0.8);
903        wave.valence = 0.5;
904
905        // First access should be allowed
906        match custodian.guard_memory(&wave) {
907            GuardDecision::Allow => {}
908            _ => panic!("First access should be allowed"),
909        }
910
911        // Multiple rapid accesses should trigger throttling
912        for _ in 0..10 {
913            let _ = custodian.guard_memory(&wave);
914        }
915
916        match custodian.guard_memory(&wave) {
917            GuardDecision::Throttle(_) | GuardDecision::Block(_) => {}
918            GuardDecision::Allow => panic!("Repetitive access should be throttled or blocked"),
919        }
920    }
921
922    #[test]
923    fn test_pattern_breaking() {
924        let prevention = RepetitionPrevention::new();
925        let pattern = vec![440.0, 0.8, 440.0, 0.8];
926
927        // Repeated patterns should trigger breaking
928        for _ in 0..10 {
929            let decision = prevention.check_pattern(&pattern);
930            if matches!(decision, PatternBreakDecision::BreakPattern { .. }) {
931                return; // Test passed
932            }
933        }
934
935        panic!("Pattern breaking should have been triggered");
936    }
937
938    #[test]
939    fn test_emotional_therapy() {
940        // Create therapy with shorter tau for testing
941        let mut therapy = EmotionalMemoryTherapy::new();
942        therapy.therapy_tau = std::time::Duration::from_millis(100); // Short tau for test
943
944        let mut wave = MemoryWave::new(600.0, 0.9);
945        wave.arousal = 0.9;
946        wave.valence = -0.8;
947
948        assert!(therapy.needs_therapy(&wave));
949
950        // Wait for exposure to ramp up
951        std::thread::sleep(std::time::Duration::from_millis(50));
952
953        let reintro = therapy.calculate_reintroduction(&wave, 123);
954        assert!(reintro > 0.0, "reintro was {}", reintro);
955        assert!(reintro <= wave.amplitude * therapy.max_amplification);
956    }
957
958    #[test]
959    fn test_divergence_tracking() {
960        let tracker = DivergenceTracker::new();
961
962        // Initial divergence should be minimal
963        assert!(matches!(
964            tracker.get_divergence_category(),
965            DivergenceCategory::Normal
966        ));
967
968        // Update with divergent measurement
969        let mut measurement = SystemMeasurement {
970            relationship_values: HashMap::new(),
971            activity_levels: HashMap::new(),
972            emotional_state: EmotionalState {
973                valence: 0.9, // High divergence from baseline
974                arousal: 0.9,
975                coherence: 0.2,
976                divergence: 0.0,
977            },
978            measured_at: Instant::now(),
979        };
980
981        measurement
982            .relationship_values
983            .insert("test".to_string(), 0.9);
984        measurement.activity_levels.insert("test".to_string(), 0.9);
985
986        tracker.update_measurement(measurement);
987
988        let divergence = tracker.calculate_divergence();
989        assert!(divergence > 0);
990    }
991
992    #[test]
993    fn test_collective_emotional_intelligence() {
994        let cei = CollectiveEmotionalIntelligence::new();
995
996        // Add individuals
997        cei.update_individual(
998            "user1".to_string(),
999            EmotionalState {
1000                valence: 0.5,
1001                arousal: 0.6,
1002                coherence: 0.8,
1003                divergence: 0.0,
1004            },
1005            0.9,
1006        );
1007
1008        cei.update_individual(
1009            "user2".to_string(),
1010            EmotionalState {
1011                valence: 0.4,
1012                arousal: 0.5,
1013                coherence: 0.7,
1014                divergence: 0.0,
1015            },
1016            0.85,
1017        );
1018
1019        let collective = cei.calculate_collective_state();
1020        assert_eq!(collective.group_size, 2);
1021        assert!(collective.psychological_safety > 0.0);
1022        assert!(collective.harmony_score > 0.0);
1023    }
1024}