UAT: CorrectionService has no database persistence — correction attempts are lost on service restart #2930

Open
opened 2026-04-05 02:51:31 +00:00 by freemo · 2 comments
Owner

Metadata

  • Branch: fix/correction-service-db-persistence
  • Commit Message: fix(correction): wire CorrectionService to CorrectionAttemptRepository for durable persistence
  • Milestone: v3.7.0
  • Parent Epic: #394

Background

During UAT testing of the Decision Tree & Corrections feature area, it was found that CorrectionService (in src/cleveragents/application/services/correction_service.py) stores all correction state exclusively in-memory dictionaries. There is no database persistence for correction attempts.

Expected Behaviour (per spec §28678)

The specification explicitly states:

"5. Record correction: Create a correction_attempts record linking old and new decisions."

The spec also defines a correction_attempts table (line 45681) and lists Correction Attempts as a persisted entity:

| Correction Attempts | SQLite correction_attempts table + archived artifacts on filesystem | Server PostgreSQL + object storage | Relational rows + file archives | ULID (correction_attempt_id) |

Actual Behaviour

CorrectionService.__init__() initialises:

self._corrections: dict[str, CorrectionRequest] = {}
self._impacts: dict[str, CorrectionImpact] = {}
self._attempts: dict[str, list[CorrectionAttempt]] = {}
self._results: dict[str, CorrectionResult] = {}

All state is in-memory only. The service docstring even acknowledges: "A production deployment would swap these for repository adapters."

The CorrectionAttemptRepository class exists in src/cleveragents/infrastructure/database/repositories.py (line 5754) with full CRUD methods (create, get, list_by_plan, update_state), but it is never used by CorrectionService. The CorrectionAttemptRecord domain model also exists in src/cleveragents/domain/models/core/correction.py but is not imported by CorrectionService.

Impact

  1. All correction requests, impacts, attempts, and results are lost when the process restarts.
  2. agents plan diff --correction <id> cannot look up historical correction attempts.
  3. The correction_attempts database table (created by migration m8_001_correction_attempts) is never written to by the application.

Steps to Reproduce

  1. Run agents plan correct <decision_id> --mode revert --guidance "test" --yes
  2. Restart the process
  3. Attempt to reference the correction attempt ID — it will not be found

Code Locations

  • src/cleveragents/application/services/correction_service.py — lines 101–115 (constructor)
  • src/cleveragents/infrastructure/database/repositories.py — line 5754 (CorrectionAttemptRepository, unused)
  • src/cleveragents/domain/models/core/correction.pyCorrectionAttemptRecord class (unused by service)

Subtasks

  • Write a TDD issue-capture Behave scenario (@tdd_expected_fail) that demonstrates the bug: correction attempt is not found after service restart
  • Inject CorrectionAttemptRepository into CorrectionService.__init__() via constructor dependency injection
  • Replace all in-memory self._attempts writes with CorrectionAttemptRepository.create() / update_state() calls
  • Replace all in-memory self._attempts reads with CorrectionAttemptRepository.get() / list_by_plan() calls
  • Persist CorrectionRequest, CorrectionImpact, and CorrectionResult state via their respective repository adapters (or extend CorrectionAttemptRepository as appropriate per spec)
  • Import and use CorrectionAttemptRecord from src/cleveragents/domain/models/core/correction.py in the service
  • Remove the in-memory dict fallback and the "production deployment" TODO comment from the service docstring
  • Update Behave unit test scenarios to cover the repository-backed persistence path
  • Verify agents plan diff --correction <id> correctly retrieves persisted correction attempts after restart
  • Ensure all nox sessions pass (nox -e lint, nox -e typecheck, nox -e unit_tests, nox -e integration_tests, nox -e coverage_report)

Definition of Done

  • TDD issue-capture test (@tdd_expected_fail) exists and demonstrates the bug before the fix
  • CorrectionService no longer uses in-memory dicts for correction state
  • CorrectionAttemptRepository is injected into and actively used by CorrectionService
  • CorrectionAttemptRecord is imported and used by CorrectionService
  • The correction_attempts database table is written to on every correction attempt
  • agents plan diff --correction <id> successfully retrieves correction attempts after a process restart
  • All nox stages pass
  • Coverage >= 97%

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

