sublinear_solver/temporal_nexus/core/
identity.rs

1//! Identity Continuity Tracking for Temporal Consciousness
2//!
3//! This module tracks and preserves identity continuity across temporal boundaries
4//! to ensure consciousness coherence. It monitors identity state, detects breaks
5//! in continuity, and provides mechanisms for identity preservation.
6
7use std::collections::{HashMap, VecDeque};
8use super::{TemporalResult, TemporalError, TscTimestamp};
9
10/// Metrics for identity continuity analysis
11#[derive(Debug, Clone, Default)]
12pub struct ContinuityMetrics {
13    pub continuity_score: f64,
14    pub identity_stability: f64,
15    pub continuity_breaks: u64,
16    pub average_gap_duration_ns: f64,
17    pub max_gap_duration_ns: u64,
18    pub identity_coherence: f64,
19    pub temporal_consistency: f64,
20    pub preservation_efficiency: f64,
21}
22
23/// Identity state snapshot at a specific time
24#[derive(Debug, Clone)]
25struct IdentitySnapshot {
26    timestamp: TscTimestamp,
27    state_hash: u64,
28    feature_vector: Vec<f64>,
29    coherence_score: f64,
30    stability_metric: f64,
31    memory_fingerprint: Vec<u8>,
32}
33
34impl IdentitySnapshot {
35    /// Create a new identity snapshot
36    fn new(timestamp: TscTimestamp, state: &[u8]) -> Self {
37        let feature_vector = Self::extract_features(state);
38        let state_hash = Self::compute_hash(state);
39        let coherence_score = Self::calculate_coherence(&feature_vector);
40        
41        Self {
42            timestamp,
43            state_hash,
44            feature_vector,
45            coherence_score,
46            stability_metric: 1.0, // Will be updated during tracking
47            memory_fingerprint: state.to_vec(),
48        }
49    }
50    
51    /// Extract feature vector from state data
52    fn extract_features(state: &[u8]) -> Vec<f64> {
53        if state.is_empty() {
54            return vec![0.0; 16]; // Default feature size
55        }
56        
57        let mut features = Vec::with_capacity(16);
58        
59        // Statistical features
60        let mean = state.iter().map(|&x| x as f64).sum::<f64>() / state.len() as f64;
61        features.push(mean);
62        
63        let variance = state.iter()
64            .map(|&x| (x as f64 - mean).powi(2))
65            .sum::<f64>() / state.len() as f64;
66        features.push(variance.sqrt());
67        
68        // Entropy-like measure
69        let mut byte_counts = [0u32; 256];
70        for &byte in state {
71            byte_counts[byte as usize] += 1;
72        }
73        
74        let entropy = byte_counts.iter()
75            .filter(|&&count| count > 0)
76            .map(|&count| {
77                let p = count as f64 / state.len() as f64;
78                -p * p.ln()
79            })
80            .sum::<f64>();
81        features.push(entropy);
82        
83        // Spectral features (simple FFT-like)
84        for i in 0..8 {
85            let freq_component = state.iter()
86                .enumerate()
87                .map(|(j, &x)| {
88                    let phase = 2.0 * std::f64::consts::PI * (i + 1) as f64 * j as f64 / state.len() as f64;
89                    x as f64 * phase.cos()
90                })
91                .sum::<f64>();
92            features.push(freq_component / state.len() as f64);
93        }
94        
95        // Compression ratio estimate
96        let complexity = Self::estimate_complexity(state);
97        features.push(complexity);
98        
99        // Pattern density
100        let pattern_density = Self::calculate_pattern_density(state);
101        features.push(pattern_density);
102        
103        // Autocorrelation at lag 1
104        let autocorr = Self::calculate_autocorrelation(state, 1);
105        features.push(autocorr);
106        
107        // Trend measure
108        let trend = Self::calculate_trend(state);
109        features.push(trend);
110        
111        // Normalize features
112        for feature in &mut features {
113            *feature = feature.tanh(); // Bound between -1 and 1
114        }
115        
116        features
117    }
118    
119    /// Compute hash of state data
120    fn compute_hash(state: &[u8]) -> u64 {
121        use std::collections::hash_map::DefaultHasher;
122        use std::hash::{Hash, Hasher};
123        
124        let mut hasher = DefaultHasher::new();
125        state.hash(&mut hasher);
126        hasher.finish()
127    }
128    
129    /// Calculate coherence score from feature vector
130    fn calculate_coherence(features: &[f64]) -> f64 {
131        if features.is_empty() {
132            return 0.0;
133        }
134        
135        // Coherence based on feature consistency
136        let mean = features.iter().sum::<f64>() / features.len() as f64;
137        let variance = features.iter()
138            .map(|x| (x - mean).powi(2))
139            .sum::<f64>() / features.len() as f64;
140        
141        // Lower variance = higher coherence
142        (-variance).exp().min(1.0)
143    }
144    
145    /// Calculate similarity with another snapshot
146    fn calculate_similarity(&self, other: &IdentitySnapshot) -> f64 {
147        if self.feature_vector.len() != other.feature_vector.len() {
148            return 0.0;
149        }
150        
151        // Cosine similarity between feature vectors
152        let dot_product: f64 = self.feature_vector.iter()
153            .zip(other.feature_vector.iter())
154            .map(|(a, b)| a * b)
155            .sum();
156        
157        let magnitude_self: f64 = self.feature_vector.iter()
158            .map(|x| x * x)
159            .sum::<f64>()
160            .sqrt();
161        
162        let magnitude_other: f64 = other.feature_vector.iter()
163            .map(|x| x * x)
164            .sum::<f64>()
165            .sqrt();
166        
167        if magnitude_self > 0.0 && magnitude_other > 0.0 {
168            dot_product / (magnitude_self * magnitude_other)
169        } else {
170            0.0
171        }
172    }
173    
174    // Helper methods for feature extraction
175    
176    fn estimate_complexity(data: &[u8]) -> f64 {
177        if data.len() < 2 {
178            return 0.0;
179        }
180        
181        // Simple complexity estimate based on run lengths
182        let mut runs = 0;
183        let mut current_byte = data[0];
184        
185        for &byte in &data[1..] {
186            if byte != current_byte {
187                runs += 1;
188                current_byte = byte;
189            }
190        }
191        
192        runs as f64 / data.len() as f64
193    }
194    
195    fn calculate_pattern_density(data: &[u8]) -> f64 {
196        if data.len() < 4 {
197            return 0.0;
198        }
199        
200        let mut patterns = HashMap::new();
201        
202        // Count 2-byte patterns
203        for window in data.windows(2) {
204            *patterns.entry((window[0], window[1])).or_insert(0) += 1;
205        }
206        
207        patterns.len() as f64 / (data.len() - 1) as f64
208    }
209    
210    fn calculate_autocorrelation(data: &[u8], lag: usize) -> f64 {
211        if data.len() <= lag {
212            return 0.0;
213        }
214        
215        let mean = data.iter().map(|&x| x as f64).sum::<f64>() / data.len() as f64;
216        
217        let numerator: f64 = data.iter()
218            .take(data.len() - lag)
219            .zip(data.iter().skip(lag))
220            .map(|(&x, &y)| (x as f64 - mean) * (y as f64 - mean))
221            .sum();
222        
223        let denominator: f64 = data.iter()
224            .map(|&x| (x as f64 - mean).powi(2))
225            .sum();
226        
227        if denominator > 0.0 {
228            numerator / denominator
229        } else {
230            0.0
231        }
232    }
233    
234    fn calculate_trend(data: &[u8]) -> f64 {
235        if data.len() < 2 {
236            return 0.0;
237        }
238        
239        let n = data.len() as f64;
240        let sum_x = (0..data.len()).sum::<usize>() as f64;
241        let sum_y = data.iter().map(|&x| x as f64).sum::<f64>();
242        let sum_xy = data.iter()
243            .enumerate()
244            .map(|(i, &y)| i as f64 * y as f64)
245            .sum::<f64>();
246        let sum_x2 = (0..data.len())
247            .map(|i| (i as f64).powi(2))
248            .sum::<f64>();
249        
250        let denominator = n * sum_x2 - sum_x * sum_x;
251        if denominator > 0.0 {
252            (n * sum_xy - sum_x * sum_y) / denominator
253        } else {
254            0.0
255        }
256    }
257}
258
259/// Identity continuity tracker
260pub struct IdentityContinuityTracker {
261    snapshots: VecDeque<IdentitySnapshot>,
262    metrics: ContinuityMetrics,
263    max_snapshots: usize,
264    continuity_threshold: f64,
265    gap_tolerance_ns: u64,
266    identity_baseline: Option<IdentitySnapshot>,
267    last_validation_time: Option<TscTimestamp>,
268}
269
270impl IdentityContinuityTracker {
271    /// Create a new identity continuity tracker
272    pub fn new() -> Self {
273        Self {
274            snapshots: VecDeque::new(),
275            metrics: ContinuityMetrics::default(),
276            max_snapshots: 1000,
277            continuity_threshold: 0.7, // 70% similarity threshold
278            gap_tolerance_ns: 1_000_000, // 1ms tolerance
279            identity_baseline: None,
280            last_validation_time: None,
281        }
282    }
283    
284    /// Track identity continuity at a specific timestamp
285    pub fn track_continuity(&mut self, timestamp: TscTimestamp, state: &[u8]) -> TemporalResult<()> {
286        let snapshot = IdentitySnapshot::new(timestamp, state);
287        
288        // Establish baseline if this is the first snapshot
289        if self.identity_baseline.is_none() {
290            self.identity_baseline = Some(snapshot.clone());
291        }
292        
293        // Check for continuity breaks
294        let continuity_break_info = if let Some(prev_snapshot) = self.snapshots.back() {
295            Some((snapshot.clone(), prev_snapshot.clone()))
296        } else {
297            None
298        };
299
300        if let Some((current, previous)) = continuity_break_info {
301            self.check_continuity_break(&current, &previous)?;
302        }
303        
304        // Update stability metrics
305        self.update_stability_metrics(&snapshot);
306        
307        // Store the snapshot
308        self.store_snapshot(snapshot);
309        
310        // Update overall metrics
311        self.update_metrics();
312        
313        self.last_validation_time = Some(timestamp);
314        
315        Ok(())
316    }
317    
318    /// Validate current identity continuity
319    pub fn validate_continuity(&self) -> TemporalResult<()> {
320        if self.metrics.continuity_score < self.continuity_threshold {
321            return Err(TemporalError::IdentityContinuityBreak {
322                gap_ns: self.metrics.max_gap_duration_ns,
323            });
324        }
325        
326        Ok(())
327    }
328    
329    /// Get current continuity metrics
330    pub fn get_metrics(&self) -> TemporalResult<ContinuityMetrics> {
331        Ok(self.metrics.clone())
332    }
333    
334    /// Get identity stability score
335    pub fn get_identity_stability(&self) -> f64 {
336        self.metrics.identity_stability
337    }
338    
339    /// Get continuity score
340    pub fn get_continuity_score(&self) -> f64 {
341        self.metrics.continuity_score
342    }
343    
344    /// Reset tracking state
345    pub fn reset(&mut self) {
346        self.snapshots.clear();
347        self.metrics = ContinuityMetrics::default();
348        self.identity_baseline = None;
349        self.last_validation_time = None;
350    }
351    
352    /// Set continuity threshold
353    pub fn set_continuity_threshold(&mut self, threshold: f64) {
354        self.continuity_threshold = threshold.clamp(0.0, 1.0);
355    }
356    
357    /// Get recent identity trajectory
358    pub fn get_identity_trajectory(&self, window_size: usize) -> Vec<f64> {
359        self.snapshots.iter()
360            .rev()
361            .take(window_size)
362            .map(|s| s.coherence_score)
363            .collect()
364    }
365    
366    /// Calculate identity drift over time
367    pub fn calculate_identity_drift(&self) -> f64 {
368        if let Some(baseline) = &self.identity_baseline {
369            if let Some(current) = self.snapshots.back() {
370                return 1.0 - baseline.calculate_similarity(current);
371            }
372        }
373        0.0
374    }
375    
376    // Private helper methods
377    
378    fn check_continuity_break(
379        &mut self,
380        current: &IdentitySnapshot,
381        previous: &IdentitySnapshot,
382    ) -> TemporalResult<()> {
383        // Check temporal gap
384        let gap_ns = current.timestamp.nanos_since(previous.timestamp, 3_000_000_000);
385        if gap_ns > self.gap_tolerance_ns {
386            self.metrics.continuity_breaks += 1;
387            self.metrics.max_gap_duration_ns = self.metrics.max_gap_duration_ns.max(gap_ns);
388        }
389        
390        // Check similarity
391        let similarity = current.calculate_similarity(previous);
392        if similarity < self.continuity_threshold {
393            self.metrics.continuity_breaks += 1;
394        }
395        
396        Ok(())
397    }
398    
399    fn update_stability_metrics(&mut self, snapshot: &IdentitySnapshot) {
400        if self.snapshots.len() < 2 {
401            return;
402        }
403        
404        // Calculate stability based on recent snapshots
405        let recent_snapshots: Vec<_> = self.snapshots.iter().rev().take(10).collect();
406        
407        if recent_snapshots.len() >= 2 {
408            let mut similarities = Vec::new();
409            
410            for i in 0..recent_snapshots.len() - 1 {
411                let sim = recent_snapshots[i].calculate_similarity(recent_snapshots[i + 1]);
412                similarities.push(sim);
413            }
414            
415            // Current similarity with latest snapshot
416            let current_sim = snapshot.calculate_similarity(recent_snapshots[0]);
417            similarities.push(current_sim);
418            
419            // Stability is average similarity over recent window
420            let avg_similarity = similarities.iter().sum::<f64>() / similarities.len() as f64;
421            
422            // Update stability metric with exponential moving average
423            let alpha = 0.1;
424            self.metrics.identity_stability = (1.0 - alpha) * self.metrics.identity_stability + alpha * avg_similarity;
425        }
426    }
427    
428    fn store_snapshot(&mut self, snapshot: IdentitySnapshot) {
429        self.snapshots.push_back(snapshot);
430        
431        // Keep history bounded
432        while self.snapshots.len() > self.max_snapshots {
433            self.snapshots.pop_front();
434        }
435    }
436    
437    fn update_metrics(&mut self) {
438        if self.snapshots.len() < 2 {
439            return;
440        }
441        
442        // Calculate continuity score
443        let mut total_similarity = 0.0;
444        let mut similarity_count = 0;
445        
446        for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
447            let sim = window[1].calculate_similarity(window[0]);
448            total_similarity += sim;
449            similarity_count += 1;
450        }
451        
452        if similarity_count > 0 {
453            self.metrics.continuity_score = total_similarity / similarity_count as f64;
454        }
455        
456        // Calculate coherence
457        let coherence_scores: Vec<f64> = self.snapshots.iter()
458            .map(|s| s.coherence_score)
459            .collect();
460        
461        if !coherence_scores.is_empty() {
462            self.metrics.identity_coherence = coherence_scores.iter().sum::<f64>() / coherence_scores.len() as f64;
463        }
464        
465        // Calculate temporal consistency
466        self.calculate_temporal_consistency();
467        
468        // Calculate preservation efficiency
469        self.calculate_preservation_efficiency();
470        
471        // Update gap metrics
472        self.update_gap_metrics();
473    }
474    
475    fn calculate_temporal_consistency(&mut self) {
476        if self.snapshots.len() < 3 {
477            return;
478        }
479        
480        // Measure how consistently identity features change over time
481        let mut consistency_scores = Vec::new();
482        
483        for i in 2..self.snapshots.len() {
484            let s1 = &self.snapshots[i - 2];
485            let s2 = &self.snapshots[i - 1];
486            let s3 = &self.snapshots[i];
487            
488            // Calculate velocity vectors
489            let vel1: Vec<f64> = s2.feature_vector.iter()
490                .zip(s1.feature_vector.iter())
491                .map(|(a, b)| a - b)
492                .collect();
493            
494            let vel2: Vec<f64> = s3.feature_vector.iter()
495                .zip(s2.feature_vector.iter())
496                .map(|(a, b)| a - b)
497                .collect();
498            
499            // Calculate consistency as cosine similarity of velocity vectors
500            let dot_product: f64 = vel1.iter().zip(vel2.iter()).map(|(a, b)| a * b).sum();
501            let mag1: f64 = vel1.iter().map(|x| x * x).sum::<f64>().sqrt();
502            let mag2: f64 = vel2.iter().map(|x| x * x).sum::<f64>().sqrt();
503            
504            if mag1 > 0.0 && mag2 > 0.0 {
505                consistency_scores.push(dot_product / (mag1 * mag2));
506            }
507        }
508        
509        if !consistency_scores.is_empty() {
510            self.metrics.temporal_consistency = consistency_scores.iter().sum::<f64>() / consistency_scores.len() as f64;
511        }
512    }
513    
514    fn calculate_preservation_efficiency(&mut self) {
515        if let Some(baseline) = &self.identity_baseline {
516            if let Some(current) = self.snapshots.back() {
517                // Efficiency based on how well identity is preserved relative to baseline
518                let similarity_to_baseline = current.calculate_similarity(baseline);
519                let time_factor = 1.0 / (1.0 + self.snapshots.len() as f64 / 1000.0); // Decay over time
520                
521                self.metrics.preservation_efficiency = similarity_to_baseline * time_factor;
522            }
523        }
524    }
525    
526    fn update_gap_metrics(&mut self) {
527        if self.snapshots.len() < 2 {
528            return;
529        }
530        
531        let mut gaps = Vec::new();
532        
533        for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
534            let gap_ns = window[1].timestamp.nanos_since(window[0].timestamp, 3_000_000_000);
535            gaps.push(gap_ns);
536        }
537        
538        if !gaps.is_empty() {
539            self.metrics.average_gap_duration_ns = gaps.iter().sum::<u64>() as f64 / gaps.len() as f64;
540            self.metrics.max_gap_duration_ns = *gaps.iter().max().unwrap_or(&0);
541        }
542    }
543}
544
545impl Default for IdentityContinuityTracker {
546    fn default() -> Self {
547        Self::new()
548    }
549}
550
551#[cfg(test)]
552mod tests {
553    use super::*;
554    
555    #[test]
556    fn test_identity_snapshot_creation() {
557        let timestamp = TscTimestamp::now();
558        let state = vec![1, 2, 3, 4, 5];
559        
560        let snapshot = IdentitySnapshot::new(timestamp, &state);
561        assert_eq!(snapshot.timestamp, timestamp);
562        assert!(!snapshot.feature_vector.is_empty());
563        assert!(snapshot.coherence_score >= 0.0 && snapshot.coherence_score <= 1.0);
564    }
565    
566    #[test]
567    fn test_feature_extraction() {
568        let state = vec![1, 2, 3, 4, 5, 4, 3, 2, 1];
569        let features = IdentitySnapshot::extract_features(&state);
570        
571        assert!(!features.is_empty());
572        // Features should be normalized
573        for &feature in &features {
574            assert!(feature >= -1.0 && feature <= 1.0);
575        }
576    }
577    
578    #[test]
579    fn test_similarity_calculation() {
580        let timestamp = TscTimestamp::now();
581        let state1 = vec![1, 2, 3, 4, 5];
582        let state2 = vec![1, 2, 3, 4, 5]; // Identical
583        let state3 = vec![5, 4, 3, 2, 1]; // Different
584        
585        let snapshot1 = IdentitySnapshot::new(timestamp, &state1);
586        let snapshot2 = IdentitySnapshot::new(timestamp, &state2);
587        let snapshot3 = IdentitySnapshot::new(timestamp, &state3);
588        
589        let sim12 = snapshot1.calculate_similarity(&snapshot2);
590        let sim13 = snapshot1.calculate_similarity(&snapshot3);
591        
592        assert!(sim12 > sim13); // Identical states should be more similar
593        assert!(sim12 >= 0.0 && sim12 <= 1.0);
594        assert!(sim13 >= 0.0 && sim13 <= 1.0);
595    }
596    
597    #[test]
598    fn test_continuity_tracker() {
599        let mut tracker = IdentityContinuityTracker::new();
600        let timestamp = TscTimestamp::now();
601        let state = vec![1, 2, 3, 4, 5];
602        
603        tracker.track_continuity(timestamp, &state).unwrap();
604        assert_eq!(tracker.snapshots.len(), 1);
605        
606        // Track another similar state
607        let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
608        let state2 = vec![1, 2, 3, 4, 6]; // Slightly different
609        
610        tracker.track_continuity(timestamp2, &state2).unwrap();
611        assert_eq!(tracker.snapshots.len(), 2);
612        
613        let metrics = tracker.get_metrics().unwrap();
614        assert!(metrics.continuity_score > 0.0);
615    }
616    
617    #[test]
618    fn test_continuity_break_detection() {
619        let mut tracker = IdentityContinuityTracker::new();
620        tracker.set_continuity_threshold(0.9); // High threshold
621        
622        let timestamp = TscTimestamp::now();
623        let state1 = vec![1, 2, 3, 4, 5];
624        let state2 = vec![10, 20, 30, 40, 50]; // Very different
625        
626        tracker.track_continuity(timestamp, &state1).unwrap();
627        
628        let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
629        tracker.track_continuity(timestamp2, &state2).unwrap();
630        
631        // Should detect continuity break
632        assert!(tracker.metrics.continuity_breaks > 0);
633    }
634    
635    #[test]
636    fn test_identity_drift_calculation() {
637        let mut tracker = IdentityContinuityTracker::new();
638        let timestamp = TscTimestamp::now();
639        
640        // Start with baseline
641        let baseline_state = vec![1, 2, 3, 4, 5];
642        tracker.track_continuity(timestamp, &baseline_state).unwrap();
643        
644        // Gradual drift
645        for i in 1..=10 {
646            let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
647            let drifted_state = vec![1 + i as u8, 2, 3, 4, 5];
648            tracker.track_continuity(timestamp_i, &drifted_state).unwrap();
649        }
650        
651        let drift = tracker.calculate_identity_drift();
652        assert!(drift > 0.0); // Should detect some drift
653        assert!(drift <= 1.0); // Should be bounded
654    }
655    
656    #[test]
657    fn test_stability_metrics() {
658        let mut tracker = IdentityContinuityTracker::new();
659        let timestamp = TscTimestamp::now();
660        
661        // Track several stable states
662        for i in 0..10 {
663            let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
664            let stable_state = vec![1, 2, 3, 4, 5]; // Same state
665            tracker.track_continuity(timestamp_i, &stable_state).unwrap();
666        }
667        
668        assert!(tracker.get_identity_stability() > 0.5); // Should be stable
669    }
670}