codex_memory/memory/
cognitive_memory_system.rs

1//! Cognitive Memory System Integration
2//!
3//! This module provides a unified interface for the SOTA cognitive memory system,
4//! integrating all cognitive enhancement components into a cohesive architecture.
5//!
6//! ## System Architecture
7//!
8//! The Cognitive Memory System combines several research-backed components:
9//!
10//! ### Core Components
11//! 1. **Three-Component Scoring**: Real-time memory importance calculation
12//! 2. **Cognitive Consolidation**: Enhanced memory strengthening with spacing effects
13//! 3. **Reflection Engine**: Meta-memory and insight generation
14//! 4. **Knowledge Graph**: Semantic relationship tracking
15//! 5. **Loop Prevention**: Quality control and duplicate detection
16//!
17//! ### Research Foundation
18//! - **Park et al. (2023)**: Generative agents three-component scoring
19//! - **Ebbinghaus (1885)**: Forgetting curve and spaced repetition
20//! - **Collins & Loftus (1975)**: Semantic network theory
21//! - **Flavell (1979)**: Metacognition and reflection processes
22//! - **Bjork (1994)**: Desirable difficulties and testing effects
23//!
24//! ## Usage Example
25//!
26//! ```rust
27//! use codex::memory::CognitiveMemorySystem;
28//!
29//! let mut system = CognitiveMemorySystem::new(repository).await?;
30//!
31//! // Store memory with cognitive enhancement
32//! let memory = system.store_memory_with_cognitive_processing(
33//!     "Important information to remember",
34//!     context
35//! ).await?;
36//!
37//! // Retrieve with enhanced scoring
38//! let results = system.cognitive_search(
39//!     "find related information",
40//!     search_context
41//! ).await?;
42//!
43//! // Trigger reflection for insight generation
44//! let insights = system.trigger_reflection_if_needed().await?;
45//! ```
46
47use super::cognitive_consolidation::{
48    CognitiveConsolidationConfig, CognitiveConsolidationEngine, CognitiveConsolidationResult,
49    RetrievalContext,
50};
51use super::error::Result;
52use super::insight_loop_prevention::{
53    LoopPreventionConfig, LoopPreventionEngine, PreventionAction,
54};
55use super::models::*;
56use super::reflection_engine::{Insight, ReflectionConfig, ReflectionEngine, ReflectionSession};
57use super::repository::MemoryRepository;
58use super::three_component_scoring::{
59    EnhancedSearchService, ScoringContext, ThreeComponentConfig, ThreeComponentEngine,
60};
61
62use chrono::{DateTime, Utc};
63use serde::{Deserialize, Serialize};
64use std::sync::Arc;
65use tokio::sync::RwLock;
66use tracing::{debug, info, warn};
67use uuid::Uuid;
68
69/// Configuration for the complete cognitive memory system
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct CognitiveMemoryConfig {
72    /// Three-component scoring configuration
73    pub scoring_config: ThreeComponentConfig,
74
75    /// Cognitive consolidation configuration
76    pub consolidation_config: CognitiveConsolidationConfig,
77
78    /// Reflection engine configuration
79    pub reflection_config: ReflectionConfig,
80
81    /// Loop prevention configuration
82    pub loop_prevention_config: LoopPreventionConfig,
83
84    /// Enable automatic cognitive processing
85    pub enable_auto_processing: bool,
86
87    /// Enable background reflection monitoring
88    pub enable_background_reflection: bool,
89
90    /// Minimum time between automatic processing (minutes)
91    pub auto_processing_interval_minutes: u64,
92
93    /// Performance monitoring configuration
94    pub enable_performance_monitoring: bool,
95
96    /// Maximum concurrent cognitive operations
97    pub max_concurrent_operations: usize,
98}
99
100impl Default for CognitiveMemoryConfig {
101    fn default() -> Self {
102        Self {
103            scoring_config: ThreeComponentConfig::default(),
104            consolidation_config: CognitiveConsolidationConfig::default(),
105            reflection_config: ReflectionConfig::default(),
106            loop_prevention_config: LoopPreventionConfig::default(),
107            enable_auto_processing: true,
108            enable_background_reflection: true,
109            auto_processing_interval_minutes: 30,
110            enable_performance_monitoring: true,
111            max_concurrent_operations: 10,
112        }
113    }
114}
115
116/// Performance metrics for the cognitive system
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct CognitivePerformanceMetrics {
119    pub total_memories_processed: u64,
120    pub total_insights_generated: u64,
121    pub total_reflections_completed: u64,
122    pub average_scoring_time_ms: f64,
123    pub average_consolidation_time_ms: f64,
124    pub average_reflection_time_ms: f64,
125    pub loop_prevention_blocks: u64,
126    pub quality_rejections: u64,
127    pub system_uptime_hours: f64,
128    pub last_updated: DateTime<Utc>,
129}
130
131impl Default for CognitivePerformanceMetrics {
132    fn default() -> Self {
133        Self {
134            total_memories_processed: 0,
135            total_insights_generated: 0,
136            total_reflections_completed: 0,
137            average_scoring_time_ms: 0.0,
138            average_consolidation_time_ms: 0.0,
139            average_reflection_time_ms: 0.0,
140            loop_prevention_blocks: 0,
141            quality_rejections: 0,
142            system_uptime_hours: 0.0,
143            last_updated: Utc::now(),
144        }
145    }
146}
147
148/// Enhanced memory storage request with cognitive context
149#[derive(Debug, Clone)]
150pub struct CognitiveMemoryRequest {
151    pub content: String,
152    pub embedding: Option<Vec<f32>>,
153    pub importance_score: Option<f64>,
154    pub metadata: Option<serde_json::Value>,
155    pub retrieval_context: RetrievalContext,
156    pub enable_immediate_consolidation: bool,
157    pub enable_quality_assessment: bool,
158}
159
160/// Enhanced memory with cognitive processing results
161#[derive(Debug, Clone)]
162pub struct CognitiveMemoryResult {
163    pub memory: Memory,
164    pub consolidation_result: Option<CognitiveConsolidationResult>,
165    pub quality_assessment: Option<super::insight_loop_prevention::QualityAssessment>,
166    pub processing_time_ms: u64,
167    pub cognitive_flags: CognitiveFlags,
168}
169
170/// Flags indicating cognitive processing status
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct CognitiveFlags {
173    pub consolidation_applied: bool,
174    pub reflection_triggered: bool,
175    pub quality_validated: bool,
176    pub loop_prevention_checked: bool,
177    pub three_component_scored: bool,
178}
179
180impl Default for CognitiveFlags {
181    fn default() -> Self {
182        Self {
183            consolidation_applied: false,
184            reflection_triggered: false,
185            quality_validated: false,
186            loop_prevention_checked: false,
187            three_component_scored: false,
188        }
189    }
190}
191
192/// Main cognitive memory system orchestrator
193pub struct CognitiveMemorySystem {
194    repository: Arc<MemoryRepository>,
195    config: CognitiveMemoryConfig,
196
197    // Cognitive engines
198    scoring_engine: ThreeComponentEngine,
199    consolidation_engine: CognitiveConsolidationEngine,
200    reflection_engine: Arc<RwLock<ReflectionEngine>>,
201    loop_prevention_engine: Arc<RwLock<LoopPreventionEngine>>,
202    search_service: EnhancedSearchService,
203
204    // System state
205    performance_metrics: Arc<RwLock<CognitivePerformanceMetrics>>,
206    last_background_processing: Arc<RwLock<DateTime<Utc>>>,
207    system_start_time: DateTime<Utc>,
208}
209
210impl CognitiveMemorySystem {
211    /// Create a new cognitive memory system
212    pub async fn new(
213        repository: Arc<MemoryRepository>,
214        config: CognitiveMemoryConfig,
215    ) -> Result<Self> {
216        info!("Initializing Cognitive Memory System with enhanced features");
217
218        // Initialize cognitive engines
219        let scoring_engine = ThreeComponentEngine::new(config.scoring_config.clone())?;
220        let consolidation_engine =
221            CognitiveConsolidationEngine::new(config.consolidation_config.clone());
222        let reflection_engine = Arc::new(RwLock::new(ReflectionEngine::new(
223            config.reflection_config.clone(),
224            repository.clone(),
225        )));
226        let loop_prevention_engine = Arc::new(RwLock::new(LoopPreventionEngine::new(
227            config.loop_prevention_config.clone(),
228        )));
229        let search_service = EnhancedSearchService::new(config.scoring_config.clone())?;
230
231        let performance_metrics = Arc::new(RwLock::new(CognitivePerformanceMetrics::default()));
232        let last_background_processing = Arc::new(RwLock::new(Utc::now()));
233        let system_start_time = Utc::now();
234
235        info!("Cognitive Memory System initialized successfully");
236
237        Ok(Self {
238            repository,
239            config,
240            scoring_engine,
241            consolidation_engine,
242            reflection_engine,
243            loop_prevention_engine,
244            search_service,
245            performance_metrics,
246            last_background_processing,
247            system_start_time,
248        })
249    }
250
251    /// Store memory with full cognitive processing
252    pub async fn store_memory_with_cognitive_processing(
253        &self,
254        request: CognitiveMemoryRequest,
255    ) -> Result<CognitiveMemoryResult> {
256        let start_time = std::time::Instant::now();
257        let mut cognitive_flags = CognitiveFlags::default();
258
259        info!("Processing memory storage with cognitive enhancements");
260
261        // Create base memory
262        let create_request = CreateMemoryRequest {
263            content: request.content.clone(),
264            embedding: request.embedding.clone(),
265            tier: Some(MemoryTier::Working),
266            importance_score: request.importance_score,
267            metadata: request.metadata.clone(),
268            parent_id: None,
269            expires_at: None,
270        };
271
272        let mut memory = self.repository.create_memory(create_request).await?;
273
274        // Apply three-component scoring
275        let scoring_context = ScoringContext {
276            query_embedding: request.embedding.clone().map(pgvector::Vector::from),
277            context_factors: request.retrieval_context.environmental_factors.clone(),
278            query_time: Utc::now(),
279            user_preferences: std::collections::HashMap::new(),
280        };
281
282        if let Ok(scoring_result) =
283            self.scoring_engine
284                .calculate_score(&memory, &scoring_context, false)
285        {
286            // Update memory with scores (would be persisted in production)
287            cognitive_flags.three_component_scored = true;
288            debug!(
289                "Three-component scoring applied: combined score {:.3}",
290                scoring_result.combined_score
291            );
292        }
293
294        // Apply cognitive consolidation if enabled
295        let consolidation_result = if request.enable_immediate_consolidation {
296            let similar_memories = self.find_similar_memories(&memory, 10).await?;
297
298            match self
299                .consolidation_engine
300                .calculate_cognitive_consolidation(
301                    &memory,
302                    &request.retrieval_context,
303                    &similar_memories,
304                )
305                .await
306            {
307                Ok(result) => {
308                    self.consolidation_engine
309                        .apply_consolidation_results(&mut memory, &result, &self.repository)
310                        .await?;
311                    cognitive_flags.consolidation_applied = true;
312                    debug!(
313                        "Cognitive consolidation applied: strength {:.3}",
314                        result.new_consolidation_strength
315                    );
316                    Some(result)
317                }
318                Err(e) => {
319                    warn!("Consolidation failed: {}", e);
320                    None
321                }
322            }
323        } else {
324            None
325        };
326
327        // Quality assessment if enabled
328        let quality_assessment = if request.enable_quality_assessment {
329            // Create a mock insight for quality assessment
330            let mock_insight = Insight {
331                id: Uuid::new_v4(),
332                insight_type: super::reflection_engine::InsightType::Pattern,
333                content: request.content.clone(),
334                confidence_score: 0.8,
335                source_memory_ids: vec![memory.id],
336                related_concepts: Vec::new(), // Would extract from content
337                knowledge_graph_nodes: Vec::new(),
338                importance_score: memory.importance_score,
339                generated_at: Utc::now(),
340                validation_metrics: super::reflection_engine::ValidationMetrics {
341                    novelty_score: 0.8,
342                    coherence_score: 0.9,
343                    evidence_strength: 0.7,
344                    semantic_richness: 0.6,
345                    predictive_power: 0.5,
346                },
347            };
348
349            match self
350                .loop_prevention_engine
351                .write()
352                .await
353                .validate_insight(&mock_insight)
354            {
355                Ok(loop_result) => {
356                    cognitive_flags.quality_validated = true;
357                    cognitive_flags.loop_prevention_checked = true;
358
359                    if loop_result.prevention_action == PreventionAction::RejectInsight {
360                        warn!("Memory quality assessment failed - would be rejected as insight");
361                    }
362
363                    Some(super::insight_loop_prevention::QualityAssessment {
364                        novelty_score: 0.8,
365                        coherence_score: 0.9,
366                        evidence_strength: 0.7,
367                        semantic_richness: 0.6,
368                        predictive_power: 0.5,
369                        overall_quality: 0.74,
370                        quality_factors: vec!["High coherence".to_string()],
371                        deficiency_reasons: Vec::new(),
372                    })
373                }
374                Err(e) => {
375                    warn!("Quality assessment failed: {}", e);
376                    None
377                }
378            }
379        } else {
380            None
381        };
382
383        // Check if reflection should be triggered
384        if self.config.enable_auto_processing {
385            if let Ok(should_reflect) = self
386                .reflection_engine
387                .read()
388                .await
389                .should_trigger_reflection()
390                .await
391            {
392                if should_reflect.is_some() {
393                    cognitive_flags.reflection_triggered = true;
394                    debug!("Reflection will be triggered in background");
395
396                    // Trigger background reflection (non-blocking)
397                    let reflection_engine = self.reflection_engine.clone();
398                    let trigger_reason = should_reflect.unwrap();
399                    tokio::spawn(async move {
400                        let mut engine = reflection_engine.write().await;
401                        match engine.execute_reflection(trigger_reason).await {
402                            Ok(session) => {
403                                info!(
404                                    "Background reflection completed: {} insights generated",
405                                    session.generated_insights.len()
406                                );
407                            }
408                            Err(e) => {
409                                warn!("Background reflection failed: {}", e);
410                            }
411                        }
412                    });
413                }
414            }
415        }
416
417        let processing_time = start_time.elapsed().as_millis() as u64;
418
419        // Update performance metrics
420        self.update_performance_metrics(processing_time, &cognitive_flags)
421            .await;
422
423        info!(
424            "Cognitive memory processing completed in {}ms",
425            processing_time
426        );
427
428        Ok(CognitiveMemoryResult {
429            memory,
430            consolidation_result,
431            quality_assessment,
432            processing_time_ms: processing_time,
433            cognitive_flags,
434        })
435    }
436
437    /// Perform enhanced search with cognitive scoring
438    pub async fn cognitive_search(
439        &self,
440        query: &str,
441        context: ScoringContext,
442        limit: Option<i32>,
443    ) -> Result<Vec<super::three_component_scoring::EnhancedSearchResult>> {
444        let start_time = std::time::Instant::now();
445
446        info!("Performing cognitive search for: {}", query);
447
448        // Create base search request
449        let search_request = SearchRequest {
450            query_text: Some(query.to_string()),
451            query_embedding: context
452                .query_embedding
453                .as_ref()
454                .map(|v| v.as_slice().to_vec()),
455            search_type: Some(SearchType::Hybrid),
456            limit,
457            explain_score: Some(true),
458            ..Default::default()
459        };
460
461        // Perform base search
462        let search_response = self.repository.search_memories(search_request).await?;
463
464        // Apply cognitive ranking
465        let enhanced_results =
466            self.search_service
467                .rank_search_results(search_response.results, &context, true)?;
468
469        let processing_time = start_time.elapsed().as_millis() as u64;
470
471        debug!(
472            "Cognitive search completed in {}ms, {} results",
473            processing_time,
474            enhanced_results.len()
475        );
476
477        Ok(enhanced_results)
478    }
479
480    /// Manually trigger reflection for insight generation
481    pub async fn trigger_reflection(&self, reason: String) -> Result<ReflectionSession> {
482        info!("Manually triggering reflection: {}", reason);
483
484        let mut reflection_engine = self.reflection_engine.write().await;
485        let session = reflection_engine.execute_reflection(reason).await?;
486
487        // Process generated insights through loop prevention
488        let mut loop_prevention = self.loop_prevention_engine.write().await;
489        for insight in &session.generated_insights {
490            match loop_prevention.validate_insight(insight) {
491                Ok(validation_result) => {
492                    if validation_result.prevention_action == PreventionAction::Allow {
493                        // Register valid insight
494                        let quality = super::insight_loop_prevention::QualityAssessment {
495                            novelty_score: insight.validation_metrics.novelty_score,
496                            coherence_score: insight.validation_metrics.coherence_score,
497                            evidence_strength: insight.validation_metrics.evidence_strength,
498                            semantic_richness: insight.validation_metrics.semantic_richness,
499                            predictive_power: insight.validation_metrics.predictive_power,
500                            overall_quality: (insight.validation_metrics.novelty_score
501                                + insight.validation_metrics.coherence_score
502                                + insight.validation_metrics.evidence_strength
503                                + insight.validation_metrics.semantic_richness
504                                + insight.validation_metrics.predictive_power)
505                                / 5.0,
506                            quality_factors: vec!["Validated through reflection".to_string()],
507                            deficiency_reasons: Vec::new(),
508                        };
509
510                        if let Err(e) = loop_prevention.register_insight(insight, quality) {
511                            warn!("Failed to register insight {}: {}", insight.id, e);
512                        }
513                    } else {
514                        warn!(
515                            "Insight {} blocked by loop prevention: {:?}",
516                            insight.id, validation_result.prevention_action
517                        );
518                    }
519                }
520                Err(e) => {
521                    warn!("Failed to validate insight {}: {}", insight.id, e);
522                }
523            }
524        }
525
526        // Update metrics
527        {
528            let mut metrics = self.performance_metrics.write().await;
529            metrics.total_reflections_completed += 1;
530            metrics.total_insights_generated += session.generated_insights.len() as u64;
531            metrics.last_updated = Utc::now();
532        }
533
534        info!(
535            "Reflection completed: {} insights generated, {} clusters analyzed",
536            session.generated_insights.len(),
537            session.generated_clusters.len()
538        );
539
540        Ok(session)
541    }
542
543    /// Get current system performance metrics
544    pub async fn get_performance_metrics(&self) -> CognitivePerformanceMetrics {
545        let mut metrics = self.performance_metrics.read().await.clone();
546
547        // Update uptime
548        metrics.system_uptime_hours = Utc::now()
549            .signed_duration_since(self.system_start_time)
550            .num_seconds() as f64
551            / 3600.0;
552
553        metrics
554    }
555
556    /// Get loop prevention statistics
557    pub async fn get_loop_prevention_statistics(
558        &self,
559    ) -> super::insight_loop_prevention::PreventionStatistics {
560        self.loop_prevention_engine
561            .read()
562            .await
563            .get_prevention_statistics()
564    }
565
566    /// Update system configuration
567    pub async fn update_configuration(&mut self, config: CognitiveMemoryConfig) -> Result<()> {
568        info!("Updating cognitive memory system configuration");
569
570        // Validate configuration components
571        config.scoring_config.validate()?;
572
573        // Update engines
574        self.scoring_engine
575            .update_config(config.scoring_config.clone())?;
576
577        // Update system config
578        self.config = config;
579
580        info!("Configuration updated successfully");
581        Ok(())
582    }
583
584    /// Perform background maintenance tasks
585    pub async fn background_maintenance(&self) -> Result<()> {
586        if !self.config.enable_background_reflection {
587            return Ok(());
588        }
589
590        let last_processing = *self.last_background_processing.read().await;
591        let minutes_since_last = Utc::now()
592            .signed_duration_since(last_processing)
593            .num_minutes() as u64;
594
595        if minutes_since_last < self.config.auto_processing_interval_minutes {
596            return Ok(());
597        }
598
599        debug!("Performing background maintenance");
600
601        // Check if reflection should be triggered
602        if let Ok(should_reflect) = self
603            .reflection_engine
604            .read()
605            .await
606            .should_trigger_reflection()
607            .await
608        {
609            if let Some(reason) = should_reflect {
610                match self.trigger_reflection(reason).await {
611                    Ok(_) => {
612                        info!("Background reflection completed successfully");
613                    }
614                    Err(e) => {
615                        warn!("Background reflection failed: {}", e);
616                    }
617                }
618            }
619        }
620
621        // Update last processing time
622        *self.last_background_processing.write().await = Utc::now();
623
624        Ok(())
625    }
626
627    // Private helper methods
628
629    async fn find_similar_memories(&self, memory: &Memory, limit: usize) -> Result<Vec<Memory>> {
630        if memory.embedding.is_none() {
631            return Ok(Vec::new());
632        }
633
634        let search_request = SearchRequest {
635            query_embedding: Some(memory.embedding.as_ref().unwrap().as_slice().to_vec()),
636            search_type: Some(SearchType::Semantic),
637            similarity_threshold: Some(0.7),
638            limit: Some(limit as i32),
639            ..Default::default()
640        };
641
642        let search_response = self.repository.search_memories(search_request).await?;
643
644        Ok(search_response
645            .results
646            .into_iter()
647            .filter(|result| result.memory.id != memory.id)
648            .map(|result| result.memory)
649            .collect())
650    }
651
652    async fn update_performance_metrics(&self, processing_time_ms: u64, flags: &CognitiveFlags) {
653        let mut metrics = self.performance_metrics.write().await;
654
655        metrics.total_memories_processed += 1;
656
657        // Update timing averages (simple moving average)
658        let count = metrics.total_memories_processed as f64;
659        metrics.average_scoring_time_ms =
660            (metrics.average_scoring_time_ms * (count - 1.0) + processing_time_ms as f64) / count;
661
662        if flags.consolidation_applied {
663            metrics.average_consolidation_time_ms =
664                (metrics.average_consolidation_time_ms * (count - 1.0) + processing_time_ms as f64)
665                    / count;
666        }
667
668        metrics.last_updated = Utc::now();
669    }
670}
671
672#[cfg(test)]
673mod tests {
674    use super::*;
675    use std::collections::HashMap;
676
677    async fn create_test_repository() -> Arc<MemoryRepository> {
678        // This would create a test repository in real implementation
679        panic!("Test repository creation not implemented - requires database setup");
680    }
681
682    #[tokio::test]
683    #[ignore] // Ignore for now as it requires database setup
684    async fn test_cognitive_memory_system_creation() {
685        let repository = create_test_repository().await;
686        let config = CognitiveMemoryConfig::default();
687
688        let system = CognitiveMemorySystem::new(repository, config).await;
689        assert!(system.is_ok());
690    }
691
692    #[test]
693    fn test_cognitive_memory_config_defaults() {
694        let config = CognitiveMemoryConfig::default();
695
696        assert!(config.enable_auto_processing);
697        assert!(config.enable_background_reflection);
698        assert_eq!(config.auto_processing_interval_minutes, 30);
699        assert_eq!(config.max_concurrent_operations, 10);
700    }
701
702    #[test]
703    fn test_cognitive_flags_default() {
704        let flags = CognitiveFlags::default();
705
706        assert!(!flags.consolidation_applied);
707        assert!(!flags.reflection_triggered);
708        assert!(!flags.quality_validated);
709        assert!(!flags.loop_prevention_checked);
710        assert!(!flags.three_component_scored);
711    }
712
713    #[test]
714    fn test_performance_metrics_default() {
715        let metrics = CognitivePerformanceMetrics::default();
716
717        assert_eq!(metrics.total_memories_processed, 0);
718        assert_eq!(metrics.total_insights_generated, 0);
719        assert_eq!(metrics.total_reflections_completed, 0);
720        assert_eq!(metrics.average_scoring_time_ms, 0.0);
721    }
722}