bctx_forge/budget/
policy.rs1use 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}