TDD: SessionCostBudget.record_cost() does not enforce budget limit — costs can be recorded beyond the configured cap without raising an exception #10467

Open
opened 2026-04-18 09:55:43 +00:00 by HAL9000 · 0 comments
Owner

Metadata

Field Value
Branch tdd/m6-session-cost-budget-record-cost-enforcement
Commit Message test(domain/cost_budget): add @tdd_expected_fail scenario for SessionCostBudget.record_cost not enforcing budget limit
Milestone v3.5.0

Background and Context

This is the TDD counterpart to the companion bug issue: SessionCostBudget.record_cost() does not enforce budget limit — costs can be recorded beyond the configured cap without raising an exception.

The SessionCostBudget class in src/cleveragents/domain/models/core/cost_budget.py is documented as enforcing a configurable maximum cost:

"Each tier independently tracks accumulated costs and enforces a configurable maximum. The tightest limit at any level wins: if a tool invocation would exceed any tier's budget, the request is denied."

However, the record_cost() method (lines 140–151) does not enforce this limit:

def record_cost(self, cost: float) -> None:
    """Add *cost* to the running total.

    Raises:
        TypeError: If *cost* is not numeric.
        ValueError: If *cost* is negative.
    """
    if not isinstance(cost, (int, float)):
        raise TypeError("cost must be a number")
    if cost < 0:
        raise ValueError("cost must be non-negative")
    self.total_cost += cost  # ← No check against max_cost_usd!

The would_exceed() method exists and correctly checks whether adding a cost would exceed the budget, but record_cost() never calls it. This means costs can be silently recorded beyond the configured cap, violating the domain's own invariant and the specification requirement that "Business rules must be enforced in domain layer, not application layer."

A failing test must be written that proves this bug exists before the fix is implemented.

Expected Behavior

A Behave scenario tagged @tdd_issue @tdd_issue_<N> @tdd_expected_fail should:

  1. Create a SessionCostBudget with max_cost_usd=10.0 and total_cost=9.0
  2. Call record_cost(5.0) — which would bring the total to 14.0, exceeding the 10.0 cap
  3. Assert that a domain-specific exception is raised (e.g., BudgetExceededError or ValueError with a budget-exceeded message)
  4. Assert that total_cost remains at 9.0 (the cost was not recorded)

This test must fail on the current codebase (because record_cost silently adds the cost without checking the budget), confirming the bug exists.

Acceptance Criteria

  • A Behave scenario exists tagged @tdd_issue, @tdd_issue_<N>, and @tdd_expected_fail
  • The scenario creates a SessionCostBudget near its limit and calls record_cost() with an amount that would exceed it
  • The scenario asserts that an appropriate exception is raised when the budget would be exceeded
  • The scenario fails on the current codebase (confirming the bug)
  • The scenario passes after the fix from the companion bug issue is applied
  • Step definitions are implemented (no placeholder pass statements)
  • All other existing tests continue to pass

Subtasks

  • Create or update a feature file (e.g., features/domain_cost_budget.feature) with a scenario tagged @tdd_issue @tdd_issue_<N> @tdd_expected_fail
  • Write the scenario: given a SessionCostBudget with max_cost_usd=10.0 and total_cost=9.0, when record_cost(5.0) is called, then an exception is raised and total_cost remains 9.0
  • Implement step definitions in the appropriate steps file
  • Verify the scenario fails on the current codebase (expected — confirms the bug)
  • Run nox -s unit_tests to confirm no regressions in other tests
  • Verify coverage ≥ 97% via nox -s coverage_report

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • The failing Behave scenario is committed on the tdd/m6-session-cost-budget-record-cost-enforcement branch.
  • The scenario is tagged correctly with @tdd_issue, @tdd_issue_<N>, and @tdd_expected_fail.
  • The scenario fails before the fix and passes after the fix from the companion bug issue is applied.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.

