UAT: MemoryService.EntityStore SQL persistence methods are stubs — entity tracking not persisted across sessions #3607

Open
opened 2026-04-05 20:20:57 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/memory-service-entity-store-sql-persistence
  • Commit Message: fix(memory): implement SQL persistence for EntityStore._load_from_persistence and _persist_if_needed
  • Milestone: None (backlog)
  • Parent Epic: #369

Summary

The EntityStore class in src/cleveragents/application/services/memory_service.py has two stub methods (_load_from_persistence and _persist_if_needed) that are documented as "Future: Implement actual SQL persistence" but contain no implementation. This means entity tracking (projects, plans, contexts, changes) is never persisted to the database and is lost when the service is restarted.

What Was Tested

Code-level analysis of src/cleveragents/application/services/memory_service.py.

Expected Behavior (from spec)

Per docs/specification.md §25197 and the memory management requirements, the MemoryService with SQL persistence should store entity tracking data across sessions. The EntityStore constructor accepts a connection_string parameter specifically for SQL persistence, and the MemoryService docstring states:

"EntityMemory support enables tracking of named entities (projects, plans, contexts, changes) across conversation sessions."

Actual Behavior

In src/cleveragents/application/services/memory_service.py:

def _load_from_persistence(self) -> None:
    """Load entities from SQL persistence."""
    # For now, we use a simple in-memory approach
    # Future: Implement actual SQL persistence
    pass

def _persist_if_needed(self) -> None:
    """Persist entities to SQL if dirty and connection available."""
    if not self._dirty or not self.connection_string:
        return
    # For now, mark as clean without actual persistence
    # Future: Implement actual SQL persistence
    self._dirty = False

This means:

  1. Even when a connection_string is provided, entities are never loaded from or saved to the database
  2. All entity tracking (projects, plans, contexts, files, functions, classes) is lost on service restart
  3. The connection_string parameter to EntityStore.__init__ has no effect
  4. Cross-session entity recall — a documented feature — does not work

Code Location

  • src/cleveragents/application/services/memory_service.py lines ~130-140 (_load_from_persistence)
  • src/cleveragents/application/services/memory_service.py lines ~142-150 (_persist_if_needed)

Impact

The MemoryService is used for conversation memory management. Without entity persistence, the system cannot recall entities (projects, plans, contexts) across sessions, breaking the "cross-session entity recall" feature described in the spec. This affects long-running autonomous tasks that span multiple sessions.

Subtasks

  • Design the SQL schema for EntityStore persistence (entity table with type, name, metadata columns)
  • Implement _load_from_persistence to query entities from the SQL database on EntityStore initialisation
  • Implement _persist_if_needed to upsert dirty entities to the SQL database
  • Add transaction handling and connection lifecycle management (open/close/rollback on error)
  • Write Behave unit tests (BDD) covering: load from empty DB, load from populated DB, persist on dirty flag, no-op when connection_string is None, no-op when not dirty
  • Write Robot Framework integration test verifying entity recall survives a service restart
  • Update docstrings to remove "Future:" stubs and document the actual implementation

Definition of Done

  • _load_from_persistence reads entities from the SQL database when connection_string is set
  • _persist_if_needed writes dirty entities to the SQL database when connection_string is set
  • Both methods are no-ops (safe) when connection_string is None
  • Entity tracking survives a MemoryService restart in integration tests
  • All Behave unit tests pass (nox -e unit_tests)
  • All Robot Framework integration tests pass (nox -e integration_tests)
  • All nox stages pass
  • Coverage >= 97%

