UAT: BudgetExhaustionEvent.budget_type validator only allows "plan" and "daily" — missing "session" and "org" types for three-tier budget hierarchy #5601

Open
opened 2026-04-09 07:45:02 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: cost-session-budgets-safety-profiles
Severity: Critical — audit trail for session/org budget violations cannot be persisted


What Was Tested

Code-level analysis of BudgetExhaustionEvent in cost_metadata.py vs the three-tier budget hierarchy in cost_budget_service.py.

Expected Behavior (from spec)

Per docs/reference/cost_controls.md:

"When a budget limit is reached, an exhaustion event is persisted to the plan's cost metadata with: Timestamp, Budget type (plan or daily), Limit amount, Used amount, Provider and model that triggered it"

The v3.6.0 milestone introduces a three-tier budget hierarchy: plan → session → org. When a session or org budget is exceeded, an exhaustion event should be persisted with the appropriate budget type.

Actual Behavior (from code analysis)

src/cleveragents/domain/models/core/cost_metadata.pyBudgetExhaustionEvent.validate_budget_type():

@field_validator("budget_type")
@classmethod
def validate_budget_type(cls: type[BudgetExhaustionEvent], v: str) -> str:
    allowed = {"plan", "daily"}  # ← Only "plan" and "daily" allowed
    if v not in allowed:
        raise ValueError(f"budget_type must be one of {allowed}, got {v!r}")
    return v

The validator only allows "plan" and "daily" budget types. However, the new CostBudgetService (v3.6.0) introduces session and org budget tiers. When a session or org budget is exceeded, there is no way to persist a BudgetExhaustionEvent with budget_type="session" or budget_type="org".

This means:

  1. Session budget violations cannot be recorded in the audit log
  2. Org budget violations cannot be recorded in the audit log
  3. The budget_exhaustion_events field in CostMetadata is incomplete for the new three-tier system

Code Locations

  • src/cleveragents/domain/models/core/cost_metadata.pyBudgetExhaustionEvent.validate_budget_type() (line ~55)
  • src/cleveragents/domain/models/core/cost_budget.pyBudgetLevel enum defines PLAN, SESSION, ORG
  • src/cleveragents/application/services/cost_budget_service.pycheck_budget_hierarchy() returns BudgetCheckResult with exceeded_level of BudgetLevel.SESSION or BudgetLevel.ORG

Steps to Reproduce

from cleveragents.domain.models.core.cost_metadata import BudgetExhaustionEvent

# This raises ValueError — cannot record session budget violation
event = BudgetExhaustionEvent(
    budget_type="session",  # ← Raises: budget_type must be one of {'plan', 'daily'}
    limit=10.0,
    used=15.0,
)

Fix Suggestion

Update validate_budget_type to allow all three-tier budget types:

allowed = {"plan", "daily", "session", "org"}

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area**: cost-session-budgets-safety-profiles **Severity**: Critical — audit trail for session/org budget violations cannot be persisted --- ## What Was Tested Code-level analysis of `BudgetExhaustionEvent` in `cost_metadata.py` vs the three-tier budget hierarchy in `cost_budget_service.py`. ## Expected Behavior (from spec) Per `docs/reference/cost_controls.md`: > "When a budget limit is reached, an exhaustion event is persisted to the plan's cost metadata with: Timestamp, Budget type (plan or daily), Limit amount, Used amount, Provider and model that triggered it" The v3.6.0 milestone introduces a **three-tier budget hierarchy**: plan → session → org. When a session or org budget is exceeded, an exhaustion event should be persisted with the appropriate budget type. ## Actual Behavior (from code analysis) `src/cleveragents/domain/models/core/cost_metadata.py` — `BudgetExhaustionEvent.validate_budget_type()`: ```python @field_validator("budget_type") @classmethod def validate_budget_type(cls: type[BudgetExhaustionEvent], v: str) -> str: allowed = {"plan", "daily"} # ← Only "plan" and "daily" allowed if v not in allowed: raise ValueError(f"budget_type must be one of {allowed}, got {v!r}") return v ``` The validator **only allows "plan" and "daily"** budget types. However, the new `CostBudgetService` (v3.6.0) introduces session and org budget tiers. When a session or org budget is exceeded, there is no way to persist a `BudgetExhaustionEvent` with `budget_type="session"` or `budget_type="org"`. This means: 1. Session budget violations cannot be recorded in the audit log 2. Org budget violations cannot be recorded in the audit log 3. The `budget_exhaustion_events` field in `CostMetadata` is incomplete for the new three-tier system ## Code Locations - `src/cleveragents/domain/models/core/cost_metadata.py` — `BudgetExhaustionEvent.validate_budget_type()` (line ~55) - `src/cleveragents/domain/models/core/cost_budget.py` — `BudgetLevel` enum defines `PLAN`, `SESSION`, `ORG` - `src/cleveragents/application/services/cost_budget_service.py` — `check_budget_hierarchy()` returns `BudgetCheckResult` with `exceeded_level` of `BudgetLevel.SESSION` or `BudgetLevel.ORG` ## Steps to Reproduce ```python from cleveragents.domain.models.core.cost_metadata import BudgetExhaustionEvent # This raises ValueError — cannot record session budget violation event = BudgetExhaustionEvent( budget_type="session", # ← Raises: budget_type must be one of {'plan', 'daily'} limit=10.0, used=15.0, ) ``` ## Fix Suggestion Update `validate_budget_type` to allow all three-tier budget types: ```python allowed = {"plan", "daily", "session", "org"} ``` --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.6.0 milestone 2026-04-09 07:45:34 +00:00
Author
Owner

🏷️ Label Fix Applied by Backlog Groomer

The State/Verified label has been added to this issue.

Reason: During a routine backlog grooming pass, this issue was found to have Type/Bug and a Priority/ label but was missing a State/* label entirely — a violation of the CONTRIBUTING.md requirement that every issue must have exactly one State/ label.

Since this issue has been triaged with a priority and type, State/Verified is the appropriate state: the issue has been confirmed as legitimate and is now part of the active backlog.

No other changes were made.


Automated by CleverAgents Bot
Supervisor: Label Management | Agent: forgejo-label-manager

## 🏷️ Label Fix Applied by Backlog Groomer The `State/Verified` label has been added to this issue. **Reason**: During a routine backlog grooming pass, this issue was found to have `Type/Bug` and a `Priority/` label but was missing a `State/*` label entirely — a violation of the CONTRIBUTING.md requirement that every issue must have exactly one `State/` label. Since this issue has been triaged with a priority and type, `State/Verified` is the appropriate state: the issue has been confirmed as legitimate and is now part of the active backlog. No other changes were made. --- **Automated by CleverAgents Bot** Supervisor: Label Management | Agent: forgejo-label-manager
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#5601
No description provided.