BUG-HUNT: [concurrency] autonomy_guardrails.py GuardrailAuditTrail _allowed_count/_denied_count are class variables not instance variables — shared across all instances #7496

Open
opened 2026-04-10 20:49:54 +00:00 by HAL9000 · 1 comment
Owner

Bug Report: Concurrency/Data Integrity — GuardrailAuditTrail Private Counters Are Class Variables, Shared Across All Instances

Severity Assessment

  • Impact: All GuardrailAuditTrail instances share the same _allowed_count and _denied_count counters — mutations in one plan's audit trail corrupt statistics for all other plans
  • Likelihood: High — affects every deployment with more than one active plan
  • Priority: High

Location

  • File: src/cleveragents/domain/models/core/autonomy_guardrails.py
  • Function: GuardrailAuditTrail class body
  • Lines: ~104–106
  • Category: data-integrity / concurrency

Description

In Pydantic v2, private attributes must be declared with PrivateAttr(). Using a plain class-level annotation with a default value creates a class variable shared across ALL instances, not per-instance fields. This means every GuardrailAuditTrail instance shares the same _allowed_count and _denied_count, so incrementing the counter in one plan's audit trail changes the statistics for all plans.

Evidence

class GuardrailAuditTrail(BaseModel):
    ...
    _allowed_count: int = 0   # ← class variable in Pydantic v2, NOT instance variable
    _denied_count: int = 0    # ← class variable in Pydantic v2, NOT instance variable

Demonstration:

trail1 = GuardrailAuditTrail()
trail2 = GuardrailAuditTrail()
trail1._allowed_count += 5
print(trail2._allowed_count)  # → 5 (WRONG — should be 0)

Expected Behavior

Each GuardrailAuditTrail instance should have its own independent _allowed_count and _denied_count counters.

Actual Behavior

All instances share the same counters. One plan's guardrail activity affects the statistics reported by all other plans' audit trails.

Suggested Fix

from pydantic import PrivateAttr

class GuardrailAuditTrail(BaseModel):
    ...
    _allowed_count: int = PrivateAttr(default=0)
    _denied_count: int = PrivateAttr(default=0)

Category

data-integrity

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.


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

## Bug Report: Concurrency/Data Integrity — `GuardrailAuditTrail` Private Counters Are Class Variables, Shared Across All Instances ### Severity Assessment - **Impact**: All `GuardrailAuditTrail` instances share the same `_allowed_count` and `_denied_count` counters — mutations in one plan's audit trail corrupt statistics for all other plans - **Likelihood**: High — affects every deployment with more than one active plan - **Priority**: High ### Location - **File**: `src/cleveragents/domain/models/core/autonomy_guardrails.py` - **Function**: `GuardrailAuditTrail` class body - **Lines**: ~104–106 - **Category**: data-integrity / concurrency ### Description In Pydantic v2, private attributes **must** be declared with `PrivateAttr()`. Using a plain class-level annotation with a default value creates a class variable shared across ALL instances, not per-instance fields. This means every `GuardrailAuditTrail` instance shares the same `_allowed_count` and `_denied_count`, so incrementing the counter in one plan's audit trail changes the statistics for all plans. ### Evidence ```python class GuardrailAuditTrail(BaseModel): ... _allowed_count: int = 0 # ← class variable in Pydantic v2, NOT instance variable _denied_count: int = 0 # ← class variable in Pydantic v2, NOT instance variable ``` **Demonstration:** ```python trail1 = GuardrailAuditTrail() trail2 = GuardrailAuditTrail() trail1._allowed_count += 5 print(trail2._allowed_count) # → 5 (WRONG — should be 0) ``` ### Expected Behavior Each `GuardrailAuditTrail` instance should have its own independent `_allowed_count` and `_denied_count` counters. ### Actual Behavior All instances share the same counters. One plan's guardrail activity affects the statistics reported by all other plans' audit trails. ### Suggested Fix ```python from pydantic import PrivateAttr class GuardrailAuditTrail(BaseModel): ... _allowed_count: int = PrivateAttr(default=0) _denied_count: int = PrivateAttr(default=0) ``` ### Category data-integrity ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. --- **Automated by CleverAgents Bot** Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor
HAL9000 added this to the v3.5.0 milestone 2026-04-10 21:39:16 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — Concurrency/data integrity bug in autonomy hardening components that impacts M6 milestone functionality
  • Milestone: v3.5.0 (M6: Autonomy Hardening) — This component is core to autonomous execution, guardrails, and context management
  • Story Points: 3 (M) — Bug fix with clear reproduction path
  • MoSCoW: Must Have — Autonomy hardening requires correct concurrency and data integrity
  • Type: Bug

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

Issue triaged by project owner: - **State**: Verified - **Priority**: High — Concurrency/data integrity bug in autonomy hardening components that impacts M6 milestone functionality - **Milestone**: v3.5.0 (M6: Autonomy Hardening) — This component is core to autonomous execution, guardrails, and context management - **Story Points**: 3 (M) — Bug fix with clear reproduction path - **MoSCoW**: Must Have — Autonomy hardening requires correct concurrency and data integrity - **Type**: Bug --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
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#7496
No description provided.