Skip to main content

bctx_forge/budget/
policy.rs

1use super::{BudgetPressure, SignalBudget};
2
3#[derive(Debug, Clone)]
4pub enum PolicyAction {
5    Allow,
6    SoftWarn(String),
7    AutoTrim { keep_lines: usize },
8    Reject(String),
9}
10
11pub struct BudgetPolicy {
12    pub hard_cap: usize,
13    pub warn_at_pct: f64,
14    pub trim_at_pct: f64,
15}
16
17impl BudgetPolicy {
18    pub fn default_policy() -> Self {
19        Self {
20            hard_cap: 8_000,
21            warn_at_pct: 0.65,
22            trim_at_pct: 0.85,
23        }
24    }
25
26    pub fn evaluate(&self, budget: &SignalBudget, incoming_tokens: usize) -> PolicyAction {
27        let projected = budget.used + incoming_tokens;
28        let projected_pct = projected as f64 / self.hard_cap as f64;
29
30        if projected > self.hard_cap {
31            return PolicyAction::Reject(format!(
32                "budget overflow: {projected} > {}",
33                self.hard_cap
34            ));
35        }
36
37        match budget.pressure() {
38            BudgetPressure::Overflow | BudgetPressure::Critical => {
39                let keep = (self.hard_cap.saturating_sub(budget.used)) / 4;
40                PolicyAction::AutoTrim {
41                    keep_lines: keep.max(5),
42                }
43            }
44            BudgetPressure::Elevated => {
45                PolicyAction::SoftWarn(format!("context at {:.0}% capacity", projected_pct * 100.0))
46            }
47            BudgetPressure::Calm => PolicyAction::Allow,
48        }
49    }
50}