Automated by CleverAgents Bot
Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor


Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata | Field | Value | |---|---| | **Branch** | `tdd/m6-session-cost-budget-record-cost-enforcement` | | **Commit Message** | `test(domain/cost_budget): add @tdd_expected_fail scenario for SessionCostBudget.record_cost not enforcing budget limit` | | **Milestone** | v3.5.0 | ## Background and Context This is the TDD counterpart to the companion bug issue: **`SessionCostBudget.record_cost()` does not enforce budget limit — costs can be recorded beyond the configured cap without raising an exception**. The `SessionCostBudget` class in `src/cleveragents/domain/models/core/cost_budget.py` is documented as enforcing a configurable maximum cost: > "Each tier independently tracks accumulated costs and enforces a configurable maximum. The **tightest** limit at any level wins: if a tool invocation would exceed *any* tier's budget, the request is denied." However, the `record_cost()` method (lines 140–151) does not enforce this limit: ```python def record_cost(self, cost: float) -> None: """Add *cost* to the running total. Raises: TypeError: If *cost* is not numeric. ValueError: If *cost* is negative. """ if not isinstance(cost, (int, float)): raise TypeError("cost must be a number") if cost < 0: raise ValueError("cost must be non-negative") self.total_cost += cost # ← No check against max_cost_usd! ``` The `would_exceed()` method exists and correctly checks whether adding a cost would exceed the budget, but `record_cost()` never calls it. This means costs can be silently recorded beyond the configured cap, violating the domain's own invariant and the specification requirement that "Business rules must be enforced in domain layer, not application layer." A failing test must be written that proves this bug exists before the fix is implemented. ## Expected Behavior A Behave scenario tagged `@tdd_issue @tdd_issue_<N> @tdd_expected_fail` should: 1. Create a `SessionCostBudget` with `max_cost_usd=10.0` and `total_cost=9.0` 2. Call `record_cost(5.0)` — which would bring the total to 14.0, exceeding the 10.0 cap 3. Assert that a domain-specific exception is raised (e.g., `BudgetExceededError` or `ValueError` with a budget-exceeded message) 4. Assert that `total_cost` remains at 9.0 (the cost was not recorded) This test **must fail** on the current codebase (because `record_cost` silently adds the cost without checking the budget), confirming the bug exists. ## Acceptance Criteria - [ ] A Behave scenario exists tagged `@tdd_issue`, `@tdd_issue_<N>`, and `@tdd_expected_fail` - [ ] The scenario creates a `SessionCostBudget` near its limit and calls `record_cost()` with an amount that would exceed it - [ ] The scenario asserts that an appropriate exception is raised when the budget would be exceeded - [ ] The scenario **fails** on the current codebase (confirming the bug) - [ ] The scenario **passes** after the fix from the companion bug issue is applied - [ ] Step definitions are implemented (no placeholder `pass` statements) - [ ] All other existing tests continue to pass ## Subtasks - [ ] Create or update a feature file (e.g., `features/domain_cost_budget.feature`) with a scenario tagged `@tdd_issue @tdd_issue_<N> @tdd_expected_fail` - [ ] Write the scenario: given a `SessionCostBudget` with `max_cost_usd=10.0` and `total_cost=9.0`, when `record_cost(5.0)` is called, then an exception is raised and `total_cost` remains 9.0 - [ ] Implement step definitions in the appropriate steps file - [ ] Verify the scenario fails on the current codebase (expected — confirms the bug) - [ ] Run `nox -s unit_tests` to confirm no regressions in other tests - [ ] Verify coverage ≥ 97% via `nox -s coverage_report` ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - The failing Behave scenario is committed on the `tdd/m6-session-cost-budget-record-cost-enforcement` branch. - The scenario is tagged correctly with `@tdd_issue`, `@tdd_issue_<N>`, and `@tdd_expected_fail`. - The scenario fails before the fix and passes after the fix from the companion bug issue is applied. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. --- Automated by CleverAgents Bot Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor --- **Automated by CleverAgents Bot** Agent: new-issue-creator
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.

Dependencies

No dependencies set.

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