Skip to main content

microscope_memory/
no_learn.rs

1//! No-learn mode: measure without changing what is being measured.
2//!
3//! A `recall` is not a read. It records activations, strengthens co-activations,
4//! emits resonance pulses, refines attention weights, rewrites the narrative and
5//! stores that narrative as a memory. That is the learning, and it is the point
6//! of the system -- but it also means the act of measuring changes the state the
7//! next measurement starts from.
8//!
9//! Measured: replaying one query returned its top hit at L2=0.45051, then
10//! 0.25906, 0.20475, 0.17290 and 0.16108 across consecutive runs, while the
11//! pre-fetch confidence on that query climbed 62% -> 81% -> 98%. A single
12//! recall rewrote 17 files in the output directory. A benchmark built on that
13//! reports how often the system has been asked rather than what it knows, which
14//! is why the recorded recall figures were not reproducible: three runs of one
15//! unmodified binary gave R@1 of 37, 34 and 34.
16//!
17//! Setting `MICROSCOPE_NO_LEARN=1` returns from the recall as soon as the
18//! ranking is printed, before any learning state is written. The search is
19//! untouched -- the same blocks are scored, boosted and ranked, and the same
20//! numbers are printed -- so only the learning writes are skipped, and repeated
21//! runs against one index stop feeding each other.
22//!
23//! This is about the memory system only, and is unrelated to `[hooks] read_only`
24//! in the config, which governs the hook manager. Opt-in and off by default: a
25//! server that forgets a query it just served is broken, so nothing changes
26//! unless a measurement asks for it.
27
28/// True when the process must not write learning state.
29pub fn enabled() -> bool {
30    static ENABLED: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
31    *ENABLED.get_or_init(|| {
32        std::env::var("MICROSCOPE_NO_LEARN")
33            .map(|v| parse(&v))
34            .unwrap_or(false)
35    })
36}
37
38fn parse(v: &str) -> bool {
39    matches!(
40        v.trim().to_ascii_lowercase().as_str(),
41        "1" | "true" | "yes" | "on"
42    )
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn flag_accepts_the_usual_spellings_and_nothing_else() {
51        // The environment is read once per process, so the rule itself is what
52        // is under test, not the ambient value of the test runner.
53        for yes in ["1", "true", "TRUE", " yes ", "on"] {
54            assert!(parse(yes), "{yes:?} should enable read-only");
55        }
56        for no in ["0", "false", "", "maybe", "2"] {
57            assert!(!parse(no), "{no:?} should leave learning on");
58        }
59    }
60}