Skip to main content

lean_ctx/core/shadow/
baseline.rs

1//! Baseline simulation without LeanCTX optimizations.
2
3use crate::core::{
4    shadow::recommendation::ShadowTask,
5    value_gate::{OutcomeSignal, TaskOutcome, cost_tracker::calculate_cost},
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct BaselineMeasurement {
10    pub task_id: String,
11    pub input_tokens: u64,
12    pub output_tokens: u64,
13    pub model: String,
14    pub total_cost_micros: u64,
15    pub duration_ms: u64,
16    pub outcome_accepted: bool,
17}
18
19/// The same task without context reduction: uncompressed input, priced with the model the host
20/// actually chose for this task. The model is never swapped for a configured reference model —
21/// LeanCTX does not choose models, so a price difference between models is not a LeanCTX saving.
22pub fn simulate_baseline(task: &ShadowTask) -> BaselineMeasurement {
23    let accepted = accepted(&task.task_id, &task.outcome_signals);
24    BaselineMeasurement {
25        task_id: task.task_id.clone(),
26        input_tokens: task.raw_input_tokens,
27        output_tokens: task.output_tokens,
28        model: task.model_used.clone(),
29        total_cost_micros: calculate_cost(
30            task.raw_input_tokens,
31            task.output_tokens,
32            0,
33            &task.model_used,
34        ),
35        duration_ms: task.duration_ms,
36        outcome_accepted: accepted,
37    }
38}
39
40pub(crate) fn accepted(task_id: &str, signals: &[OutcomeSignal]) -> bool {
41    crate::core::value_gate::outcome_evaluator::evaluate(&TaskOutcome {
42        task_id: task_id.into(),
43        completed: true,
44        signals: signals.to_vec(),
45    })
46}