UAT: agents plan list --action filter not implemented in PlanLifecycleService.list_plans() #2833

Open
opened 2026-04-04 20:45:10 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/plan-lifecycle-list-plans-missing-action-filter
  • Commit Message: fix(plan-lifecycle): add action_name parameter to list_plans() to support server-side action filtering
  • Milestone: v3.7.0
  • Parent Epic: #372

Bug Report

Background and Context

The agents plan list CLI command accepts an --action <ACTION> flag per docs/specification.md, which specifies that plans can be filtered by their source action. The CLI command in src/cleveragents/cli/commands/plan.py correctly accepts --action as a parameter, but the underlying service method PlanLifecycleService.list_plans() in src/cleveragents/application/services/plan_lifecycle_service.py has no corresponding action_name parameter.

As a result, the CLI works around this gap by performing client-side filtering after fetching all plans from the service:

# In CLI plan.py (approximate workaround):
if action_filter:
    plans = [p for p in plans if p.action_name == action_filter]

This client-side filtering is inefficient for large datasets and violates the Service Layer pattern: the service layer is responsible for data access patterns, and callers using list_plans() directly (e.g., A2A handlers, other services) cannot filter by action without fetching all plans.

Files Affected

  • src/cleveragents/application/services/plan_lifecycle_service.pyPlanLifecycleService.list_plans() method signature
  • src/cleveragents/cli/commands/plan.py--action filter workaround (client-side filtering to be removed)

Current Behavior

PlanLifecycleService.list_plans() signature:

def list_plans(
    self,
    namespace: str | None = None,
    phase: PlanPhase | None = None,
    project_name: str | None = None,
) -> list[Plan]:

There is no action_name parameter. The CLI accepts --action but filters the result list client-side after calling list_plans() with no action filter. In persisted mode, ctx.lifecycle_plans.list_all() fetches all plans from the database regardless of the action filter, making the database query O(N) even when only a small subset of plans match the requested action.

Expected Behavior (from spec)

Per docs/specification.md, agents plan list [--action <ACTION>] must filter plans by their source action. The service layer should support this filter natively:

def list_plans(
    self,
    namespace: str | None = None,
    phase: PlanPhase | None = None,
    project_name: str | None = None,
    action_name: str | None = None,  # ← missing parameter
) -> list[Plan]:

When action_name is provided:

  1. The service must filter plans by their source action at the repository/database level (not client-side).
  2. The CLI must pass the --action value directly to list_plans(action_name=...) instead of filtering after the fact.
  3. Any other callers of list_plans() (A2A handlers, other services) gain the ability to filter by action without fetching all plans.

Impact

  1. Performance: For large plan databases, fetching all plans and filtering client-side is O(N) instead of O(filtered). The database query in persisted mode fetches all plans regardless of the action filter.
  2. Incomplete service API: Callers using list_plans() directly (e.g., A2A handlers) cannot filter by action without fetching all plans and filtering themselves.
  3. Spec violation: The spec requires agents plan list [--action <ACTION>] to filter by action; the service layer — the authoritative data access point — does not implement this filter.

Evidence

  • list_plans() signature in src/cleveragents/application/services/plan_lifecycle_service.py:
    def list_plans(self, namespace: str | None = None, phase: PlanPhase | None = None, project_name: str | None = None) -> list[Plan]:
    
  • No action_name parameter exists.
  • The CLI has --action option but filters after calling list_plans().

Subtasks

  • Add action_name: str | None = None parameter to PlanLifecycleService.list_plans() signature
  • Update the in-memory filtering logic inside list_plans() to apply the action_name filter alongside existing namespace, phase, and project_name filters
  • Update the persisted-mode repository call (e.g., ctx.lifecycle_plans.list_all()) to pass action_name to the repository layer if supported, or apply the filter at the service level immediately after fetch
  • Remove the client-side --action workaround from src/cleveragents/cli/commands/plan.py and replace it with a direct pass-through to list_plans(action_name=action_filter)
  • Add or update Behave unit test scenarios in features/ to assert that list_plans(action_name=...) correctly filters plans by action
  • Ensure all nox stages pass (nox -e lint, nox -e typecheck, nox -e unit_tests, nox -e coverage_report)
  • Confirm test coverage remains ≥ 97%

Definition of Done

  • PlanLifecycleService.list_plans() accepts an action_name parameter and filters plans by action at the service level
  • The CLI agents plan list --action <ACTION> passes the filter directly to list_plans() — no client-side post-filtering
  • All callers of list_plans() can filter by action without fetching all plans
  • Behave feature file covers the action_name filter with at least one scenario (e.g., filtering returns only plans for the specified action, and an unmatched action returns an empty list)
  • All nox stages pass
  • Coverage >= 97%

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

