UAT: UnitOfWorkContext exposes legacy ProjectRepository instead of spec-aligned NamespacedProjectRepository — new project repository inaccessible via Unit of Work #1914

Open
opened 2026-04-03 00:12:10 +00:00 by freemo · 2 comments
Owner

Metadata

  • Branch: fix/uow-namespaced-project-repo
  • Commit Message: fix(infra): expose NamespacedProjectRepository in UnitOfWorkContext
  • Milestone: v3.7.0
  • Parent Epic: None identified — see orphan note below

Description

The UnitOfWorkContext (the transaction context provided by UnitOfWork.transaction()) exposes a projects property that returns the legacy ProjectRepository (integer-ID based, targeting the old plans table). The new spec-aligned NamespacedProjectRepository (which uses namespaced names as primary keys, per the specification) is NOT accessible via the Unit of Work pattern.

What was tested: Code-level analysis of src/cleveragents/infrastructure/database/unit_of_work.py and runtime verification.

Expected Behavior (from spec)

The UnitOfWorkContext should expose the spec-aligned NamespacedProjectRepository so that project operations can participate in cross-repository atomic transactions. Per ADR-019: "For cross-repository atomicity, use UnitOfWork."

Actual Behavior

UnitOfWorkContext.projects returns ProjectRepository (legacy):

@property
def projects(self) -> ProjectRepository:
    """Get project repository for this transaction."""
    if self._projects is None:
        self._projects = ProjectRepository(self._session)
    return self._projects

The NamespacedProjectRepository is only accessible via the DI container as a standalone Factory provider (container.namespaced_project_repo()), bypassing the Unit of Work pattern entirely.

Verified at runtime:

from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext
import inspect
props = [name for name, val in inspect.getmembers(UnitOfWorkContext) if isinstance(val, property)]
# Returns: ['actions', 'actors', 'changes', 'checkpoints', 'contexts',
#           'correction_attempts', 'debug_attempts', 'decisions',
#           'lifecycle_plans', 'plans', 'projects']
# Note: 'projects' returns legacy ProjectRepository, not NamespacedProjectRepository

Impact

  1. Project CRUD operations (create, update, delete) using the spec-aligned NamespacedProjectRepository cannot be made atomic with other repository operations (e.g., creating a project and linking resources in a single transaction).
  2. The NamespacedProjectRepository uses auto-commit (separate bug), making it impossible to roll back project operations if a subsequent step fails.
  3. Application services that need to create a project AND link resources atomically cannot do so.

Code location: src/cleveragents/infrastructure/database/unit_of_work.pyUnitOfWorkContext.projects property

Steps to Reproduce

from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext
import inspect
props = [name for name, val in inspect.getmembers(UnitOfWorkContext) if isinstance(val, property)]
print(props)
# 'namespaced_projects' is missing from the list

Subtasks

  • Audit UnitOfWorkContext to identify all repository properties and their types
  • Add a namespaced_projects property to UnitOfWorkContext that returns a session-bound NamespacedProjectRepository
  • Ensure NamespacedProjectRepository accepts a SQLAlchemy session parameter (no auto-commit)
  • Update DI container wiring so namespaced_project_repo can also be obtained via Unit of Work
  • Write unit tests verifying UnitOfWorkContext.namespaced_projects participates in the same transaction (rollback test)
  • Write integration test verifying atomic create-project + link-resource via Unit of Work
  • Update any application services that call container.namespaced_project_repo() directly to use Unit of Work instead

Definition of Done

  • UnitOfWorkContext exposes a namespaced_projects property returning a session-bound NamespacedProjectRepository
  • NamespacedProjectRepository does NOT auto-commit when obtained via Unit of Work
  • Rolling back a UnitOfWork transaction also rolls back NamespacedProjectRepository operations
  • All existing tests continue to pass
  • New unit and integration tests cover the transactional behaviour
  • All nox stages pass
  • Coverage >= 97%

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

