UAT: A2A facade _cleveragents/plan/correct and _cleveragents/plan/rollback always return stubs — service not wired despite PlanLifecycleService being available #3117

Open
opened 2026-04-05 06:24:58 +00:00 by freemo · 3 comments
Owner

Metadata

  • Branch: fix/a2a-plan-correct-rollback-wiring
  • Commit Message: fix(a2a): wire plan/correct and plan/rollback handlers to PlanLifecycleService
  • Milestone: v3.5.0
  • Parent Epic: #933

Bug Report

Feature Area: A2A Facade — Plan Lifecycle Operations (M6: Autonomy Hardening)

What was tested

The A2A local facade handlers for _cleveragents/plan/correct and _cleveragents/plan/rollback operations.

Expected behavior (from spec)

Per docs/specification.md §Plan Lifecycle and the A2A facade docstring, the _cleveragents/plan/correct operation should delegate to PlanLifecycleService (which has revert_plan() and execute_correction() methods), and _cleveragents/plan/rollback should delegate to the rollback/revert service. These are core M6 autonomy hardening operations.

Actual behavior (from code analysis)

In src/cleveragents/a2a/facade.py, both handlers unconditionally return stub responses regardless of whether plan_lifecycle_service is available:

# Line 528-530
def _handle_plan_correct(self, params: dict[str, Any]) -> dict[str, Any]:
    plan_id = params.get("plan_id", "")
    return {"plan_id": plan_id, "status": "corrected", "stub": True}  # ALWAYS stub

# Line 563-565
def _handle_plan_rollback(self, params: dict[str, Any]) -> dict[str, Any]:
    plan_id = params.get("plan_id", "")
    return {"plan_id": plan_id, "status": "rolled_back", "stub": True}  # ALWAYS stub

Unlike _handle_plan_cancel, _handle_plan_execute, and _handle_plan_apply which correctly check self._plan_lifecycle_service and delegate to it, _handle_plan_correct and _handle_plan_rollback never delegate — they always return stubs even when plan_lifecycle_service is wired.

The PlanLifecycleService has revert_plan() (line 2218) and the CLI has rollback_plan() (line 3323 of cli/commands/plan.py), but the A2A facade never calls them.

Code location

  • src/cleveragents/a2a/facade.py, lines 528-530 (_handle_plan_correct)
  • src/cleveragents/a2a/facade.py, lines 563-565 (_handle_plan_rollback)
  • src/cleveragents/application/services/plan_lifecycle_service.py, line 2218 (revert_plan)

Steps to reproduce

  1. Wire a PlanLifecycleService into A2aLocalFacade
  2. Dispatch _cleveragents/plan/correct with a valid plan_id
  3. Observe that the response always contains "stub": True — the service is never called

Impact

  • Phase reversion (correct) and rollback are core M6 Autonomy Hardening deliverables
  • Any A2A client calling _cleveragents/plan/correct or _cleveragents/plan/rollback receives a fake success response without any actual state change
  • This silently breaks the plan correction workflow

Subtasks

  • Wire _handle_plan_correct to PlanLifecycleService.revert_plan() or execute_correction()
  • Wire _handle_plan_rollback to the appropriate rollback service method
  • Add BDD tests for both handlers with a wired service
  • Verify stub: True is removed from responses when service is available

Definition of Done

  • _handle_plan_correct delegates to PlanLifecycleService when available
  • _handle_plan_rollback delegates to the rollback service when available
  • Both handlers only return stub: True when the service is None
  • BDD tests cover both wired and unwired cases
  • All nox stages pass
  • Coverage >= 97%

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

