Skip to main content

lean_ctx/core/context_kernel/
adaptive_bridge.rs

1//! Adaptive compression signals exposed through the Context Kernel.
2
3use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
4
5use super::kernel_config;
6
7static BOUNCE_RATE_BITS: AtomicU64 = AtomicU64::new(0.0_f64.to_bits());
8static SIGNALS_RECEIVED: AtomicUsize = AtomicUsize::new(0);
9
10/// Kernel-level recommendation for adjusting compression depth.
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize)]
12pub enum KernelCompressionAdvice {
13    /// No change to current compression.
14    #[default]
15    Maintain,
16    /// Reduce compression because users are bouncing too often.
17    Reduce,
18    /// Increase compression because users accept compressed output.
19    Increase,
20}
21
22/// Snapshot of the kernel's adaptive compression signal state.
23#[derive(Debug, Clone, Default, serde::Serialize)]
24pub struct AdaptiveSummary {
25    /// Most recently observed bounce rate.
26    pub current_bounce_rate: f64,
27    /// Compression adjustment advised by the current signal.
28    pub advice: KernelCompressionAdvice,
29    /// Number of bounce-rate signals recorded since the last reset.
30    pub signals_received: usize,
31}
32
33/// Advises how compression should change for a measured bounce rate.
34#[must_use]
35pub fn compression_advice(bounce_rate: f64) -> KernelCompressionAdvice {
36    if !kernel_config::is_enabled() {
37        return KernelCompressionAdvice::Maintain;
38    }
39    if bounce_rate > 0.3 {
40        KernelCompressionAdvice::Reduce
41    } else if bounce_rate < 0.05 {
42        KernelCompressionAdvice::Increase
43    } else {
44        KernelCompressionAdvice::Maintain
45    }
46}
47
48/// Stores the latest bounce-rate signal for kernel consumers.
49pub fn update_bounce_signal(bounce_rate: f64) {
50    BOUNCE_RATE_BITS.store(bounce_rate.to_bits(), Ordering::Relaxed);
51    SIGNALS_RECEIVED.fetch_add(1, Ordering::Relaxed);
52}
53
54/// Returns the most recently stored bounce rate.
55#[must_use]
56pub fn current_bounce_rate() -> f64 {
57    f64::from_bits(BOUNCE_RATE_BITS.load(Ordering::Relaxed))
58}
59
60/// Returns the current adaptive compression state.
61#[must_use]
62pub fn adaptive_summary() -> AdaptiveSummary {
63    let current_bounce_rate = current_bounce_rate();
64    AdaptiveSummary {
65        current_bounce_rate,
66        advice: compression_advice(current_bounce_rate),
67        signals_received: SIGNALS_RECEIVED.load(Ordering::Relaxed),
68    }
69}
70
71/// Clears all adaptive compression signal state.
72pub fn reset() {
73    BOUNCE_RATE_BITS.store(0.0_f64.to_bits(), Ordering::Relaxed);
74    SIGNALS_RECEIVED.store(0, Ordering::Relaxed);
75}
76
77#[cfg(test)]
78mod tests {
79    use super::{
80        KernelCompressionAdvice, adaptive_summary, compression_advice, reset, update_bounce_signal,
81    };
82    use crate::core::context_kernel::kernel_config::{self, KernelFeatures};
83
84    fn setup() -> std::sync::MutexGuard<'static, ()> {
85        let guard = kernel_config::KERNEL_TEST_LOCK
86            .lock()
87            .unwrap_or_else(std::sync::PoisonError::into_inner);
88        kernel_config::reset_features();
89        reset();
90        guard
91    }
92
93    #[test]
94    fn high_bounce_advises_reduce() {
95        let _guard = setup();
96        assert_eq!(compression_advice(0.5), KernelCompressionAdvice::Reduce);
97    }
98
99    #[test]
100    fn low_bounce_advises_increase() {
101        let _guard = setup();
102        assert_eq!(compression_advice(0.01), KernelCompressionAdvice::Increase);
103    }
104
105    #[test]
106    fn moderate_bounce_maintains() {
107        let _guard = setup();
108        assert_eq!(compression_advice(0.15), KernelCompressionAdvice::Maintain);
109    }
110
111    #[test]
112    fn disabled_kernel_always_maintains() {
113        let _guard = setup();
114        let features = KernelFeatures {
115            enabled: false,
116            ..KernelFeatures::default()
117        };
118        kernel_config::update_features(features);
119        assert_eq!(compression_advice(0.9), KernelCompressionAdvice::Maintain);
120    }
121
122    #[test]
123    fn summary_reports_latest_signal_and_count() {
124        let _guard = setup();
125        update_bounce_signal(0.4);
126        update_bounce_signal(0.2);
127        let summary = adaptive_summary();
128        assert_eq!(summary.current_bounce_rate, 0.2);
129        assert_eq!(summary.advice, KernelCompressionAdvice::Maintain);
130        assert_eq!(summary.signals_received, 2);
131    }
132}