## Metadata - **Branch**: `fix/uow-namespaced-project-repo` - **Commit Message**: `fix(infra): expose NamespacedProjectRepository in UnitOfWorkContext` - **Milestone**: v3.7.0 - **Parent Epic**: _None identified — see orphan note below_ ## Description The `UnitOfWorkContext` (the transaction context provided by `UnitOfWork.transaction()`) exposes a `projects` property that returns the **legacy** `ProjectRepository` (integer-ID based, targeting the old `plans` table). The new spec-aligned `NamespacedProjectRepository` (which uses namespaced names as primary keys, per the specification) is NOT accessible via the Unit of Work pattern. **What was tested**: Code-level analysis of `src/cleveragents/infrastructure/database/unit_of_work.py` and runtime verification. ### Expected Behavior (from spec) The `UnitOfWorkContext` should expose the spec-aligned `NamespacedProjectRepository` so that project operations can participate in cross-repository atomic transactions. Per ADR-019: "For cross-repository atomicity, use UnitOfWork." ### Actual Behavior `UnitOfWorkContext.projects` returns `ProjectRepository` (legacy): ```python @property def projects(self) -> ProjectRepository: """Get project repository for this transaction.""" if self._projects is None: self._projects = ProjectRepository(self._session) return self._projects ``` The `NamespacedProjectRepository` is only accessible via the DI container as a standalone `Factory` provider (`container.namespaced_project_repo()`), bypassing the Unit of Work pattern entirely. Verified at runtime: ```python from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext import inspect props = [name for name, val in inspect.getmembers(UnitOfWorkContext) if isinstance(val, property)] # Returns: ['actions', 'actors', 'changes', 'checkpoints', 'contexts', # 'correction_attempts', 'debug_attempts', 'decisions', # 'lifecycle_plans', 'plans', 'projects'] # Note: 'projects' returns legacy ProjectRepository, not NamespacedProjectRepository ``` ### Impact 1. Project CRUD operations (create, update, delete) using the spec-aligned `NamespacedProjectRepository` cannot be made atomic with other repository operations (e.g., creating a project and linking resources in a single transaction). 2. The `NamespacedProjectRepository` uses auto-commit (separate bug), making it impossible to roll back project operations if a subsequent step fails. 3. Application services that need to create a project AND link resources atomically cannot do so. **Code location**: `src/cleveragents/infrastructure/database/unit_of_work.py` — `UnitOfWorkContext.projects` property ### Steps to Reproduce ```python from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext import inspect props = [name for name, val in inspect.getmembers(UnitOfWorkContext) if isinstance(val, property)] print(props) # 'namespaced_projects' is missing from the list ``` ## Subtasks - [ ] Audit `UnitOfWorkContext` to identify all repository properties and their types - [ ] Add a `namespaced_projects` property to `UnitOfWorkContext` that returns a session-bound `NamespacedProjectRepository` - [ ] Ensure `NamespacedProjectRepository` accepts a SQLAlchemy session parameter (no auto-commit) - [ ] Update DI container wiring so `namespaced_project_repo` can also be obtained via Unit of Work - [ ] Write unit tests verifying `UnitOfWorkContext.namespaced_projects` participates in the same transaction (rollback test) - [ ] Write integration test verifying atomic create-project + link-resource via Unit of Work - [ ] Update any application services that call `container.namespaced_project_repo()` directly to use Unit of Work instead ## Definition of Done - [ ] `UnitOfWorkContext` exposes a `namespaced_projects` property returning a session-bound `NamespacedProjectRepository` - [ ] `NamespacedProjectRepository` does NOT auto-commit when obtained via Unit of Work - [ ] Rolling back a `UnitOfWork` transaction also rolls back `NamespacedProjectRepository` operations - [ ] All existing tests continue to pass - [ ] New unit and integration tests cover the transactional behaviour - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.7.0 milestone 2026-04-03 00:12:39 +00:00
Author
Owner

⚠️ Orphan Issue — Manual Epic Linking Required

This issue was created automatically by the UAT testing pipeline. A search of all open issues with Type/Epic label found no suitable parent Epic for this infrastructure bug (Unit of Work / NamespacedProjectRepository).

The only open Epic at time of creation was:

  • #1678: Epic: CI Execution Time Optimization — Timeouts, Concurrency, and Coverage Artifact Sharing (not relevant)

Action required: A project maintainer should either:

  1. Link this issue to an existing or newly created Epic covering infrastructure / repository layer alignment with the specification, or
  2. Create a new Epic (e.g., "Epic: Align infrastructure layer with spec — NamespacedProject, UnitOfWork, and repository wiring") and link this issue as a child that blocks that Epic.

Related issues in the same area:

  • #1848: NamespacedProject domain model missing invariants and invariant_actor fields
  • #1844: NamespacedProjectModel.to_domain() silently drops invariants_json and invariant_actor columns

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

⚠️ **Orphan Issue — Manual Epic Linking Required** This issue was created automatically by the UAT testing pipeline. A search of all open issues with `Type/Epic` label found no suitable parent Epic for this infrastructure bug (Unit of Work / `NamespacedProjectRepository`). The only open Epic at time of creation was: - **#1678**: Epic: CI Execution Time Optimization — Timeouts, Concurrency, and Coverage Artifact Sharing _(not relevant)_ **Action required**: A project maintainer should either: 1. Link this issue to an existing or newly created Epic covering infrastructure / repository layer alignment with the specification, **or** 2. Create a new Epic (e.g., "Epic: Align infrastructure layer with spec — NamespacedProject, UnitOfWork, and repository wiring") and link this issue as a child that **blocks** that Epic. Related issues in the same area: - #1848: `NamespacedProject` domain model missing `invariants` and `invariant_actor` fields - #1844: `NamespacedProjectModel.to_domain()` silently drops `invariants_json` and `invariant_actor` columns --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • MoSCoW: MoSCoW/Should Have — bug or error handling improvement.

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

Issue triaged by project owner: - **State**: Verified - **MoSCoW**: MoSCoW/Should Have — bug or error handling improvement. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
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#1914
No description provided.