## Metadata - **Branch**: `fix/a2a-plan-correct-rollback-wiring` - **Commit Message**: `fix(a2a): wire plan/correct and plan/rollback handlers to PlanLifecycleService` - **Milestone**: v3.5.0 - **Parent Epic**: #933 ## Bug Report **Feature Area**: A2A Facade — Plan Lifecycle Operations (M6: Autonomy Hardening) ### What was tested The A2A local facade handlers for `_cleveragents/plan/correct` and `_cleveragents/plan/rollback` operations. ### Expected behavior (from spec) Per `docs/specification.md` §Plan Lifecycle and the A2A facade docstring, the `_cleveragents/plan/correct` operation should delegate to `PlanLifecycleService` (which has `revert_plan()` and `execute_correction()` methods), and `_cleveragents/plan/rollback` should delegate to the rollback/revert service. These are core M6 autonomy hardening operations. ### Actual behavior (from code analysis) In `src/cleveragents/a2a/facade.py`, both handlers unconditionally return stub responses regardless of whether `plan_lifecycle_service` is available: ```python # Line 528-530 def _handle_plan_correct(self, params: dict[str, Any]) -> dict[str, Any]: plan_id = params.get("plan_id", "") return {"plan_id": plan_id, "status": "corrected", "stub": True} # ALWAYS stub # Line 563-565 def _handle_plan_rollback(self, params: dict[str, Any]) -> dict[str, Any]: plan_id = params.get("plan_id", "") return {"plan_id": plan_id, "status": "rolled_back", "stub": True} # ALWAYS stub ``` Unlike `_handle_plan_cancel`, `_handle_plan_execute`, and `_handle_plan_apply` which correctly check `self._plan_lifecycle_service` and delegate to it, `_handle_plan_correct` and `_handle_plan_rollback` never delegate — they always return stubs even when `plan_lifecycle_service` is wired. The `PlanLifecycleService` has `revert_plan()` (line 2218) and the CLI has `rollback_plan()` (line 3323 of `cli/commands/plan.py`), but the A2A facade never calls them. ### Code location - `src/cleveragents/a2a/facade.py`, lines 528-530 (`_handle_plan_correct`) - `src/cleveragents/a2a/facade.py`, lines 563-565 (`_handle_plan_rollback`) - `src/cleveragents/application/services/plan_lifecycle_service.py`, line 2218 (`revert_plan`) ### Steps to reproduce 1. Wire a `PlanLifecycleService` into `A2aLocalFacade` 2. Dispatch `_cleveragents/plan/correct` with a valid `plan_id` 3. Observe that the response always contains `"stub": True` — the service is never called ### Impact - Phase reversion (correct) and rollback are core M6 Autonomy Hardening deliverables - Any A2A client calling `_cleveragents/plan/correct` or `_cleveragents/plan/rollback` receives a fake success response without any actual state change - This silently breaks the plan correction workflow ## Subtasks - [ ] Wire `_handle_plan_correct` to `PlanLifecycleService.revert_plan()` or `execute_correction()` - [ ] Wire `_handle_plan_rollback` to the appropriate rollback service method - [ ] Add BDD tests for both handlers with a wired service - [ ] Verify `stub: True` is removed from responses when service is available ## Definition of Done - [ ] `_handle_plan_correct` delegates to `PlanLifecycleService` when available - [ ] `_handle_plan_rollback` delegates to the rollback service when available - [ ] Both handlers only return `stub: True` when the service is `None` - [ ] BDD tests cover both wired and unwired cases - All nox stages pass - Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.5.0 milestone 2026-04-05 06:25:54 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Critical (keeping existing — A2A facade plan operations are core M6 deliverables)
  • Milestone: v3.5.0 (already assigned, keeping)
  • MoSCoW: Must Have — v3.5.0 acceptance criteria requires "A2A facade session and plan lifecycle operations functional via CLI." Stub responses for plan/correct and plan/rollback mean the A2A facade is non-functional for correction operations.
  • Parent Epic: #933 (A2A Protocol Compliance)

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

Issue triaged by project owner: - **State**: Verified - **Priority**: Critical (keeping existing — A2A facade plan operations are core M6 deliverables) - **Milestone**: v3.5.0 (already assigned, keeping) - **MoSCoW**: Must Have — v3.5.0 acceptance criteria requires "A2A facade session and plan lifecycle operations functional via CLI." Stub responses for plan/correct and plan/rollback mean the A2A facade is non-functional for correction operations. - **Parent Epic**: #933 (A2A Protocol Compliance) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Author
Owner

Label compliance fix applied:

  • Removed duplicate label: State/In progress (ID: 1322, incorrect casing)
  • Kept: State/Verified (more advanced state, correct casing)
  • Reason: Issue had both State/In progress and State/Verified — conflicting state labels. Per CONTRIBUTING.md, exactly one State/* label is required. State/Verified is the more advanced state.

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

Label compliance fix applied: - Removed duplicate label: `State/In progress` (ID: 1322, incorrect casing) - Kept: `State/Verified` (more advanced state, correct casing) - Reason: Issue had both `State/In progress` and `State/Verified` — conflicting state labels. Per CONTRIBUTING.md, exactly one `State/*` label is required. `State/Verified` is the more advanced state. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-backlog-groomer
Author
Owner

Starting implementation on branch fix/a2a-plan-correct-rollback-wiring.

Root cause confirmed: _handle_plan_correct (line 530) and _handle_plan_rollback (line 565) in src/cleveragents/a2a/facade.py unconditionally return stub responses — they never check self._plan_lifecycle_service.

Fix: Wire both handlers to PlanLifecycleService.revert_plan(plan_id, PlanPhase.STRATEGIZE, reason=...), matching the pattern used by _handle_plan_cancel, _handle_plan_execute, and _handle_plan_apply.

BDD tests: 8 new scenarios in features/a2a_plan_correct_rollback_wiring.feature covering wired (service present) and unwired (service is None) paths for both handlers.

All nox quality gates (lint, typecheck, unit_tests) passing.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

Starting implementation on branch `fix/a2a-plan-correct-rollback-wiring`. **Root cause confirmed**: `_handle_plan_correct` (line 530) and `_handle_plan_rollback` (line 565) in `src/cleveragents/a2a/facade.py` unconditionally return stub responses — they never check `self._plan_lifecycle_service`. **Fix**: Wire both handlers to `PlanLifecycleService.revert_plan(plan_id, PlanPhase.STRATEGIZE, reason=...)`, matching the pattern used by `_handle_plan_cancel`, `_handle_plan_execute`, and `_handle_plan_apply`. **BDD tests**: 8 new scenarios in `features/a2a_plan_correct_rollback_wiring.feature` covering wired (service present) and unwired (service is None) paths for both handlers. All nox quality gates (lint, typecheck, unit_tests) passing. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
freemo referenced this issue from a commit 2026-04-05 10:18:00 +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.

Reference
cleveragents/cleveragents-core#3117
No description provided.