Backlog note: This issue was discovered during autonomous operation
on milestone v3.5.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/memory-service-entity-store-sql-persistence` - **Commit Message**: `fix(memory): implement SQL persistence for EntityStore._load_from_persistence and _persist_if_needed` - **Milestone**: None (backlog) - **Parent Epic**: #369 ## Summary The `EntityStore` class in `src/cleveragents/application/services/memory_service.py` has two stub methods (`_load_from_persistence` and `_persist_if_needed`) that are documented as "Future: Implement actual SQL persistence" but contain no implementation. This means entity tracking (projects, plans, contexts, changes) is never persisted to the database and is lost when the service is restarted. ## What Was Tested Code-level analysis of `src/cleveragents/application/services/memory_service.py`. ## Expected Behavior (from spec) Per `docs/specification.md` §25197 and the memory management requirements, the `MemoryService` with SQL persistence should store entity tracking data across sessions. The `EntityStore` constructor accepts a `connection_string` parameter specifically for SQL persistence, and the `MemoryService` docstring states: > "EntityMemory support enables tracking of named entities (projects, plans, contexts, changes) across conversation sessions." ## Actual Behavior In `src/cleveragents/application/services/memory_service.py`: ```python def _load_from_persistence(self) -> None: """Load entities from SQL persistence.""" # For now, we use a simple in-memory approach # Future: Implement actual SQL persistence pass def _persist_if_needed(self) -> None: """Persist entities to SQL if dirty and connection available.""" if not self._dirty or not self.connection_string: return # For now, mark as clean without actual persistence # Future: Implement actual SQL persistence self._dirty = False ``` This means: 1. Even when a `connection_string` is provided, entities are never loaded from or saved to the database 2. All entity tracking (projects, plans, contexts, files, functions, classes) is lost on service restart 3. The `connection_string` parameter to `EntityStore.__init__` has no effect 4. Cross-session entity recall — a documented feature — does not work ## Code Location - `src/cleveragents/application/services/memory_service.py` lines ~130-140 (`_load_from_persistence`) - `src/cleveragents/application/services/memory_service.py` lines ~142-150 (`_persist_if_needed`) ## Impact The `MemoryService` is used for conversation memory management. Without entity persistence, the system cannot recall entities (projects, plans, contexts) across sessions, breaking the "cross-session entity recall" feature described in the spec. This affects long-running autonomous tasks that span multiple sessions. ## Subtasks - [ ] Design the SQL schema for `EntityStore` persistence (entity table with type, name, metadata columns) - [ ] Implement `_load_from_persistence` to query entities from the SQL database on `EntityStore` initialisation - [ ] Implement `_persist_if_needed` to upsert dirty entities to the SQL database - [ ] Add transaction handling and connection lifecycle management (open/close/rollback on error) - [ ] Write Behave unit tests (BDD) covering: load from empty DB, load from populated DB, persist on dirty flag, no-op when `connection_string` is `None`, no-op when not dirty - [ ] Write Robot Framework integration test verifying entity recall survives a service restart - [ ] Update docstrings to remove "Future:" stubs and document the actual implementation ## Definition of Done - [ ] `_load_from_persistence` reads entities from the SQL database when `connection_string` is set - [ ] `_persist_if_needed` writes dirty entities to the SQL database when `connection_string` is set - [ ] Both methods are no-ops (safe) when `connection_string` is `None` - [ ] Entity tracking survives a `MemoryService` restart in integration tests - [ ] All Behave unit tests pass (`nox -e unit_tests`) - [ ] All Robot Framework integration tests pass (`nox -e integration_tests`) - [ ] All nox stages pass - [ ] Coverage >= 97% > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.5.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.7.0 milestone 2026-04-05 20:23:27 +00:00
Author
Owner

Duplicate UAT Report — Additional Context

A second UAT tester independently discovered and reported this same bug. The duplicate report has been suppressed (no new issue created) and this comment adds the additional context from that report.

Additional UAT Findings

Feature Area: Memory and Knowledge Management

Steps to reproduce (from second UAT report):

  1. Create a MemoryService with a connection_string
  2. Track an entity: service.track_entity("my-project", EntityType.PROJECT)
  3. Create a new MemoryService with the same connection_string and session_id
  4. Call service.get_entity("my-project", EntityType.PROJECT) — returns None instead of the tracked entity

Impact confirmed: Cross-session entity recall is completely non-functional. Any feature relying on persistent entity memory across sessions will silently fail.

Code location confirmed:

  • EntityStore._load_from_persistence() (~line 130)
  • EntityStore._persist_if_needed() (~line 140)

The Type/Automation label has been added to this issue to reflect that it was also discovered via automated UAT testing.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Duplicate UAT Report — Additional Context A second UAT tester independently discovered and reported this same bug. The duplicate report has been suppressed (no new issue created) and this comment adds the additional context from that report. ### Additional UAT Findings **Feature Area**: Memory and Knowledge Management **Steps to reproduce** (from second UAT report): 1. Create a `MemoryService` with a `connection_string` 2. Track an entity: `service.track_entity("my-project", EntityType.PROJECT)` 3. Create a **new** `MemoryService` with the same `connection_string` and `session_id` 4. Call `service.get_entity("my-project", EntityType.PROJECT)` — returns `None` instead of the tracked entity **Impact confirmed**: Cross-session entity recall is completely non-functional. Any feature relying on persistent entity memory across sessions will silently fail. **Code location confirmed**: - `EntityStore._load_from_persistence()` (~line 130) - `EntityStore._persist_if_needed()` (~line 140) The `Type/Automation` label has been added to this issue to reflect that it was also discovered via automated UAT testing. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
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
#369 Epic: Large Project Autonomy & Context
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3607
No description provided.