## Metadata - **Branch**: `fix/plan-lifecycle-list-plans-missing-action-filter` - **Commit Message**: `fix(plan-lifecycle): add action_name parameter to list_plans() to support server-side action filtering` - **Milestone**: v3.7.0 - **Parent Epic**: #372 ## Bug Report ### Background and Context The `agents plan list` CLI command accepts an `--action <ACTION>` flag per `docs/specification.md`, which specifies that plans can be filtered by their source action. The CLI command in `src/cleveragents/cli/commands/plan.py` correctly accepts `--action` as a parameter, but the underlying service method `PlanLifecycleService.list_plans()` in `src/cleveragents/application/services/plan_lifecycle_service.py` has no corresponding `action_name` parameter. As a result, the CLI works around this gap by performing client-side filtering **after** fetching all plans from the service: ```python # In CLI plan.py (approximate workaround): if action_filter: plans = [p for p in plans if p.action_name == action_filter] ``` This client-side filtering is inefficient for large datasets and violates the Service Layer pattern: the service layer is responsible for data access patterns, and callers using `list_plans()` directly (e.g., A2A handlers, other services) cannot filter by action without fetching all plans. ### Files Affected - `src/cleveragents/application/services/plan_lifecycle_service.py` — `PlanLifecycleService.list_plans()` method signature - `src/cleveragents/cli/commands/plan.py` — `--action` filter workaround (client-side filtering to be removed) ### Current Behavior `PlanLifecycleService.list_plans()` signature: ```python def list_plans( self, namespace: str | None = None, phase: PlanPhase | None = None, project_name: str | None = None, ) -> list[Plan]: ``` There is **no `action_name` parameter**. The CLI accepts `--action` but filters the result list client-side after calling `list_plans()` with no action filter. In persisted mode, `ctx.lifecycle_plans.list_all()` fetches all plans from the database regardless of the action filter, making the database query O(N) even when only a small subset of plans match the requested action. ### Expected Behavior (from spec) Per `docs/specification.md`, `agents plan list [--action <ACTION>]` must filter plans by their source action. The service layer should support this filter natively: ```python def list_plans( self, namespace: str | None = None, phase: PlanPhase | None = None, project_name: str | None = None, action_name: str | None = None, # ← missing parameter ) -> list[Plan]: ``` When `action_name` is provided: 1. The service must filter plans by their source action at the repository/database level (not client-side). 2. The CLI must pass the `--action` value directly to `list_plans(action_name=...)` instead of filtering after the fact. 3. Any other callers of `list_plans()` (A2A handlers, other services) gain the ability to filter by action without fetching all plans. ### Impact 1. **Performance**: For large plan databases, fetching all plans and filtering client-side is O(N) instead of O(filtered). The database query in persisted mode fetches all plans regardless of the action filter. 2. **Incomplete service API**: Callers using `list_plans()` directly (e.g., A2A handlers) cannot filter by action without fetching all plans and filtering themselves. 3. **Spec violation**: The spec requires `agents plan list [--action <ACTION>]` to filter by action; the service layer — the authoritative data access point — does not implement this filter. ### Evidence - `list_plans()` signature in `src/cleveragents/application/services/plan_lifecycle_service.py`: ```python def list_plans(self, namespace: str | None = None, phase: PlanPhase | None = None, project_name: str | None = None) -> list[Plan]: ``` - No `action_name` parameter exists. - The CLI has `--action` option but filters after calling `list_plans()`. ## Subtasks - [ ] Add `action_name: str | None = None` parameter to `PlanLifecycleService.list_plans()` signature - [ ] Update the in-memory filtering logic inside `list_plans()` to apply the `action_name` filter alongside existing `namespace`, `phase`, and `project_name` filters - [ ] Update the persisted-mode repository call (e.g., `ctx.lifecycle_plans.list_all()`) to pass `action_name` to the repository layer if supported, or apply the filter at the service level immediately after fetch - [ ] Remove the client-side `--action` workaround from `src/cleveragents/cli/commands/plan.py` and replace it with a direct pass-through to `list_plans(action_name=action_filter)` - [ ] Add or update Behave unit test scenarios in `features/` to assert that `list_plans(action_name=...)` correctly filters plans by action - [ ] Ensure all nox stages pass (`nox -e lint`, `nox -e typecheck`, `nox -e unit_tests`, `nox -e coverage_report`) - [ ] Confirm test coverage remains ≥ 97% ## Definition of Done - [ ] `PlanLifecycleService.list_plans()` accepts an `action_name` parameter and filters plans by action at the service level - [ ] The CLI `agents plan list --action <ACTION>` passes the filter directly to `list_plans()` — no client-side post-filtering - [ ] All callers of `list_plans()` can filter by action without fetching all plans - [ ] Behave feature file covers the `action_name` filter with at least one scenario (e.g., filtering returns only plans for the specified action, and an unmatched action returns an empty list) - [ ] 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-04 20:45:17 +00:00
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
Reference
cleveragents/cleveragents-core#2833
No description provided.