"""C-3 budget check for assist cost (TASK-11-02, REQ-IDEATE-07, C-3, D-012). Estimates the monthly assist cost per learner + compares against the C-3 target (≤ $3/active learner/month — relaxed for the Canada pilot per D-012, but the architecture must not preclude it). This is a DIAGNOSTIC check (not enforced — D-012 says no enforced ceiling in the pilot). It's logged at shift-end + reported in the P2 verification. The operator can review the log to understand the cost impact of assist usage. R-ASSIST-14 mitigation: the budget check helps the operator understand the cost impact of assist usage. If the total (practice + assist) exceeds $3, the `flag` is True (diagnostic — the pilot continues, but the operator is alerted). Example (from the plan): 20 turns/shift × 20 shifts/month = 400 extra LLM calls. At ~$0.0005/turn (gemma4:cloud pilot rates), that's ~$0.20/month — well under $3. But if the turns are longer or the model is more expensive, the cost could approach the ceiling. """ from __future__ import annotations from typing import Any # C-3 target: ≤ $3/active learner/month (relaxed for pilot per D-012, but the # architecture must not preclude it). C3_TARGET_USD = 3.0 def check_c3_budget( assist_turns_per_shift: int, shifts_per_month: int, cost_per_turn_cents: float, practice_cost_per_month_usd: float = 0.0, ) -> dict[str, Any]: """Estimate the monthly assist cost + compare against the C-3 target. Args: assist_turns_per_shift: average assist turns per shift. shifts_per_month: number of assist shifts per month. cost_per_turn_cents: average cost per assist turn (cents) — from derive_assist_turn_cost().derived_cents. practice_cost_per_month_usd: the existing practice cost/month (USD) — added to the assist cost to get the total. Default 0 (assist-only). Returns: { monthly_assist_cost: float (USD), practice_cost_per_month: float (USD), total_with_practice: float (USD), c3_target: 3.0, within_budget: bool, # total <= c3_target flag: bool, # total > c3_target (diagnostic — not enforced) turns_per_month: int, } D-012: the check is diagnostic (not enforced). `flag=True` means the total exceeds $3 — the operator is alerted, but the pilot continues. """ turns_per_month = assist_turns_per_shift * shifts_per_month # cost_per_turn_cents is in CENTS → divide by 100 for USD. monthly_assist_cost_usd = (turns_per_month * float(cost_per_turn_cents)) / 100.0 total_with_practice = monthly_assist_cost_usd + float(practice_cost_per_month_usd) within_budget = total_with_practice <= C3_TARGET_USD return { "monthly_assist_cost": round(monthly_assist_cost_usd, 4), "practice_cost_per_month": round(float(practice_cost_per_month_usd), 4), "total_with_practice": round(total_with_practice, 4), "c3_target": C3_TARGET_USD, "within_budget": within_budget, "flag": not within_budget, # flag=True if over budget (diagnostic) "turns_per_month": turns_per_month, } __all__ = ["check_c3_budget", "C3_TARGET_USD"]