UAT: _perform_reversion in PlanLifecycleService does not emit domain events for plan phase reversion, breaking audit log completeness #3736

Open
opened 2026-04-05 22:22:42 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/plan-reversion-domain-event
  • Commit Message: fix(plan): emit PLAN_PHASE_CHANGED event in _perform_reversion
  • Milestone: None (Backlog)
  • Parent Epic: #362

Background and Context

PlanLifecycleService._perform_reversion in src/cleveragents/application/services/plan_lifecycle_service.py (lines 2596–2648) updates the plan state and commits it but does NOT emit a domain event. Every other phase transition method in PlanLifecycleService emits a domain event:

  • complete_strategize → emits PLAN_STATE_CHANGED
  • execute_plan → emits PLAN_PHASE_CHANGED
  • apply_plan → (no event, but complete_apply emits PLAN_APPLIED)
  • fail_strategize → emits PLAN_ERRORED
  • fail_execute → emits PLAN_ERRORED
  • fail_apply → emits PLAN_ERRORED
  • cancel_plan → emits PLAN_CANCELLED
  • complete_apply → emits PLAN_APPLIED

But _perform_reversion (called by revert_plan, try_auto_revert_from_apply, try_auto_revert_from_execute) emits NO event. This means plan reversions are invisible to the audit log and any event subscribers.

The specification (docs/specification.md §Audit Logging) requires that all significant lifecycle transitions be captured in the audit log via domain events.

This was discovered during UAT testing of the Plan Lifecycle feature area.

Current Behavior

_perform_reversion (lines 2596–2648):

  1. Records a reversion decision in plan.decisions
  2. Updates plan state ✓
  3. Commits the plan ✓
  4. Logs the reversion ✓
  5. Does NOT emit a domain event

Callers of _perform_reversion:

  • revert_plan (manual reversion via agents plan revert)
  • try_auto_revert_from_apply (automatic reversion from constrained Apply)
  • try_auto_revert_from_execute (automatic reversion from Execute)

None of these reversion paths produce a domain event.

Expected Behavior

_perform_reversion should emit a PLAN_PHASE_CHANGED event (or a dedicated PLAN_REVERTED event) after successfully reverting the plan, consistent with all other phase transition methods:

if self.event_bus is not None:
    try:
        self.event_bus.emit(
            DomainEvent(
                event_type=EventType.PLAN_PHASE_CHANGED,
                plan_id=plan_id,
                details={
                    "from_phase": source_phase.value,
                    "to_phase": to_phase.value,
                    "processing_state": plan.processing_state.value,
                    "reason": reason,
                    "reversion_count": plan.reversion_count,
                },
            )
        )
    except Exception:
        self._logger.warning("event_bus_emit_failed", ...)

Steps to Reproduce

  1. Create a plan and run it through Execute phase
  2. Call revert_plan(plan_id, PlanPhase.STRATEGIZE)
  3. Observe: plan is reverted but no domain event is emitted
  4. Check audit log: no reversion event recorded

Code Location

  • File: src/cleveragents/application/services/plan_lifecycle_service.py
  • Lines: 2596–2648 (_perform_reversion method)
  • Related: EventType in src/cleveragents/infrastructure/events/types.py

Subtasks

  • Add domain event emission to _perform_reversion after successful state commit
  • Use EventType.PLAN_PHASE_CHANGED or add a new EventType.PLAN_REVERTED if appropriate
  • Add/update unit test in features/ to verify event emission on reversion
  • Verify nox -e unit_tests passes
  • Verify nox -e typecheck passes

Definition of Done

  • _perform_reversion emits a domain event after successful reversion
  • Event includes from_phase, to_phase, reason, and reversion_count
  • Unit test coverage for event emission on reversion
  • All nox quality gates pass
  • PR merged
  • All nox stages pass
  • Coverage >= 97%

