Skip to main content

second_brain_core/
decay.rs

1use anyhow::Result;
2use chrono::Utc;
3
4use crate::store::Store;
5
6pub struct DecayConfig {
7    pub rate_per_day: f32,
8    pub min_confidence: f32,
9    pub access_protection_factor: f32,
10}
11
12impl Default for DecayConfig {
13    fn default() -> Self {
14        Self {
15            rate_per_day: 0.01,
16            min_confidence: 0.05,
17            access_protection_factor: 0.1,
18        }
19    }
20}
21
22pub fn apply_decay<S: Store>(store: &S, config: &DecayConfig) -> Result<u32> {
23    let memories = store.memories_needing_decay(1)?;
24    let mut updated = 0;
25
26    for mut memory in memories {
27        let days_since_access = Utc::now()
28            .signed_duration_since(memory.last_accessed)
29            .num_hours() as f32
30            / 24.0;
31
32        let protection = (memory.access_count as f32 * config.access_protection_factor).min(0.5);
33        let effective_rate = config.rate_per_day * (1.0 - protection);
34        let decay_amount = effective_rate * days_since_access;
35
36        memory.confidence = (memory.confidence - decay_amount).max(config.min_confidence);
37        // invariant: confidence decay is per-machine and time-driven, so it must
38        // go through record_access and not enter the sync log.
39        store.record_access(&memory)?;
40        updated += 1;
41    }
42
43    Ok(updated)
44}