use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
const MAX_EVENT_BUFFER_SIZE: usize = 1000;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ConsolidationEvent {
MemoryStrengthened {
memory_id: String,
content_preview: String,
activation_before: f32,
activation_after: f32,
reason: StrengtheningReason,
timestamp: DateTime<Utc>,
},
MemoryDecayed {
memory_id: String,
content_preview: String,
activation_before: f32,
activation_after: f32,
at_risk: bool, timestamp: DateTime<Utc>,
},
EdgeFormed {
from_memory_id: String,
to_memory_id: String,
initial_strength: f32,
reason: EdgeFormationReason,
timestamp: DateTime<Utc>,
},
EdgeStrengthened {
from_memory_id: String,
to_memory_id: String,
strength_before: f32,
strength_after: f32,
co_activations: u32,
timestamp: DateTime<Utc>,
},
EdgePotentiated {
from_memory_id: String,
to_memory_id: String,
final_strength: f32,
total_co_activations: u32,
timestamp: DateTime<Utc>,
},
EdgePruned {
from_memory_id: String,
to_memory_id: String,
final_strength: f32,
reason: PruningReason,
timestamp: DateTime<Utc>,
},
FactExtracted {
fact_id: String,
fact_content: String,
confidence: f32,
source_memory_count: usize,
fact_type: String,
timestamp: DateTime<Utc>,
},
FactReinforced {
fact_id: String,
fact_content: String,
confidence_before: f32,
confidence_after: f32,
new_support_count: usize,
timestamp: DateTime<Utc>,
},
FactDecayed {
fact_id: String,
fact_content: String,
confidence_before: f32,
confidence_after: f32,
days_since_reinforcement: i64,
timestamp: DateTime<Utc>,
},
FactDeleted {
fact_id: String,
fact_content: String,
final_confidence: f32,
support_count: usize,
reason: String,
timestamp: DateTime<Utc>,
},
MemoryPromoted {
memory_id: String,
content_preview: String,
from_tier: String,
to_tier: String,
timestamp: DateTime<Utc>,
},
MaintenanceCycleCompleted {
memories_processed: usize,
memories_decayed: usize,
edges_pruned: usize,
duration_ms: u64,
timestamp: DateTime<Utc>,
},
MemoryReplayed {
memory_id: String,
content_preview: String,
activation_before: f32,
activation_after: f32,
replay_priority: f32,
connected_memories_replayed: usize,
timestamp: DateTime<Utc>,
},
ReplayCycleCompleted {
memories_replayed: usize,
edges_strengthened: usize,
total_priority_score: f32,
duration_ms: u64,
timestamp: DateTime<Utc>,
},
InterferenceDetected {
new_memory_id: String,
old_memory_id: String,
similarity: f32,
interference_type: InterferenceType,
timestamp: DateTime<Utc>,
},
MemoryWeakened {
memory_id: String,
content_preview: String,
activation_before: f32,
activation_after: f32,
interfering_memory_id: String,
interference_type: InterferenceType,
timestamp: DateTime<Utc>,
},
RetrievalCompetition {
query_preview: String,
winner_memory_id: String,
suppressed_memory_ids: Vec<String>,
competition_factor: f32,
timestamp: DateTime<Utc>,
},
PatternTriggeredReplay {
trigger_type: String,
memory_ids: Vec<String>,
pattern_confidence: f32,
trigger_description: String,
timestamp: DateTime<Utc>,
},
EntityPatternDetected {
entity_group: Vec<String>,
memory_ids: Vec<String>,
overlap_score: f32,
confidence: f32,
timestamp: DateTime<Utc>,
},
SemanticClusterFormed {
memory_ids: Vec<String>,
cluster_size: usize,
avg_similarity: f32,
centroid_id: String,
timestamp: DateTime<Utc>,
},
TemporalClusterFormed {
memory_ids: Vec<String>,
session_duration_secs: i64,
session_id: Option<String>,
timestamp: DateTime<Utc>,
},
SalienceSpikeDetected {
memory_id: String,
content_preview: String,
importance: f32,
arousal: f32,
surprise_factor: f32,
timestamp: DateTime<Utc>,
},
BehavioralChangeDetected {
change_type: String,
affected_memory_ids: Vec<String>,
context: String,
timestamp: DateTime<Utc>,
},
PatternDetected {
trigger_type: String,
description: String,
memory_ids: Vec<String>,
timestamp: DateTime<Utc>,
},
EdgePromotionBoostApplied {
memory_id: String,
entity_name: String,
old_tier: String,
new_tier: String,
importance_boost: f64,
new_importance: f64,
timestamp: DateTime<Utc>,
},
GraphOrphanDetected {
memory_id: String,
entity_count: usize,
compensatory_boost: f64,
timestamp: DateTime<Utc>,
},
GraphAdjustedPromotion {
memory_id: String,
base_threshold: f64,
adjusted_threshold: f64,
l2_plus_edge_count: usize,
promoted: bool,
timestamp: DateTime<Utc>,
},
GraphDecayConsolidated {
pruned_count: usize,
orphaned_entities: usize,
timestamp: DateTime<Utc>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum InterferenceType {
Retroactive,
Proactive,
RetrievalCompetition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StrengtheningReason {
Recalled,
SpreadingActivation,
ExplicitBoost,
CoRetrieval,
MaintenancePotentiation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EdgeFormationReason {
CoRetrieval,
SharedEntities,
SemanticSimilarity,
TemporalProximity,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PruningReason {
DecayedBelowThreshold,
Inactivity,
Invalidated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConsolidationReport {
pub period: ReportPeriod,
pub strengthened_memories: Vec<MemoryChange>,
pub decayed_memories: Vec<MemoryChange>,
pub formed_associations: Vec<AssociationChange>,
pub strengthened_associations: Vec<AssociationChange>,
pub potentiated_associations: Vec<AssociationChange>,
pub pruned_associations: Vec<AssociationChange>,
pub extracted_facts: Vec<FactChange>,
pub reinforced_facts: Vec<FactChange>,
pub decayed_facts: Vec<FactChange>,
pub deleted_facts: Vec<FactChange>,
pub replayed_memories: Vec<ReplayEvent>,
pub interference_events: Vec<InterferenceEvent>,
pub weakened_memories: Vec<MemoryChange>,
pub statistics: ConsolidationStats,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplayEvent {
pub memory_id: String,
pub content_preview: String,
pub activation_before: f32,
pub activation_after: f32,
pub replay_priority: f32,
pub connected_memories: usize,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InterferenceEvent {
pub new_memory_id: String,
pub old_memory_id: String,
pub similarity: f32,
pub interference_type: InterferenceType,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportPeriod {
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryChange {
pub memory_id: String,
pub content_preview: String,
pub activation_before: f32,
pub activation_after: f32,
pub change_reason: String,
pub at_risk: bool,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssociationChange {
pub from_memory_id: String,
pub to_memory_id: String,
pub strength_before: Option<f32>,
pub strength_after: f32,
pub co_activations: Option<u32>,
pub reason: String,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FactChange {
pub fact_id: String,
pub fact_content: String,
pub confidence: f32,
pub support_count: usize,
pub fact_type: String,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ConsolidationStats {
pub total_memories: usize,
pub memories_strengthened: usize,
pub memories_decayed: usize,
pub memories_at_risk: usize,
pub edges_formed: usize,
pub edges_strengthened: usize,
pub edges_potentiated: usize,
pub edges_pruned: usize,
pub facts_extracted: usize,
pub facts_reinforced: usize,
pub facts_decayed: usize,
pub facts_deleted: usize,
pub maintenance_cycles: usize,
pub total_maintenance_duration_ms: u64,
pub memories_replayed: usize,
pub replay_cycles: usize,
pub total_replay_priority: f32,
pub interference_events: usize,
pub memories_weakened: usize,
pub retrieval_competitions: usize,
}
#[derive(Debug, Default)]
pub struct ConsolidationEventBuffer {
events: VecDeque<ConsolidationEvent>,
max_size: usize,
}
impl ConsolidationEventBuffer {
pub fn new() -> Self {
Self {
events: VecDeque::new(),
max_size: MAX_EVENT_BUFFER_SIZE,
}
}
pub fn with_capacity(max_size: usize) -> Self {
Self {
events: VecDeque::with_capacity(max_size),
max_size,
}
}
pub fn push(&mut self, event: ConsolidationEvent) {
if self.events.len() >= self.max_size {
self.events.pop_front();
}
self.events.push_back(event);
}
pub fn events_since(&self, since: DateTime<Utc>) -> Vec<ConsolidationEvent> {
self.events
.iter()
.filter(|e| e.timestamp() >= since)
.cloned()
.collect()
}
pub fn all_events(&self) -> Vec<ConsolidationEvent> {
self.events.iter().cloned().collect()
}
pub fn clear(&mut self) {
self.events.clear();
}
pub fn len(&self) -> usize {
self.events.len()
}
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
pub fn generate_report(
&self,
since: DateTime<Utc>,
until: DateTime<Utc>,
) -> ConsolidationReport {
let events: Vec<_> = self
.events
.iter()
.filter(|e| {
let ts = e.timestamp();
ts >= since && ts <= until
})
.collect();
let mut report = ConsolidationReport {
period: ReportPeriod {
start: since,
end: until,
},
strengthened_memories: Vec::new(),
decayed_memories: Vec::new(),
formed_associations: Vec::new(),
strengthened_associations: Vec::new(),
potentiated_associations: Vec::new(),
pruned_associations: Vec::new(),
extracted_facts: Vec::new(),
reinforced_facts: Vec::new(),
decayed_facts: Vec::new(),
deleted_facts: Vec::new(),
replayed_memories: Vec::new(),
interference_events: Vec::new(),
weakened_memories: Vec::new(),
statistics: ConsolidationStats::default(),
};
for event in events {
match event {
ConsolidationEvent::MemoryStrengthened {
memory_id,
content_preview,
activation_before,
activation_after,
reason,
timestamp,
} => {
report.strengthened_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: format!("{:?}", reason),
at_risk: false,
timestamp: *timestamp,
});
report.statistics.memories_strengthened += 1;
}
ConsolidationEvent::MemoryDecayed {
memory_id,
content_preview,
activation_before,
activation_after,
at_risk,
timestamp,
} => {
report.decayed_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: "decay".to_string(),
at_risk: *at_risk,
timestamp: *timestamp,
});
report.statistics.memories_decayed += 1;
if *at_risk {
report.statistics.memories_at_risk += 1;
}
}
ConsolidationEvent::EdgeFormed {
from_memory_id,
to_memory_id,
initial_strength,
reason,
timestamp,
} => {
report.formed_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: None,
strength_after: *initial_strength,
co_activations: Some(1),
reason: format!("{:?}", reason),
timestamp: *timestamp,
});
report.statistics.edges_formed += 1;
}
ConsolidationEvent::EdgeStrengthened {
from_memory_id,
to_memory_id,
strength_before,
strength_after,
co_activations,
timestamp,
} => {
report.strengthened_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: Some(*strength_before),
strength_after: *strength_after,
co_activations: Some(*co_activations),
reason: "co_activation".to_string(),
timestamp: *timestamp,
});
report.statistics.edges_strengthened += 1;
}
ConsolidationEvent::EdgePotentiated {
from_memory_id,
to_memory_id,
final_strength,
total_co_activations,
timestamp,
} => {
report.potentiated_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: None,
strength_after: *final_strength,
co_activations: Some(*total_co_activations),
reason: "long_term_potentiation".to_string(),
timestamp: *timestamp,
});
report.statistics.edges_potentiated += 1;
}
ConsolidationEvent::EdgePruned {
from_memory_id,
to_memory_id,
final_strength,
reason,
timestamp,
} => {
report.pruned_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: Some(*final_strength),
strength_after: 0.0,
co_activations: None,
reason: format!("{:?}", reason),
timestamp: *timestamp,
});
report.statistics.edges_pruned += 1;
}
ConsolidationEvent::FactExtracted {
fact_id,
fact_content,
confidence,
source_memory_count,
fact_type,
timestamp,
} => {
report.extracted_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence,
support_count: *source_memory_count,
fact_type: fact_type.clone(),
timestamp: *timestamp,
});
report.statistics.facts_extracted += 1;
}
ConsolidationEvent::FactReinforced {
fact_id,
fact_content,
confidence_after,
new_support_count,
timestamp,
..
} => {
report.reinforced_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence_after,
support_count: *new_support_count,
fact_type: "reinforced".to_string(),
timestamp: *timestamp,
});
report.statistics.facts_reinforced += 1;
}
ConsolidationEvent::FactDecayed {
fact_id,
fact_content,
confidence_after,
days_since_reinforcement,
timestamp,
..
} => {
report.decayed_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence_after,
support_count: *days_since_reinforcement as usize,
fact_type: "decayed".to_string(),
timestamp: *timestamp,
});
report.statistics.facts_decayed += 1;
}
ConsolidationEvent::FactDeleted {
fact_id,
fact_content,
final_confidence,
support_count,
reason,
timestamp,
} => {
report.deleted_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *final_confidence,
support_count: *support_count,
fact_type: reason.clone(),
timestamp: *timestamp,
});
report.statistics.facts_deleted += 1;
}
ConsolidationEvent::MemoryPromoted { .. } => {
}
ConsolidationEvent::MaintenanceCycleCompleted { duration_ms, .. } => {
report.statistics.maintenance_cycles += 1;
report.statistics.total_maintenance_duration_ms += duration_ms;
}
ConsolidationEvent::MemoryReplayed {
memory_id,
content_preview,
activation_before,
activation_after,
replay_priority,
connected_memories_replayed,
timestamp,
} => {
report.replayed_memories.push(ReplayEvent {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
replay_priority: *replay_priority,
connected_memories: *connected_memories_replayed,
timestamp: *timestamp,
});
report.statistics.memories_replayed += 1;
report.statistics.total_replay_priority += replay_priority;
}
ConsolidationEvent::ReplayCycleCompleted {
memories_replayed,
total_priority_score,
..
} => {
report.statistics.replay_cycles += 1;
report.statistics.memories_replayed += memories_replayed;
report.statistics.total_replay_priority += total_priority_score;
}
ConsolidationEvent::InterferenceDetected {
new_memory_id,
old_memory_id,
similarity,
interference_type,
timestamp,
} => {
report.interference_events.push(InterferenceEvent {
new_memory_id: new_memory_id.clone(),
old_memory_id: old_memory_id.clone(),
similarity: *similarity,
interference_type: interference_type.clone(),
timestamp: *timestamp,
});
report.statistics.interference_events += 1;
}
ConsolidationEvent::MemoryWeakened {
memory_id,
content_preview,
activation_before,
activation_after,
interfering_memory_id,
interference_type,
timestamp,
} => {
report.weakened_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: format!(
"{:?} interference from {}",
interference_type, interfering_memory_id
),
at_risk: *activation_after < 0.1,
timestamp: *timestamp,
});
report.statistics.memories_weakened += 1;
}
ConsolidationEvent::RetrievalCompetition { .. } => {
report.statistics.retrieval_competitions += 1;
}
ConsolidationEvent::PatternTriggeredReplay { .. } => {
}
ConsolidationEvent::EntityPatternDetected { .. } => {
}
ConsolidationEvent::SemanticClusterFormed { .. } => {
}
ConsolidationEvent::TemporalClusterFormed { .. } => {
}
ConsolidationEvent::SalienceSpikeDetected { .. } => {
}
ConsolidationEvent::BehavioralChangeDetected { .. } => {
}
ConsolidationEvent::PatternDetected { .. } => {
}
ConsolidationEvent::EdgePromotionBoostApplied { .. } => {}
ConsolidationEvent::GraphOrphanDetected { .. } => {}
ConsolidationEvent::GraphAdjustedPromotion { .. } => {}
ConsolidationEvent::GraphDecayConsolidated { .. } => {}
}
}
report
}
pub fn generate_report_from_events(
events: &[ConsolidationEvent],
since: DateTime<Utc>,
until: DateTime<Utc>,
) -> ConsolidationReport {
let mut report = ConsolidationReport {
period: ReportPeriod {
start: since,
end: until,
},
strengthened_memories: Vec::new(),
decayed_memories: Vec::new(),
formed_associations: Vec::new(),
strengthened_associations: Vec::new(),
potentiated_associations: Vec::new(),
pruned_associations: Vec::new(),
extracted_facts: Vec::new(),
reinforced_facts: Vec::new(),
decayed_facts: Vec::new(),
deleted_facts: Vec::new(),
replayed_memories: Vec::new(),
interference_events: Vec::new(),
weakened_memories: Vec::new(),
statistics: ConsolidationStats::default(),
};
for event in events {
match event {
ConsolidationEvent::MemoryStrengthened {
memory_id,
content_preview,
activation_before,
activation_after,
reason,
timestamp,
} => {
report.strengthened_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: format!("{:?}", reason),
at_risk: false,
timestamp: *timestamp,
});
report.statistics.memories_strengthened += 1;
}
ConsolidationEvent::MemoryDecayed {
memory_id,
content_preview,
activation_before,
activation_after,
at_risk,
timestamp,
} => {
report.decayed_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: "decay".to_string(),
at_risk: *at_risk,
timestamp: *timestamp,
});
report.statistics.memories_decayed += 1;
if *at_risk {
report.statistics.memories_at_risk += 1;
}
}
ConsolidationEvent::EdgeFormed {
from_memory_id,
to_memory_id,
initial_strength,
reason,
timestamp,
} => {
report.formed_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: None,
strength_after: *initial_strength,
co_activations: Some(1),
reason: format!("{:?}", reason),
timestamp: *timestamp,
});
report.statistics.edges_formed += 1;
}
ConsolidationEvent::EdgeStrengthened {
from_memory_id,
to_memory_id,
strength_before,
strength_after,
co_activations,
timestamp,
} => {
report.strengthened_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: Some(*strength_before),
strength_after: *strength_after,
co_activations: Some(*co_activations),
reason: "co_activation".to_string(),
timestamp: *timestamp,
});
report.statistics.edges_strengthened += 1;
}
ConsolidationEvent::EdgePotentiated {
from_memory_id,
to_memory_id,
final_strength,
total_co_activations,
timestamp,
} => {
report.potentiated_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: None,
strength_after: *final_strength,
co_activations: Some(*total_co_activations),
reason: "long_term_potentiation".to_string(),
timestamp: *timestamp,
});
report.statistics.edges_potentiated += 1;
}
ConsolidationEvent::EdgePruned {
from_memory_id,
to_memory_id,
final_strength,
reason,
timestamp,
} => {
report.pruned_associations.push(AssociationChange {
from_memory_id: from_memory_id.clone(),
to_memory_id: to_memory_id.clone(),
strength_before: Some(*final_strength),
strength_after: 0.0,
co_activations: None,
reason: format!("{:?}", reason),
timestamp: *timestamp,
});
report.statistics.edges_pruned += 1;
}
ConsolidationEvent::FactExtracted {
fact_id,
fact_content,
confidence,
source_memory_count,
fact_type,
timestamp,
} => {
report.extracted_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence,
support_count: *source_memory_count,
fact_type: fact_type.clone(),
timestamp: *timestamp,
});
report.statistics.facts_extracted += 1;
}
ConsolidationEvent::FactReinforced {
fact_id,
fact_content,
confidence_after,
new_support_count,
timestamp,
..
} => {
report.reinforced_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence_after,
support_count: *new_support_count,
fact_type: "reinforced".to_string(),
timestamp: *timestamp,
});
report.statistics.facts_reinforced += 1;
}
ConsolidationEvent::FactDecayed {
fact_id,
fact_content,
confidence_after,
days_since_reinforcement,
timestamp,
..
} => {
report.decayed_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *confidence_after,
support_count: *days_since_reinforcement as usize,
fact_type: "decayed".to_string(),
timestamp: *timestamp,
});
report.statistics.facts_decayed += 1;
}
ConsolidationEvent::FactDeleted {
fact_id,
fact_content,
final_confidence,
support_count,
reason,
timestamp,
} => {
report.deleted_facts.push(FactChange {
fact_id: fact_id.clone(),
fact_content: fact_content.clone(),
confidence: *final_confidence,
support_count: *support_count,
fact_type: reason.clone(),
timestamp: *timestamp,
});
report.statistics.facts_deleted += 1;
}
ConsolidationEvent::MemoryPromoted { .. } => {
}
ConsolidationEvent::MaintenanceCycleCompleted { duration_ms, .. } => {
report.statistics.maintenance_cycles += 1;
report.statistics.total_maintenance_duration_ms += duration_ms;
}
ConsolidationEvent::MemoryReplayed {
memory_id,
content_preview,
activation_before,
activation_after,
replay_priority,
connected_memories_replayed,
timestamp,
} => {
report.replayed_memories.push(ReplayEvent {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
replay_priority: *replay_priority,
connected_memories: *connected_memories_replayed,
timestamp: *timestamp,
});
report.statistics.memories_replayed += 1;
report.statistics.total_replay_priority += replay_priority;
}
ConsolidationEvent::ReplayCycleCompleted {
memories_replayed,
total_priority_score,
..
} => {
report.statistics.replay_cycles += 1;
report.statistics.memories_replayed += memories_replayed;
report.statistics.total_replay_priority += total_priority_score;
}
ConsolidationEvent::InterferenceDetected {
new_memory_id,
old_memory_id,
similarity,
interference_type,
timestamp,
} => {
report.interference_events.push(InterferenceEvent {
new_memory_id: new_memory_id.clone(),
old_memory_id: old_memory_id.clone(),
similarity: *similarity,
interference_type: interference_type.clone(),
timestamp: *timestamp,
});
report.statistics.interference_events += 1;
}
ConsolidationEvent::MemoryWeakened {
memory_id,
content_preview,
activation_before,
activation_after,
interfering_memory_id,
interference_type,
timestamp,
} => {
report.weakened_memories.push(MemoryChange {
memory_id: memory_id.clone(),
content_preview: content_preview.clone(),
activation_before: *activation_before,
activation_after: *activation_after,
change_reason: format!(
"{:?} interference from {}",
interference_type, interfering_memory_id
),
at_risk: *activation_after < 0.1,
timestamp: *timestamp,
});
report.statistics.memories_weakened += 1;
}
ConsolidationEvent::RetrievalCompetition { .. } => {
report.statistics.retrieval_competitions += 1;
}
ConsolidationEvent::PatternTriggeredReplay { .. } => {}
ConsolidationEvent::EntityPatternDetected { .. } => {}
ConsolidationEvent::SemanticClusterFormed { .. } => {}
ConsolidationEvent::TemporalClusterFormed { .. } => {}
ConsolidationEvent::SalienceSpikeDetected { .. } => {}
ConsolidationEvent::BehavioralChangeDetected { .. } => {}
ConsolidationEvent::PatternDetected { .. } => {}
ConsolidationEvent::EdgePromotionBoostApplied { .. } => {}
ConsolidationEvent::GraphOrphanDetected { .. } => {}
ConsolidationEvent::GraphAdjustedPromotion { .. } => {}
ConsolidationEvent::GraphDecayConsolidated { .. } => {}
}
}
report
}
}
impl ConsolidationEvent {
pub fn timestamp(&self) -> DateTime<Utc> {
match self {
ConsolidationEvent::MemoryStrengthened { timestamp, .. } => *timestamp,
ConsolidationEvent::MemoryDecayed { timestamp, .. } => *timestamp,
ConsolidationEvent::EdgeFormed { timestamp, .. } => *timestamp,
ConsolidationEvent::EdgeStrengthened { timestamp, .. } => *timestamp,
ConsolidationEvent::EdgePotentiated { timestamp, .. } => *timestamp,
ConsolidationEvent::EdgePruned { timestamp, .. } => *timestamp,
ConsolidationEvent::FactExtracted { timestamp, .. } => *timestamp,
ConsolidationEvent::FactReinforced { timestamp, .. } => *timestamp,
ConsolidationEvent::FactDecayed { timestamp, .. } => *timestamp,
ConsolidationEvent::FactDeleted { timestamp, .. } => *timestamp,
ConsolidationEvent::MemoryPromoted { timestamp, .. } => *timestamp,
ConsolidationEvent::MaintenanceCycleCompleted { timestamp, .. } => *timestamp,
ConsolidationEvent::MemoryReplayed { timestamp, .. } => *timestamp,
ConsolidationEvent::ReplayCycleCompleted { timestamp, .. } => *timestamp,
ConsolidationEvent::InterferenceDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::MemoryWeakened { timestamp, .. } => *timestamp,
ConsolidationEvent::RetrievalCompetition { timestamp, .. } => *timestamp,
ConsolidationEvent::PatternTriggeredReplay { timestamp, .. } => *timestamp,
ConsolidationEvent::EntityPatternDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::SemanticClusterFormed { timestamp, .. } => *timestamp,
ConsolidationEvent::TemporalClusterFormed { timestamp, .. } => *timestamp,
ConsolidationEvent::SalienceSpikeDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::BehavioralChangeDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::PatternDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::EdgePromotionBoostApplied { timestamp, .. } => *timestamp,
ConsolidationEvent::GraphOrphanDetected { timestamp, .. } => *timestamp,
ConsolidationEvent::GraphAdjustedPromotion { timestamp, .. } => *timestamp,
ConsolidationEvent::GraphDecayConsolidated { timestamp, .. } => *timestamp,
}
}
pub fn is_significant(&self) -> bool {
matches!(
self,
ConsolidationEvent::EdgePotentiated { .. }
| ConsolidationEvent::FactExtracted { .. }
| ConsolidationEvent::FactDeleted { .. }
| ConsolidationEvent::FactReinforced { .. }
| ConsolidationEvent::InterferenceDetected { .. }
| ConsolidationEvent::MemoryReplayed { .. }
| ConsolidationEvent::MemoryPromoted { .. }
| ConsolidationEvent::ReplayCycleCompleted { .. }
| ConsolidationEvent::MaintenanceCycleCompleted { .. }
| ConsolidationEvent::PatternTriggeredReplay { .. }
| ConsolidationEvent::EntityPatternDetected { .. }
| ConsolidationEvent::SemanticClusterFormed { .. }
| ConsolidationEvent::SalienceSpikeDetected { .. }
| ConsolidationEvent::PatternDetected { .. }
| ConsolidationEvent::EdgePromotionBoostApplied { .. }
| ConsolidationEvent::GraphOrphanDetected { .. }
| ConsolidationEvent::GraphAdjustedPromotion { .. }
| ConsolidationEvent::GraphDecayConsolidated { .. }
)
}
}
impl Default for ConsolidationReport {
fn default() -> Self {
Self {
period: ReportPeriod {
start: Utc::now(),
end: Utc::now(),
},
strengthened_memories: Vec::new(),
decayed_memories: Vec::new(),
formed_associations: Vec::new(),
strengthened_associations: Vec::new(),
potentiated_associations: Vec::new(),
pruned_associations: Vec::new(),
extracted_facts: Vec::new(),
reinforced_facts: Vec::new(),
decayed_facts: Vec::new(),
deleted_facts: Vec::new(),
replayed_memories: Vec::new(),
interference_events: Vec::new(),
weakened_memories: Vec::new(),
statistics: ConsolidationStats::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_event_buffer_push() {
let mut buffer = ConsolidationEventBuffer::with_capacity(3);
for i in 0..5 {
buffer.push(ConsolidationEvent::MemoryDecayed {
memory_id: format!("mem-{}", i),
content_preview: format!("Memory {}", i),
activation_before: 0.5,
activation_after: 0.4,
at_risk: false,
timestamp: Utc::now(),
});
}
assert_eq!(buffer.len(), 3);
}
#[test]
fn test_generate_report() {
let mut buffer = ConsolidationEventBuffer::new();
let now = Utc::now();
buffer.push(ConsolidationEvent::MemoryStrengthened {
memory_id: "mem-1".to_string(),
content_preview: "Test memory".to_string(),
activation_before: 0.5,
activation_after: 0.7,
reason: StrengtheningReason::Recalled,
timestamp: now,
});
buffer.push(ConsolidationEvent::EdgeFormed {
from_memory_id: "mem-1".to_string(),
to_memory_id: "mem-2".to_string(),
initial_strength: 0.5,
reason: EdgeFormationReason::CoRetrieval,
timestamp: now,
});
let report = buffer.generate_report(
now - chrono::Duration::hours(1),
now + chrono::Duration::hours(1),
);
assert_eq!(report.statistics.memories_strengthened, 1);
assert_eq!(report.statistics.edges_formed, 1);
}
}