zeph_memory/
recall_view.rs1use crate::graph::types::GraphFact;
10use crate::types::MessageId;
11
12pub use zeph_common::memory::RecallView;
13
14#[derive(Debug, Clone)]
45pub struct RecalledFact {
46 pub fact: GraphFact,
48 pub activation_score: Option<f32>,
53 pub provenance_message_id: Option<MessageId>,
55 pub provenance_snippet: Option<String>,
57 pub neighbors: Vec<GraphFact>,
59}
60
61impl RecalledFact {
62 #[must_use]
64 pub fn from_graph_fact(fact: GraphFact) -> Self {
65 Self {
66 fact,
67 activation_score: None,
68 provenance_message_id: None,
69 provenance_snippet: None,
70 neighbors: Vec::new(),
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::graph::types::{EdgeType, GraphFact};
79 use crate::types::MessageId;
80
81 fn make_fact() -> GraphFact {
82 GraphFact {
83 entity_name: "Rust".to_string(),
84 relation: "uses".to_string(),
85 target_name: "LLVM".to_string(),
86 fact: "Rust uses LLVM".to_string(),
87 entity_match_score: 0.9,
88 hop_distance: 0,
89 confidence: 0.95,
90 valid_from: None,
91 edge_type: EdgeType::Semantic,
92 retrieval_count: 0,
93 edge_id: None,
94 }
95 }
96
97 #[test]
98 fn from_graph_fact_no_enrichment() {
99 let rf = RecalledFact::from_graph_fact(make_fact());
100 assert!(rf.activation_score.is_none());
101 assert!(rf.provenance_message_id.is_none());
102 assert!(rf.provenance_snippet.is_none());
103 assert!(rf.neighbors.is_empty());
104 }
105
106 #[test]
107 fn recall_view_default_is_head() {
108 assert_eq!(RecallView::default(), RecallView::Head);
109 }
110
111 fn head_fact() -> RecalledFact {
114 RecalledFact::from_graph_fact(GraphFact {
115 entity_name: "Rust".to_string(),
116 relation: "uses".to_string(),
117 target_name: "LLVM".to_string(),
118 fact: "Rust uses LLVM for code generation".to_string(),
119 entity_match_score: 0.9,
120 hop_distance: 0,
121 confidence: 0.95,
122 valid_from: Some("2026-01-01".to_string()),
123 edge_type: EdgeType::Semantic,
124 retrieval_count: 1,
125 edge_id: Some(10),
126 })
127 }
128
129 #[test]
130 fn snapshot_head_no_enrichment() {
131 let rf = head_fact();
132 insta::assert_debug_snapshot!("head_view", rf);
133 }
134
135 #[test]
136 fn snapshot_zoom_in_with_provenance() {
137 let mut rf = head_fact();
138 rf.provenance_message_id = Some(MessageId(42));
139 rf.provenance_snippet = Some("The Rust compiler uses LLVM as its backend".to_string());
140 insta::assert_debug_snapshot!("zoom_in_view", rf);
141 }
142
143 #[test]
144 fn snapshot_zoom_out_with_neighbors() {
145 let mut rf = head_fact();
146 rf.neighbors.push(GraphFact {
147 entity_name: "LLVM".to_string(),
148 relation: "supports".to_string(),
149 target_name: "WebAssembly".to_string(),
150 fact: "LLVM supports WebAssembly output".to_string(),
151 entity_match_score: 0.5,
152 hop_distance: 1,
153 confidence: 0.8,
154 valid_from: None,
155 edge_type: EdgeType::Semantic,
156 retrieval_count: 0,
157 edge_id: Some(11),
158 });
159 insta::assert_debug_snapshot!("zoom_out_view", rf);
160 }
161
162 #[test]
163 fn snapshot_sa_fact_with_activation_score() {
164 let rf = RecalledFact {
166 fact: GraphFact {
167 entity_name: String::new(),
168 relation: "uses".to_string(),
169 target_name: String::new(),
170 fact: "Rust uses LLVM for compilation".to_string(),
171 entity_match_score: 0.82,
172 hop_distance: 0,
173 confidence: 0.9,
174 valid_from: Some("2026-01-01".to_string()),
175 edge_type: EdgeType::Semantic,
176 retrieval_count: 0,
177 edge_id: Some(55),
178 },
179 activation_score: Some(0.82),
180 provenance_message_id: None,
181 provenance_snippet: None,
182 neighbors: Vec::new(),
183 };
184 insta::assert_debug_snapshot!("sa_head_view", rf);
185 }
186}