// daemon.rs — graph health metrics // // Compute graph health statistics for the TUI (F4 hippocampus screen). // The background daemon and RPC infrastructure have been removed; // graph maintenance agents now run within the consciousness binary. /// Graph health snapshot for the hippocampus TUI screen. #[derive(Clone, Default, serde::Serialize, serde::Deserialize)] pub struct GraphHealth { pub nodes: usize, pub edges: usize, pub communities: usize, pub alpha: f32, // power-law exponent (target ≥2.5) pub gini: f32, // degree inequality (target ≤0.4) pub avg_cc: f32, // clustering coefficient (target ≥0.2) pub sigma: f32, // small-world sigma pub episodic_ratio: f32, // episodic/total nodes (target <0.4) pub interference: usize, // interfering pairs (target <50) // Consolidation work estimate from plan #[serde(default)] pub plan_counts: std::collections::HashMap, pub plan_rationale: Vec, pub computed_at: String, } pub fn compute_graph_health(store: &crate::store::Store) -> GraphHealth { let graph = store.build_graph(); let snap = crate::graph::current_metrics(&graph); let episodic_count = store.nodes.iter() .filter(|(_, n)| matches!(n.node_type, crate::store::NodeType::EpisodicSession)) .count(); let episodic_ratio = if store.nodes.is_empty() { 0.0 } else { episodic_count as f32 / store.nodes.len() as f32 }; // Use the same planning logic as consolidation (skip O(n²) interference) let plan = crate::neuro::consolidation_plan_quick(store); GraphHealth { nodes: snap.nodes, edges: snap.edges, communities: snap.communities, alpha: snap.alpha, gini: snap.gini, avg_cc: snap.avg_cc, sigma: snap.sigma, episodic_ratio, interference: 0, plan_counts: plan.counts, plan_rationale: plan.rationale, computed_at: crate::store::format_datetime_space(crate::store::now_epoch()), } }