use crate::coherence::CoherenceEnergy;
use crate::execution::GateDecision;
use crate::governance::WitnessRecord;
use crate::types::{Hash, NodeId, Timestamp, WitnessId};
use super::error::RuvllmIntegrationResult;
use std::collections::HashMap;
pub trait CoherenceValidatable {
fn embedding(&self) -> &[f32];
fn embedding_dim(&self) -> usize {
self.embedding().len()
}
fn extract_claims(&self) -> Vec<Claim>;
fn metadata(&self) -> HashMap<String, String>;
fn content_id(&self) -> String;
}
#[derive(Debug, Clone)]
pub struct Claim {
pub id: String,
pub text: String,
pub embedding: Vec<f32>,
pub extraction_confidence: f32,
pub claim_type: ClaimType,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ClaimType {
Factual,
Causal,
Temporal,
Comparison,
Opinion,
Unknown,
}
pub trait ContextSource {
fn facts(&self) -> Vec<Fact>;
fn context_embedding(&self) -> &[f32];
fn scope_id(&self) -> String;
}
#[derive(Debug, Clone)]
pub struct Fact {
pub id: String,
pub node_id: Option<NodeId>,
pub embedding: Vec<f32>,
pub source: String,
pub confidence: f32,
}
#[derive(Debug, Clone)]
pub struct SemanticRelation {
pub relation_type: RelationType,
pub strength: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelationType {
Supports,
Contradicts,
Unrelated,
Extends,
Cites,
}
impl Claim {
pub fn relates_to(&self, fact: &Fact) -> Option<SemanticRelation> {
let similarity = cosine_similarity(&self.embedding, &fact.embedding);
if similarity > 0.7 {
Some(SemanticRelation {
relation_type: RelationType::Supports,
strength: similarity,
})
} else if similarity < 0.3 {
Some(SemanticRelation {
relation_type: RelationType::Contradicts,
strength: 1.0 - similarity,
})
} else {
None
}
}
}
pub trait UnifiedWitnessProvider {
fn create_generation_witness(
&mut self,
prompt: &str,
response: &str,
coherence_decision: &GateDecision,
coherence_witness: &WitnessRecord,
) -> RuvllmIntegrationResult<GenerationWitnessRef>;
fn get_witness(&self, id: &WitnessId) -> Option<&WitnessRecord>;
fn verify_chain_integrity(&self) -> RuvllmIntegrationResult<bool>;
fn chain_hash(&self) -> Hash;
}
#[derive(Debug, Clone)]
pub struct GenerationWitnessRef {
pub inference_id: String,
pub coherence_id: WitnessId,
pub combined_hash: Hash,
pub timestamp: Timestamp,
}
pub trait PatternBridge {
fn learn_success(
&mut self,
pattern_id: &str,
source_embedding: &[f32],
target_embedding: &[f32],
) -> RuvllmIntegrationResult<()>;
fn learn_failure(
&mut self,
pattern_id: &str,
source_embedding: &[f32],
target_embedding: &[f32],
failure_residual: &[f32],
) -> RuvllmIntegrationResult<()>;
fn get_restriction_map(&self, pattern_id: &str) -> Option<RestrictionMapRef>;
fn export_to_graph(&self) -> Vec<(String, RestrictionMapRef)>;
}
#[derive(Debug, Clone)]
pub struct RestrictionMapRef {
pub input_dim: usize,
pub output_dim: usize,
pub source_pattern: String,
pub training_count: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemoryType {
Agentic,
Working,
Episodic,
}
#[derive(Debug, Clone)]
pub struct MemoryEntry {
pub id: String,
pub memory_type: MemoryType,
pub embedding: Vec<f32>,
pub metadata: HashMap<String, String>,
pub timestamp: Timestamp,
}
pub trait MemoryCoherenceProvider {
fn add_with_coherence(&mut self, entry: MemoryEntry) -> RuvllmIntegrationResult<MemoryAddResult>;
fn check_coherence(&self, entry: &MemoryEntry) -> RuvllmIntegrationResult<f32>;
fn find_related(&self, entry: &MemoryEntry, limit: usize) -> Vec<String>;
fn memory_coherence_energy(&self) -> f32;
}
#[derive(Debug, Clone)]
pub struct MemoryAddResult {
pub memory_id: String,
pub node_id: NodeId,
pub energy: f32,
pub coherent: bool,
pub conflicts: Vec<String>,
}
pub trait ConfidenceSource {
fn confidence_from_energy(&self, energy: &CoherenceEnergy) -> ConfidenceResult;
fn threshold(&self) -> f32;
fn scale(&self) -> f32;
}
#[derive(Debug, Clone)]
pub struct ConfidenceResult {
pub value: f32,
pub explanation: String,
pub witness_backed: bool,
pub uncertainty_sources: Vec<UncertaintySource>,
}
#[derive(Debug, Clone)]
pub struct UncertaintySource {
pub description: String,
pub energy_contribution: f32,
}
fn cosine_similarity(a: &[f32], b: &[f32]) -> f32 {
if a.len() != b.len() || a.is_empty() {
return 0.0;
}
let dot: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
let norm_a: f32 = a.iter().map(|x| x * x).sum::<f32>().sqrt();
let norm_b: f32 = b.iter().map(|x| x * x).sum::<f32>().sqrt();
if norm_a == 0.0 || norm_b == 0.0 {
return 0.0;
}
dot / (norm_a * norm_b)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cosine_similarity() {
let a = vec![1.0, 0.0, 0.0];
let b = vec![1.0, 0.0, 0.0];
assert!((cosine_similarity(&a, &b) - 1.0).abs() < 0.001);
let c = vec![0.0, 1.0, 0.0];
assert!((cosine_similarity(&a, &c) - 0.0).abs() < 0.001);
}
#[test]
fn test_claim_type() {
assert_ne!(ClaimType::Factual, ClaimType::Opinion);
}
#[test]
fn test_relation_type() {
assert_ne!(RelationType::Supports, RelationType::Contradicts);
}
#[test]
fn test_memory_type() {
assert_ne!(MemoryType::Agentic, MemoryType::Working);
assert_ne!(MemoryType::Working, MemoryType::Episodic);
}
}