Skip to main content

lean_ctx/core/context_kernel/
accounting_fix.rs

1//! Honest token accounting after all delivery-time additions.
2
3/// Honest token accounting that includes all additions and subtractions.
4///
5/// Compression measured before kernel enrichment and server decorations can
6/// overstate the savings visible to the LLM. This type records both views.
7#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
8pub struct PostDeliveryAccounting {
9    /// Tokens in the original raw content before any processing.
10    pub original_tokens: usize,
11    /// Tokens after compression but before kernel enrichment and decorations.
12    pub compressed_tokens: usize,
13    /// Tokens added by Context Kernel enrichment.
14    pub kernel_overhead_tokens: usize,
15    /// Tokens added by server decorations such as hints, headers, and footers.
16    pub decoration_tokens: usize,
17    /// Final tokens actually sent to the LLM.
18    pub delivered_tokens: usize,
19    /// True compression ratio: `(original - delivered) / original`.
20    pub actual_compression_ratio: f64,
21    /// Compression ratio reported before post-gate additions.
22    pub reported_compression_ratio: f64,
23    /// Reported minus actual compression, with negative values clamped to zero.
24    pub phantom_savings_pct: f64,
25}
26
27/// Validation of a savings claim against actual delivery data.
28#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
29pub struct SavingsValidation {
30    /// Tokens the system claimed it saved.
31    pub claimed_saved: usize,
32    /// Tokens actually saved, or zero when delivery met or exceeded the input.
33    pub actual_saved: usize,
34    /// Claimed savings exceeding actual savings.
35    pub phantom: usize,
36    /// Whether phantom savings are less than five percent of the original.
37    pub is_valid: bool,
38}
39
40/// Computes token accounting after kernel and server additions are included.
41pub fn compute_honest_accounting(
42    original: usize,
43    compressed: usize,
44    kernel_added: usize,
45    decorations: usize,
46) -> PostDeliveryAccounting {
47    let delivered = compressed
48        .saturating_add(kernel_added)
49        .saturating_add(decorations);
50    let (actual_ratio, reported_ratio) = if original == 0 {
51        (0.0, 0.0)
52    } else {
53        let original = original as f64;
54        (
55            (1.0 - delivered as f64 / original).clamp(-1.0, 1.0),
56            1.0 - compressed as f64 / original,
57        )
58    };
59
60    PostDeliveryAccounting {
61        original_tokens: original,
62        compressed_tokens: compressed,
63        kernel_overhead_tokens: kernel_added,
64        decoration_tokens: decorations,
65        delivered_tokens: delivered,
66        actual_compression_ratio: actual_ratio,
67        reported_compression_ratio: reported_ratio,
68        phantom_savings_pct: (reported_ratio - actual_ratio).max(0.0),
69    }
70}
71
72/// Validates claimed savings against the tokens actually sent to the LLM.
73pub fn validate_savings(claimed_saved: usize, original: usize, sent: usize) -> SavingsValidation {
74    let actual_saved = original.saturating_sub(sent);
75    let phantom = claimed_saved.saturating_sub(actual_saved);
76    let is_valid = phantom == 0 || (phantom as f64) < (original as f64 * 0.05);
77
78    SavingsValidation {
79        claimed_saved,
80        actual_saved,
81        phantom,
82        is_valid,
83    }
84}
85
86/// Formats a privacy-safe summary containing only token counts and ratios.
87pub fn format_honest_summary(accounting: &PostDeliveryAccounting) -> String {
88    format!(
89        "Original: {} → Compressed: {} → +Kernel: {} → +Decorations: {} → Delivered: {}\n\
90         Actual compression: {:.2}% (reported: {:.2}%, phantom: {:.2}%)",
91        accounting.original_tokens,
92        accounting.compressed_tokens,
93        accounting.kernel_overhead_tokens,
94        accounting.decoration_tokens,
95        accounting.delivered_tokens,
96        accounting.actual_compression_ratio * 100.0,
97        accounting.reported_compression_ratio * 100.0,
98        accounting.phantom_savings_pct * 100.0,
99    )
100}
101
102/// Returns whether post-compression additions make delivery exceed the input.
103pub fn detect_negative_savings(accounting: &PostDeliveryAccounting) -> bool {
104    accounting.delivered_tokens > accounting.original_tokens
105}
106
107/// Bridge: compute honest accounting from proxy request data.
108///
109/// Takes raw proxy metrics and produces a complete accounting record
110/// including phantom savings detection.
111pub fn account_proxy_request(
112    original_tokens: usize,
113    compressed_tokens: usize,
114    kernel_supplement_tokens: usize,
115    injection_overhead_tokens: usize,
116) -> PostDeliveryAccounting {
117    compute_honest_accounting(
118        original_tokens,
119        compressed_tokens,
120        kernel_supplement_tokens,
121        injection_overhead_tokens,
122    )
123}
124
125/// Formats a one-line accounting summary suitable for logging.
126pub fn format_proxy_accounting(accounting: &PostDeliveryAccounting) -> String {
127    format!(
128        "delivered={} actual={:.1}% reported={:.1}% phantom={:.1}%",
129        accounting.delivered_tokens,
130        accounting.actual_compression_ratio * 100.0,
131        accounting.reported_compression_ratio * 100.0,
132        accounting.phantom_savings_pct * 100.0,
133    )
134}
135
136/// Returns true if the accounting shows negative net savings (kernel adds
137/// more tokens than compression removes).
138pub fn has_negative_savings(accounting: &PostDeliveryAccounting) -> bool {
139    detect_negative_savings(accounting)
140}
141
142#[cfg(test)]
143mod tests {
144    use super::{
145        account_proxy_request, compute_honest_accounting, detect_negative_savings,
146        format_honest_summary, format_proxy_accounting, has_negative_savings, validate_savings,
147    };
148
149    fn assert_close(actual: f64, expected: f64) {
150        assert!((actual - expected).abs() < f64::EPSILON);
151    }
152
153    #[test]
154    fn honest_accounting_basic() {
155        let accounting = compute_honest_accounting(1_000, 300, 50, 20);
156
157        assert_eq!(accounting.delivered_tokens, 370);
158        assert_close(accounting.actual_compression_ratio, 0.63);
159        assert_close(accounting.reported_compression_ratio, 0.70);
160        assert_close(accounting.phantom_savings_pct, 0.07);
161    }
162
163    #[test]
164    fn phantom_savings_detected() {
165        let validation = validate_savings(500, 500, 500);
166
167        assert_eq!(validation.actual_saved, 0);
168        assert_eq!(validation.phantom, 500);
169        assert!(!validation.is_valid);
170    }
171
172    #[test]
173    fn negative_savings_when_kernel_dominates() {
174        let accounting = compute_honest_accounting(100, 80, 200, 0);
175
176        assert_eq!(accounting.delivered_tokens, 280);
177        assert_close(accounting.actual_compression_ratio, -1.0);
178        assert!(detect_negative_savings(&accounting));
179    }
180
181    #[test]
182    fn zero_original_safe() {
183        let accounting = compute_honest_accounting(0, 0, 10, 5);
184
185        assert_close(accounting.actual_compression_ratio, 0.0);
186        assert_close(accounting.reported_compression_ratio, 0.0);
187    }
188
189    #[test]
190    fn no_phantom_when_honest() {
191        let validation = validate_savings(500, 1_000, 500);
192
193        assert_eq!(validation.phantom, 0);
194        assert!(validation.is_valid);
195    }
196
197    #[test]
198    fn format_summary_no_content() {
199        let accounting = compute_honest_accounting(1_000, 300, 50, 20);
200        let summary = format_honest_summary(&accounting);
201
202        assert!(summary.contains("Original: 1000 → Compressed: 300"));
203        assert!(summary.contains("Actual compression: 63.00%"));
204        assert!(!summary.contains('/'));
205        assert!(!summary.contains("content"));
206    }
207
208    #[test]
209    fn kernel_overhead_visible() {
210        let accounting = compute_honest_accounting(1_000, 300, 50, 20);
211        let summary = format_honest_summary(&accounting);
212
213        assert_eq!(accounting.kernel_overhead_tokens, 50);
214        assert!(summary.contains("+Kernel: 50"));
215    }
216
217    #[test]
218    fn five_percent_phantom_is_invalid() {
219        let validation = validate_savings(55, 100, 50);
220
221        assert_eq!(validation.phantom, 5);
222        assert!(!validation.is_valid);
223    }
224
225    #[test]
226    fn account_proxy_standard() {
227        let accounting = account_proxy_request(1_000, 300, 50, 20);
228
229        assert_eq!(accounting.delivered_tokens, 370);
230        assert_close(accounting.actual_compression_ratio, 0.63);
231        assert_close(accounting.reported_compression_ratio, 0.70);
232        assert_close(accounting.phantom_savings_pct, 0.07);
233    }
234
235    #[test]
236    fn format_includes_all_fields() {
237        let accounting = account_proxy_request(1_000, 300, 50, 20);
238        let summary = format_proxy_accounting(&accounting);
239
240        assert!(summary.contains("delivered=370"));
241        assert!(summary.contains("actual=63.0%"));
242        assert!(summary.contains("reported=70.0%"));
243        assert!(summary.contains("phantom=7.0%"));
244    }
245
246    #[test]
247    fn negative_savings_detected() {
248        let accounting = account_proxy_request(100, 80, 30, 0);
249
250        assert!(has_negative_savings(&accounting));
251    }
252}