UAT: CRP ContextBudget base class has weaker validation than spec — allows max_tokens=0 and reserved_tokens == max_tokens #4839

Open
opened 2026-04-08 20:06:36 +00:00 by HAL9000 · 0 comments
Owner

Bug Report

Feature Area: ACMS — Context Request Protocol (CRP), ContextBudget model

Severity: Medium — the CRP base class has two validation gaps that allow invalid budget configurations; code using the CRP model directly (not the core model) will silently accept invalid inputs

What Was Tested

Code-level analysis comparing src/cleveragents/domain/models/acms/crp.py against the spec (docs/reference/acms.md) and the core model (src/cleveragents/domain/models/core/context_fragment.py).

Expected Behavior (from spec)

From docs/reference/acms.md:

  • max_tokens -- Maximum total tokens (default 4096, must be >= 1)
  • reserved_tokens -- Tokens reserved for system prompt (default 512, must be >= 0)
  • Validation: reserved_tokens must be strictly less than max_tokens.

Actual Behavior

src/cleveragents/domain/models/acms/crp.py ContextBudget:

class ContextBudget(BaseModel, frozen=True):
    max_tokens: int = Field(
        ...,
        ge=0,          # ❌ allows 0 — spec says must be >= 1
        description="Maximum total token budget (>= 0)",
    )
    reserved_tokens: int = Field(
        default=0,
        ge=0,
        description="Reserved tokens (<= `max_tokens`)",
    )

    @model_validator(mode="after")
    def _validate_reservation(self) -> ContextBudget:
        if self.reserved_tokens > self.max_tokens:   # ❌ allows equal — spec says strictly less than
            raise ValueError("reserved_tokens cannot exceed max_tokens")
        return self

src/cleveragents/domain/models/core/context_fragment.py ContextBudget (correct):

class ContextBudget(CRPContextBudget, frozen=True):
    max_tokens: int = Field(ge=1, default=4096)   # ✅ correct: ge=1
    reserved_tokens: int = Field(ge=0, default=512)

    @model_validator(mode="after")
    def _check_reserved_within_max(self) -> ContextBudget:
        if self.reserved_tokens >= self.max_tokens:  # ✅ correct: >= (strictly less than)
            raise ValueError(...)
        return self

Specific Gaps

Field CRP base class Spec requirement Core model
max_tokens constraint ge=0 (allows 0) >= 1 ge=1
reserved_tokens validation > max_tokens raises (allows equal) strictly less than >= max_tokens raises
max_tokens default no default (required) 4096 default=4096

Impact

  • ContextBudget(max_tokens=0) is accepted by the CRP base class — available_tokens would be 0, causing division-by-zero in budget_used calculation in ACMSPipeline.assemble()
  • ContextBudget(max_tokens=100, reserved_tokens=100) is accepted by the CRP base class — available_tokens would be 0, causing the pipeline to produce empty context without error
  • Code using from cleveragents.domain.models.acms.crp import ContextBudget directly (not the core model) will have these weaker validations

Code Locations

  • src/cleveragents/domain/models/acms/crp.py — CRP base class (wrong)
  • src/cleveragents/domain/models/core/context_fragment.py — core model (correct)

Fix Required

Update src/cleveragents/domain/models/acms/crp.py ContextBudget:

class ContextBudget(BaseModel, frozen=True):
    max_tokens: int = Field(
        ...,
        ge=1,          # Fix: spec says must be >= 1
        description="Maximum total token budget (>= 1)",
    )
    reserved_tokens: int = Field(
        default=0,
        ge=0,
        description="Reserved tokens (strictly less than max_tokens)",
    )

    @model_validator(mode="after")
    def _validate_reservation(self) -> ContextBudget:
        if self.reserved_tokens >= self.max_tokens:  # Fix: spec says strictly less than
            raise ValueError(
                f"reserved_tokens ({self.reserved_tokens}) must be strictly less than "
                f"max_tokens ({self.max_tokens})"
            )
        return self

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

