fix(invariant): persist invariants to database via InvariantRepository and Alembic migration

ISSUES CLOSED: #8573
This commit is contained in:
HAL9000
2026-05-15 06:33:28 +00:00
committed by Forgejo
parent 5106e03494
commit 421429c65f
12 changed files with 648 additions and 87 deletions
@@ -1,20 +1,10 @@
"""Step definitions for tdd_invariant_persistence.feature (bug #1022).
"""Step definitions for tdd_invariant_persistence.feature (bug #1022, now fixed).
TDD issue-capture tests verifying that ``InvariantService`` persists invariants
across simulated CLI process restarts (separate service instances).
Bug #1022: ``InvariantService`` stores invariants in an in-memory dict
(``self._invariants``) with no database persistence layer. Each CLI
invocation spawns a fresh process with a new ``InvariantService()``
instance, so all invariants are lost when the process exits.
These steps exercise the current (buggy) behaviour by creating fresh
``InvariantService`` instances to simulate separate process invocations.
When the bug is fixed, the service will use a database repository and
fresh instances backed by the same database will share state.
The tests carry ``@tdd_expected_fail`` so CI passes while the bug is
unfixed. The tag will be removed when bug #1022 is fixed.
Tests verify that ``InvariantService`` persists invariants across simulated
CLI process restarts (separate service instances), confirming that Bug #8573
/#1022 is resolved: the database-backed InvariantService stores data in SQLite,
so separate CLI invocations share the same underlying ``cleveragents.db`` and
cross-instance data visibility is confirmed.
"""
from __future__ import annotations
+15 -19
View File
@@ -1,49 +1,45 @@
# TDD issue-capture test for bug #1022 — InvariantService in-memory storage only.
# TDD issue-capture test for bug #1022 — InvariantService persistence.
#
# InvariantService stores invariants in an in-memory dict (self._invariants)
# with no database persistence layer. Each CLI invocation spawns a fresh
# process with a new InvariantService() instance, so all invariants added in
# one invocation are lost when the process exits.
# Bug #1022 has been fixed: InvariantService now uses SQLite-based storage
# via a lazy session-factory pattern. Invariants added in one CLI invocation
# persist across process restarts because all instances share the same
# ``cleveragents.db`` (or equivalent) database configured in Settings.
#
# These scenarios prove the bug exists by simulating separate CLI invocations
# (fresh InvariantService instances) and asserting that data added in one
# invocation is visible in the next. They FAIL until the bug is fixed.
# The @tag inverts the result so CI passes.
#
# See: https://git.cleverthis.com/cleveragents/cleveragents-core/issues/1022
# These scenarios verify cross-instance data visibility by simulating
# separate CLI invocations (fresh service instances backing a shared DB).
@tdd_issue @tdd_issue_1022 @mock_only
Feature: TDD Issue #1022 — InvariantService invariants lost across process restarts
Feature: TDD Issue #1022 — InvariantService persistence across process restarts
As a developer using the agents CLI
I want invariants added via "agents invariant add" to persist across CLI invocations
So that "agents invariant list" in a subsequent invocation returns previously added invariants
InvariantService uses in-memory dict storage only. Each CLI invocation
creates a fresh InvariantService() instance, so invariants are lost when
the process exits. These tests simulate separate process invocations by
InvariantService uses SQLite-based storage backed by the configured database URL.
Fresh service instances share the same underlying database, so data persists across
process restarts. These tests simulate separate process invocations by
creating fresh service instances and verifying cross-instance data visibility.
@tdd_issue @tdd_issue_4283 @tdd_expected_fail
@tdd_issue_1022
Scenario: Invariant added in one service instance is visible in a fresh instance
Given I add a project invariant "All APIs must validate auth tokens" to project "local/api-service" via invariant service instance A
When I create a fresh invariant service instance B
And I list project invariants for "local/api-service" via instance B
Then the invariant list from instance B should contain "All APIs must validate auth tokens"
@tdd_issue @tdd_issue_4283 @tdd_expected_fail
@tdd_issue_1022
Scenario: Global invariant persists across simulated process restarts
Given I add a global invariant "Never delete production data" via invariant service instance A
When I create a fresh invariant service instance B
And I list global invariants via instance B
Then the invariant list from instance B should contain "Never delete production data"
@tdd_issue @tdd_issue_4283 @tdd_expected_fail
@tdd_issue_1022
Scenario: Invariant added via CLI add is visible via CLI list in a new invocation
Given I invoke invariant add via CLI with "--project local/webapp" and text "All changes need tests" using service invocation 1
When I invoke invariant list via CLI with "--project local/webapp" using service invocation 2
Then the CLI list output from invocation 2 should contain "All changes need tests"
@tdd_issue @tdd_issue_4283 @tdd_expected_fail
@tdd_issue_1022
Scenario: Invariant soft-deleted in a fresh instance after being added in another
Given I add a project invariant "Temporary constraint" to project "local/temp" via invariant service instance A
And I capture the invariant ID from instance A