Backlog note: This issue was discovered during autonomous operation
on milestone v3.3.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/plan-reversion-domain-event` - **Commit Message**: `fix(plan): emit PLAN_PHASE_CHANGED event in _perform_reversion` - **Milestone**: None (Backlog) - **Parent Epic**: #362 ## Background and Context `PlanLifecycleService._perform_reversion` in `src/cleveragents/application/services/plan_lifecycle_service.py` (lines 2596–2648) updates the plan state and commits it but does NOT emit a domain event. Every other phase transition method in `PlanLifecycleService` emits a domain event: - `complete_strategize` → emits `PLAN_STATE_CHANGED` - `execute_plan` → emits `PLAN_PHASE_CHANGED` - `apply_plan` → (no event, but `complete_apply` emits `PLAN_APPLIED`) - `fail_strategize` → emits `PLAN_ERRORED` - `fail_execute` → emits `PLAN_ERRORED` - `fail_apply` → emits `PLAN_ERRORED` - `cancel_plan` → emits `PLAN_CANCELLED` - `complete_apply` → emits `PLAN_APPLIED` But `_perform_reversion` (called by `revert_plan`, `try_auto_revert_from_apply`, `try_auto_revert_from_execute`) emits NO event. This means plan reversions are invisible to the audit log and any event subscribers. The specification (docs/specification.md §Audit Logging) requires that all significant lifecycle transitions be captured in the audit log via domain events. This was discovered during UAT testing of the Plan Lifecycle feature area. ## Current Behavior `_perform_reversion` (lines 2596–2648): 1. Records a reversion decision in `plan.decisions` ✓ 2. Updates plan state ✓ 3. Commits the plan ✓ 4. Logs the reversion ✓ 5. **Does NOT emit a domain event** ✗ Callers of `_perform_reversion`: - `revert_plan` (manual reversion via `agents plan revert`) - `try_auto_revert_from_apply` (automatic reversion from constrained Apply) - `try_auto_revert_from_execute` (automatic reversion from Execute) None of these reversion paths produce a domain event. ## Expected Behavior `_perform_reversion` should emit a `PLAN_PHASE_CHANGED` event (or a dedicated `PLAN_REVERTED` event) after successfully reverting the plan, consistent with all other phase transition methods: ```python if self.event_bus is not None: try: self.event_bus.emit( DomainEvent( event_type=EventType.PLAN_PHASE_CHANGED, plan_id=plan_id, details={ "from_phase": source_phase.value, "to_phase": to_phase.value, "processing_state": plan.processing_state.value, "reason": reason, "reversion_count": plan.reversion_count, }, ) ) except Exception: self._logger.warning("event_bus_emit_failed", ...) ``` ## Steps to Reproduce 1. Create a plan and run it through Execute phase 2. Call `revert_plan(plan_id, PlanPhase.STRATEGIZE)` 3. Observe: plan is reverted but no domain event is emitted 4. Check audit log: no reversion event recorded ## Code Location - **File**: `src/cleveragents/application/services/plan_lifecycle_service.py` - **Lines**: 2596–2648 (`_perform_reversion` method) - **Related**: `EventType` in `src/cleveragents/infrastructure/events/types.py` ## Subtasks - [ ] Add domain event emission to `_perform_reversion` after successful state commit - [ ] Use `EventType.PLAN_PHASE_CHANGED` or add a new `EventType.PLAN_REVERTED` if appropriate - [ ] Add/update unit test in `features/` to verify event emission on reversion - [ ] Verify `nox -e unit_tests` passes - [ ] Verify `nox -e typecheck` passes ## Definition of Done - [ ] `_perform_reversion` emits a domain event after successful reversion - [ ] Event includes `from_phase`, `to_phase`, `reason`, and `reversion_count` - [ ] Unit test coverage for event emission on reversion - [ ] All nox quality gates pass - [ ] PR merged - [ ] All nox stages pass - [ ] Coverage >= 97% > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.3.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
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
#362 Epic: Security & Safety Hardening
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3736
No description provided.