Files
cleveragents-core/features/plan_lifecycle_model_validation.feature
Luis Mendes 9e316b1a3e
CI / build (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 47s
CI / lint (pull_request) Successful in 3m17s
CI / quality (pull_request) Successful in 3m33s
CI / security (pull_request) Successful in 3m59s
CI / unit_tests (pull_request) Successful in 5m31s
CI / docker (pull_request) Successful in 57s
CI / coverage (pull_request) Successful in 12m32s
CI / status-check (pull_request) Successful in 1s
CI / integration_tests (pull_request) Successful in 2m25s
CI / e2e_tests (pull_request) Successful in 7m9s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (push) Successful in 26s
CI / lint (push) Successful in 3m18s
CI / typecheck (push) Successful in 3m54s
CI / security (push) Successful in 4m2s
CI / quality (push) Successful in 3m33s
CI / integration_tests (push) Successful in 5m47s
CI / unit_tests (push) Successful in 7m6s
CI / docker (push) Successful in 39s
CI / benchmark-regression (pull_request) Failing after 21m11s
CI / coverage (push) Failing after 19m3s
CI / benchmark-regression (push) Has been skipped
CI / e2e_tests (push) Failing after 21m14s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Failing after 18m51s
fix(domain): align plan lifecycle model validation with specification
Aligned the plan lifecycle model with the specification:

1. ERRORED is now treated as terminal in is_terminal property,
   matching the spec table where errored is marked "Terminal? Yes"
   for all processing phases.

2. Added per-phase state validation via model_validator: APPLIED
   and CONSTRAINED are only valid in APPLY phase; COMPLETE is only
   valid in STRATEGIZE or EXECUTE phases. Invalid combinations
   now raise ValueError at construction time.

3. Updated ProcessingState.COMPLETE docstring to clarify phase-level
   terminality semantics.

4. Fixed assignment ordering in execute_plan() to set
   processing_state before phase, consistent with the state-first
   pattern used in apply_plan() and _perform_reversion().

5. Added defensive coercion in LifecyclePlanModel.to_domain() to
   handle legacy DB rows with invalid phase/state combinations
   (e.g. APPLY/COMPLETE -> APPLY/APPLIED) with warning-level
   logging for observability.

6. Updated module docstrings: ERRORED description now reflects
   terminal semantics, terminal outcomes location clarified for
   all phases, can_revert_to docstring notes ERRORED/CONSTRAINED
   are terminal but revertable, is_terminal docstring explains
   the distinction between terminal and permanently irrecoverable
   and documents why COMPLETE is not plan-terminal despite the
   spec marking it "Terminal? Yes" (phase-level vs plan-level).

7. Updated PlanResumeService.validate_eligibility() docstring to
   reflect that ERRORED is now terminal but still eligible for
   resume.

8. Added CHANGELOG entry.

ISSUES CLOSED: #918
2026-03-23 23:33:33 +00:00

191 lines
8.9 KiB
Gherkin

Feature: Plan lifecycle model validation
Verify that the plan lifecycle model enforces the specification
constraints: ERRORED terminality, per-phase state validation,
and rejection of invalid phase/state combinations.
# ---------------------------------------------------------------
# ERRORED is terminal (spec alignment)
# ---------------------------------------------------------------
Scenario: ERRORED state is terminal
Given a plmv plan in STRATEGIZE phase with ERRORED state
Then the plmv plan should be terminal
# ---------------------------------------------------------------
# APPLIED only valid in APPLY phase
# ---------------------------------------------------------------
Scenario: APPLIED only valid in APPLY phase
When I try to create a plmv plan with phase STRATEGIZE and state APPLIED
Then a plmv validation error should be raised containing "APPLIED is only valid in the APPLY phase"
# ---------------------------------------------------------------
# CONSTRAINED only valid in APPLY phase
# ---------------------------------------------------------------
Scenario: CONSTRAINED only valid in APPLY phase
When I try to create a plmv plan with phase EXECUTE and state CONSTRAINED
Then a plmv validation error should be raised containing "CONSTRAINED is only valid in the APPLY phase"
# ---------------------------------------------------------------
# COMPLETE only valid in STRATEGIZE or EXECUTE phases
# ---------------------------------------------------------------
Scenario: COMPLETE only valid in STRATEGIZE or EXECUTE phase
When I try to create a plmv plan with phase APPLY and state COMPLETE
Then a plmv validation error should be raised containing "COMPLETE is only valid in STRATEGIZE or EXECUTE"
# ---------------------------------------------------------------
# QUEUED valid in any phase
# ---------------------------------------------------------------
Scenario: QUEUED valid in any phase
Given a plmv plan in STRATEGIZE phase with QUEUED state
And a plmv plan in EXECUTE phase with QUEUED state
And a plmv plan in APPLY phase with QUEUED state
Then all plmv plans should be valid
# ---------------------------------------------------------------
# Additional coverage: valid combos
# ---------------------------------------------------------------
Scenario: APPLIED is valid in APPLY phase
Given a plmv plan in APPLY phase with APPLIED state
Then the plmv plan should be terminal
Scenario: CONSTRAINED is valid in APPLY phase
Given a plmv plan in APPLY phase with CONSTRAINED state
Then the plmv plan should be terminal
Scenario: COMPLETE is valid in STRATEGIZE phase
Given a plmv plan in STRATEGIZE phase with COMPLETE state
Then the plmv plan should not be terminal
Scenario: COMPLETE is valid in EXECUTE phase
Given a plmv plan in EXECUTE phase with COMPLETE state
Then the plmv plan should not be terminal
Scenario: ERRORED in APPLY phase is also terminal
Given a plmv plan in APPLY phase with ERRORED state
Then the plmv plan should be terminal
Scenario: CANCELLED in EXECUTE phase is terminal
Given a plmv plan in EXECUTE phase with CANCELLED state
Then the plmv plan should be terminal
# ---------------------------------------------------------------
# Invalid combos for ACTION phase
# ---------------------------------------------------------------
Scenario: COMPLETE is not valid in ACTION phase
When I try to create a plmv plan with phase ACTION and state COMPLETE
Then a plmv validation error should be raised containing "COMPLETE is only valid in STRATEGIZE or EXECUTE"
Scenario: APPLIED is not valid in EXECUTE phase
When I try to create a plmv plan with phase EXECUTE and state APPLIED
Then a plmv validation error should be raised containing "APPLIED is only valid in the APPLY phase"
Scenario: APPLIED is not valid in ACTION phase
When I try to create a plmv plan with phase ACTION and state APPLIED
Then a plmv validation error should be raised containing "APPLIED is only valid in the APPLY phase"
Scenario: CONSTRAINED is not valid in ACTION phase
When I try to create a plmv plan with phase ACTION and state CONSTRAINED
Then a plmv validation error should be raised containing "CONSTRAINED is only valid in the APPLY phase"
Scenario: CONSTRAINED is not valid in STRATEGIZE phase
When I try to create a plmv plan with phase STRATEGIZE and state CONSTRAINED
Then a plmv validation error should be raised containing "CONSTRAINED is only valid in the APPLY phase"
# ---------------------------------------------------------------
# PROCESSING valid in any phase (T1)
# ---------------------------------------------------------------
Scenario: PROCESSING valid in any phase
Given a plmv plan in ACTION phase with PROCESSING state
And a plmv plan in STRATEGIZE phase with PROCESSING state
And a plmv plan in EXECUTE phase with PROCESSING state
And a plmv plan in APPLY phase with PROCESSING state
Then all plmv plans should be valid
# ---------------------------------------------------------------
# ERRORED valid in all phases including ACTION (T2)
# ---------------------------------------------------------------
Scenario: ERRORED in ACTION phase is terminal
Given a plmv plan in ACTION phase with ERRORED state
Then the plmv plan should be terminal
Scenario: ERRORED in EXECUTE phase is terminal
Given a plmv plan in EXECUTE phase with ERRORED state
Then the plmv plan should be terminal
# ---------------------------------------------------------------
# CANCELLED valid in all phases (additional)
# ---------------------------------------------------------------
Scenario: CANCELLED in ACTION phase is terminal
Given a plmv plan in ACTION phase with CANCELLED state
Then the plmv plan should be terminal
Scenario: CANCELLED in STRATEGIZE phase is terminal
Given a plmv plan in STRATEGIZE phase with CANCELLED state
Then the plmv plan should be terminal
Scenario: CANCELLED in APPLY phase is terminal
Given a plmv plan in APPLY phase with CANCELLED state
Then the plmv plan should be terminal
# ---------------------------------------------------------------
# Assignment-order regression: state-before-phase (T6)
# ---------------------------------------------------------------
Scenario: Phase transition with state-first assignment does not raise
Given a plmv plan in STRATEGIZE phase with COMPLETE state
When I plmv transition the plan to EXECUTE phase with QUEUED state using state-first order
Then the plmv plan should have phase EXECUTE and state QUEUED
# ---------------------------------------------------------------
# Assignment-order negative: phase-first with invalid intermediate
# ---------------------------------------------------------------
Scenario: Phase-first assignment with invalid intermediate state raises
Given a plmv plan in STRATEGIZE phase with COMPLETE state
When I plmv transition the plan to APPLY phase with APPLIED state using phase-first order
Then a plmv validation error should be raised containing "COMPLETE is only valid in STRATEGIZE or EXECUTE"
# ---------------------------------------------------------------
# ERRORED terminality blocks cancel, pause, resume (lifecycle)
# ---------------------------------------------------------------
Scenario: ERRORED plan cannot be cancelled because it is terminal
Given a plmv plan in EXECUTE phase with ERRORED state
Then the plmv plan should be terminal
And the plmv plan should not be cancellable
Scenario: ERRORED plan cannot be paused because it is terminal
Given a plmv plan in STRATEGIZE phase with ERRORED state
Then the plmv plan should be terminal
And the plmv plan should not be pausable
Scenario: ERRORED plan cannot be resumed via lifecycle because it is terminal
Given a plmv plan in EXECUTE phase with ERRORED state
Then the plmv plan should be terminal
And the plmv plan should not be resumable via lifecycle
# ---------------------------------------------------------------
# Deserialization coercion for legacy DB rows
# ---------------------------------------------------------------
Scenario: Legacy APPLY/COMPLETE is coerced to APPLY/APPLIED on deserialization
When I plmv deserialize a plan with phase "apply" and state "complete"
Then the plmv deserialized plan should have phase APPLY and state APPLIED
Scenario: Legacy STRATEGIZE/APPLIED is coerced to STRATEGIZE/ERRORED on deserialization
When I plmv deserialize a plan with phase "strategize" and state "applied"
Then the plmv deserialized plan should have phase STRATEGIZE and state ERRORED
Scenario: Legacy ACTION/COMPLETE is coerced to ACTION/QUEUED on deserialization
When I plmv deserialize a plan with phase "action" and state "complete"
Then the plmv deserialized plan should have phase ACTION and state QUEUED