## Metadata - **Branch**: `fix/correction-service-db-persistence` - **Commit Message**: `fix(correction): wire CorrectionService to CorrectionAttemptRepository for durable persistence` - **Milestone**: v3.7.0 - **Parent Epic**: #394 ## Background During UAT testing of the Decision Tree & Corrections feature area, it was found that `CorrectionService` (in `src/cleveragents/application/services/correction_service.py`) stores all correction state exclusively in-memory dictionaries. There is no database persistence for correction attempts. ### Expected Behaviour (per spec §28678) The specification explicitly states: > "5. **Record correction**: Create a `correction_attempts` record linking old and new decisions." The spec also defines a `correction_attempts` table (line 45681) and lists Correction Attempts as a persisted entity: > | **Correction Attempts** | SQLite `correction_attempts` table + archived artifacts on filesystem | Server PostgreSQL + object storage | Relational rows + file archives | ULID (`correction_attempt_id`) | ### Actual Behaviour `CorrectionService.__init__()` initialises: ```python self._corrections: dict[str, CorrectionRequest] = {} self._impacts: dict[str, CorrectionImpact] = {} self._attempts: dict[str, list[CorrectionAttempt]] = {} self._results: dict[str, CorrectionResult] = {} ``` All state is in-memory only. The service docstring even acknowledges: *"A production deployment would swap these for repository adapters."* The `CorrectionAttemptRepository` class exists in `src/cleveragents/infrastructure/database/repositories.py` (line 5754) with full CRUD methods (`create`, `get`, `list_by_plan`, `update_state`), but it is **never used** by `CorrectionService`. The `CorrectionAttemptRecord` domain model also exists in `src/cleveragents/domain/models/core/correction.py` but is not imported by `CorrectionService`. ### Impact 1. All correction requests, impacts, attempts, and results are lost when the process restarts. 2. `agents plan diff --correction <id>` cannot look up historical correction attempts. 3. The `correction_attempts` database table (created by migration `m8_001_correction_attempts`) is never written to by the application. ### Steps to Reproduce 1. Run `agents plan correct <decision_id> --mode revert --guidance "test" --yes` 2. Restart the process 3. Attempt to reference the correction attempt ID — it will not be found ### Code Locations - `src/cleveragents/application/services/correction_service.py` — lines 101–115 (constructor) - `src/cleveragents/infrastructure/database/repositories.py` — line 5754 (`CorrectionAttemptRepository`, unused) - `src/cleveragents/domain/models/core/correction.py` — `CorrectionAttemptRecord` class (unused by service) ## Subtasks - [ ] Write a TDD issue-capture Behave scenario (`@tdd_expected_fail`) that demonstrates the bug: correction attempt is not found after service restart - [ ] Inject `CorrectionAttemptRepository` into `CorrectionService.__init__()` via constructor dependency injection - [ ] Replace all in-memory `self._attempts` writes with `CorrectionAttemptRepository.create()` / `update_state()` calls - [ ] Replace all in-memory `self._attempts` reads with `CorrectionAttemptRepository.get()` / `list_by_plan()` calls - [ ] Persist `CorrectionRequest`, `CorrectionImpact`, and `CorrectionResult` state via their respective repository adapters (or extend `CorrectionAttemptRepository` as appropriate per spec) - [ ] Import and use `CorrectionAttemptRecord` from `src/cleveragents/domain/models/core/correction.py` in the service - [ ] Remove the in-memory dict fallback and the "production deployment" TODO comment from the service docstring - [ ] Update Behave unit test scenarios to cover the repository-backed persistence path - [ ] Verify `agents plan diff --correction <id>` correctly retrieves persisted correction attempts after restart - [ ] Ensure all nox sessions pass (`nox -e lint`, `nox -e typecheck`, `nox -e unit_tests`, `nox -e integration_tests`, `nox -e coverage_report`) ## Definition of Done - [ ] TDD issue-capture test (`@tdd_expected_fail`) exists and demonstrates the bug before the fix - [ ] `CorrectionService` no longer uses in-memory dicts for correction state - [ ] `CorrectionAttemptRepository` is injected into and actively used by `CorrectionService` - [ ] `CorrectionAttemptRecord` is imported and used by `CorrectionService` - [ ] The `correction_attempts` database table is written to on every correction attempt - [ ] `agents plan diff --correction <id>` successfully retrieves correction attempts after a process restart - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.7.0 milestone 2026-04-05 02:51:42 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Confirmed
  • MoSCoW: Should Have — correction persistence is important

Valid finding verified during batch triage.


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

Issue triaged by project owner: - **State**: Verified - **Priority**: Confirmed - **MoSCoW**: Should Have — correction persistence is important Valid finding verified during batch triage. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Author
Owner

Label compliance fix applied:

  • Added missing labels: Type/Bug, Priority/High
  • Reason: Issue had only State/In Progress but was missing Type/* and Priority/* labels. Per CONTRIBUTING.md, all three are required. Inferred from issue title (UAT bug) and body (has milestone v3.7.0).

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

Label compliance fix applied: - Added missing labels: `Type/Bug`, `Priority/High` - Reason: Issue had only `State/In Progress` but was missing `Type/*` and `Priority/*` labels. Per CONTRIBUTING.md, all three are required. Inferred from issue title (UAT bug) and body (has milestone v3.7.0). --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-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.

Blocks
#394 Epic: Decision Framework
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2930
No description provided.