Skip to main content

lean_ctx/core/knowledge/
fact.rs

1use chrono::{DateTime, Utc};
2
3use super::types::KnowledgeFact;
4
5impl KnowledgeFact {
6    pub fn is_current(&self) -> bool {
7        self.valid_until.is_none()
8    }
9
10    /// Stable, intrinsic quality metric (0.0..1.0).
11    ///
12    /// Based only on confidence, confirmation count, and feedback balance.
13    /// Deliberately excludes volatile signals (retrieval count, recency) to
14    /// keep recall output deterministic. For display ordering use
15    /// `salience_score()` which adds recency and category weighting.
16    pub fn quality_score(&self) -> f32 {
17        let confidence = self.confidence.clamp(0.0, 1.0);
18        let confirmations_norm = (self.confirmation_count.min(5) as f32) / 5.0;
19        let balance = self.feedback_up as i32 - self.feedback_down as i32;
20        let feedback_effect = (balance as f32 / 4.0).tanh() * 0.1;
21
22        // IMPORTANT: quality_score must be stable across repeated recall calls.
23        // Retrieval signals (retrieval_count/last_retrieved) are persisted, but should not change
24        // the displayed "quality" score, otherwise recall output becomes non-deterministic.
25        (0.8 * confidence + 0.2 * confirmations_norm + feedback_effect).clamp(0.0, 1.0)
26    }
27
28    pub fn was_valid_at(&self, at: DateTime<Utc>) -> bool {
29        let after_start = self.valid_from.is_none_or(|from| at >= from);
30        let before_end = self.valid_until.is_none_or(|until| at <= until);
31        after_start && before_end
32    }
33}