## Bug Report **Feature Area:** ACMS — Context Request Protocol (CRP), `ContextBudget` model **Severity:** Medium — the CRP base class has two validation gaps that allow invalid budget configurations; code using the CRP model directly (not the core model) will silently accept invalid inputs ### What Was Tested Code-level analysis comparing `src/cleveragents/domain/models/acms/crp.py` against the spec (`docs/reference/acms.md`) and the core model (`src/cleveragents/domain/models/core/context_fragment.py`). ### Expected Behavior (from spec) From `docs/reference/acms.md`: > - `max_tokens` -- Maximum total tokens (default 4096, **must be >= 1**) > - `reserved_tokens` -- Tokens reserved for system prompt (default 512, must be >= 0) > - **Validation: `reserved_tokens` must be strictly less than `max_tokens`.** ### Actual Behavior **`src/cleveragents/domain/models/acms/crp.py` `ContextBudget`:** ```python class ContextBudget(BaseModel, frozen=True): max_tokens: int = Field( ..., ge=0, # ❌ allows 0 — spec says must be >= 1 description="Maximum total token budget (>= 0)", ) reserved_tokens: int = Field( default=0, ge=0, description="Reserved tokens (<= `max_tokens`)", ) @model_validator(mode="after") def _validate_reservation(self) -> ContextBudget: if self.reserved_tokens > self.max_tokens: # ❌ allows equal — spec says strictly less than raise ValueError("reserved_tokens cannot exceed max_tokens") return self ``` **`src/cleveragents/domain/models/core/context_fragment.py` `ContextBudget` (correct):** ```python class ContextBudget(CRPContextBudget, frozen=True): max_tokens: int = Field(ge=1, default=4096) # ✅ correct: ge=1 reserved_tokens: int = Field(ge=0, default=512) @model_validator(mode="after") def _check_reserved_within_max(self) -> ContextBudget: if self.reserved_tokens >= self.max_tokens: # ✅ correct: >= (strictly less than) raise ValueError(...) return self ``` ### Specific Gaps | Field | CRP base class | Spec requirement | Core model | |---|---|---|---| | `max_tokens` constraint | `ge=0` (allows 0) | `>= 1` | `ge=1` ✅ | | `reserved_tokens` validation | `> max_tokens` raises (allows equal) | strictly less than | `>= max_tokens` raises ✅ | | `max_tokens` default | no default (required) | 4096 | `default=4096` ✅ | ### Impact - `ContextBudget(max_tokens=0)` is accepted by the CRP base class — `available_tokens` would be 0, causing division-by-zero in `budget_used` calculation in `ACMSPipeline.assemble()` - `ContextBudget(max_tokens=100, reserved_tokens=100)` is accepted by the CRP base class — `available_tokens` would be 0, causing the pipeline to produce empty context without error - Code using `from cleveragents.domain.models.acms.crp import ContextBudget` directly (not the core model) will have these weaker validations ### Code Locations - `src/cleveragents/domain/models/acms/crp.py` — CRP base class (wrong) - `src/cleveragents/domain/models/core/context_fragment.py` — core model (correct) ### Fix Required Update `src/cleveragents/domain/models/acms/crp.py` `ContextBudget`: ```python class ContextBudget(BaseModel, frozen=True): max_tokens: int = Field( ..., ge=1, # Fix: spec says must be >= 1 description="Maximum total token budget (>= 1)", ) reserved_tokens: int = Field( default=0, ge=0, description="Reserved tokens (strictly less than max_tokens)", ) @model_validator(mode="after") def _validate_reservation(self) -> ContextBudget: if self.reserved_tokens >= self.max_tokens: # Fix: spec says strictly less than raise ValueError( f"reserved_tokens ({self.reserved_tokens}) must be strictly less than " f"max_tokens ({self.max_tokens})" ) return self ``` --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.5.0 milestone 2026-04-08 20:18:42 +00:00
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#4839
No description provided.