UAT: InvariantService uses in-memory storage — invariants lost on process restart, no database persistence #4709

Closed
opened 2026-04-08 18:10:33 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: Database layer and repository patterns — Invariant persistence
Severity: Critical — invariants are a first-class spec feature but are not persisted to the database
Source: src/cleveragents/application/services/invariant_service.py


What Was Tested

Code-level analysis of InvariantService to verify that invariants are persisted to the SQLite database as required by the specification.

Expected Behavior (from spec)

The specification explicitly states:

Invariants | SQLite invariants table | Server PostgreSQL | Relational rows | Auto-generated ID
(spec §Storage and Persistence, line 45675)

Invariants are described as "first-class constraints (global, project, action, and plan scoped) that flow into the decision tree." The agents invariant add/list/remove CLI commands must persist invariants across CLI invocations.

Actual Behavior

InvariantService.__init__ initializes:

self._invariants: dict[str, Invariant] = {}
self._enforcement_records: list[InvariantEnforcementRecord] = []

All invariant storage is in-memory only. There is:

  • No InvariantModel SQLAlchemy ORM class in src/cleveragents/infrastructure/database/models.py
  • No invariants table in any Alembic migration
  • No InvariantRepository class anywhere in the codebase
  • No InvariantRepositoryProtocol in src/cleveragents/domain/repositories/

Impact

  1. agents invariant add --global "Never modify production databases" — invariant is created in memory but lost when the process exits
  2. agents invariant list in a new CLI invocation returns empty even after invariants were added
  3. The Invariant Reconciliation Actor at Strategize start cannot load previously-defined invariants
  4. Project-level invariants defined via agents project create --invariant "..." are stored in ns_projects.invariants_json (JSON blob) but global/plan-level invariants have no persistence at all

Steps to Reproduce

agents invariant add --global "All database changes require migration scripts"
# Process exits
agents invariant list --global
# Returns empty — invariant was lost

Code Location

  • src/cleveragents/application/services/invariant_service.py — lines 44–60 (in-memory dict)
  • src/cleveragents/infrastructure/database/models.py — no InvariantModel class
  • src/cleveragents/infrastructure/database/repositories.py — no InvariantRepository class
  • alembic/versions/ — no migration creating invariants table

Fix Required

  1. Create InvariantModel in models.py with columns: id (ULID, PK), text, scope, source_name, created_at, active, non_overridable
  2. Create Alembic migration for invariants table
  3. Create InvariantRepository in repositories.py
  4. Create InvariantRepositoryProtocol in domain/repositories/
  5. Wire InvariantRepository into UnitOfWorkContext
  6. Update InvariantService to use the repository instead of in-memory dict

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

## Bug Report **Feature Area:** Database layer and repository patterns — Invariant persistence **Severity:** Critical — invariants are a first-class spec feature but are not persisted to the database **Source:** `src/cleveragents/application/services/invariant_service.py` --- ## What Was Tested Code-level analysis of `InvariantService` to verify that invariants are persisted to the SQLite database as required by the specification. ## Expected Behavior (from spec) The specification explicitly states: > **Invariants** | SQLite `invariants` table | Server PostgreSQL | Relational rows | Auto-generated ID > (spec §Storage and Persistence, line 45675) Invariants are described as "first-class constraints (global, project, action, and plan scoped) that flow into the decision tree." The `agents invariant add/list/remove` CLI commands must persist invariants across CLI invocations. ## Actual Behavior `InvariantService.__init__` initializes: ```python self._invariants: dict[str, Invariant] = {} self._enforcement_records: list[InvariantEnforcementRecord] = [] ``` All invariant storage is **in-memory only**. There is: - No `InvariantModel` SQLAlchemy ORM class in `src/cleveragents/infrastructure/database/models.py` - No `invariants` table in any Alembic migration - No `InvariantRepository` class anywhere in the codebase - No `InvariantRepositoryProtocol` in `src/cleveragents/domain/repositories/` ## Impact 1. `agents invariant add --global "Never modify production databases"` — invariant is created in memory but **lost when the process exits** 2. `agents invariant list` in a new CLI invocation returns **empty** even after invariants were added 3. The Invariant Reconciliation Actor at Strategize start cannot load previously-defined invariants 4. Project-level invariants defined via `agents project create --invariant "..."` are stored in `ns_projects.invariants_json` (JSON blob) but global/plan-level invariants have no persistence at all ## Steps to Reproduce ```bash agents invariant add --global "All database changes require migration scripts" # Process exits agents invariant list --global # Returns empty — invariant was lost ``` ## Code Location - `src/cleveragents/application/services/invariant_service.py` — lines 44–60 (in-memory dict) - `src/cleveragents/infrastructure/database/models.py` — no `InvariantModel` class - `src/cleveragents/infrastructure/database/repositories.py` — no `InvariantRepository` class - `alembic/versions/` — no migration creating `invariants` table ## Fix Required 1. Create `InvariantModel` in `models.py` with columns: `id` (ULID, PK), `text`, `scope`, `source_name`, `created_at`, `active`, `non_overridable` 2. Create Alembic migration for `invariants` table 3. Create `InvariantRepository` in `repositories.py` 4. Create `InvariantRepositoryProtocol` in `domain/repositories/` 5. Wire `InvariantRepository` into `UnitOfWorkContext` 6. Update `InvariantService` to use the repository instead of in-memory dict --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Author
Owner

Closing as duplicate of #4696 — both issues report the same problem: InvariantService uses in-memory-only storage with no persistence. Issue #4696 has milestone v3.5.0 assigned.


Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: backlog-groomer

Closing as duplicate of #4696 — both issues report the same problem: InvariantService uses in-memory-only storage with no persistence. Issue #4696 has milestone v3.5.0 assigned. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: backlog-groomer
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#4709
No description provided.