Files
cleveragents-core/features/edge_case_plan_scenarios.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

254 lines
13 KiB
Gherkin

Feature: Plan edge case scenarios
As a QA engineer
I want to verify that plan operations handle edge cases correctly
So that concurrent execution, resource conflicts, validation chains, and rollbacks are robust
#
# Section 1: Concurrent plan execution edge cases
#
Scenario: Concurrent strategize start attempts on same plan
Given I have a plan lifecycle service
And I have a plan in strategize phase with queued state
When I start strategize on the plan
And I try to start strategize on the same plan again
Then the second strategize start should raise a plan not ready error
Scenario: Concurrent execute start attempts on same plan
Given I have a plan lifecycle service
And I have a plan in execute phase with queued state
When I start execute on the plan
And I try to start execute on the same plan again
Then the second execute start should raise a plan not ready error
Scenario: Concurrent apply start attempts on same plan
Given I have a plan lifecycle service
And I have a plan in apply phase with queued state
When I start apply on the plan
And I try to start apply on the same plan again
Then the second apply start should raise a plan not ready error
Scenario: Concurrent complete and fail on same strategize phase
Given I have a plan lifecycle service
And I have a plan in strategize phase with processing state
When I complete strategize on the plan
And I try to fail strategize with error "Late failure"
Then the plan should be in complete state
And the plan error message should still be "Late failure"
Scenario: Two plans created from same action simultaneously
Given I have a plan lifecycle service
And I have an available action "local/concurrent-action"
When I use the action to create plan for project "proj-a"
And I use the action to create plan for project "proj-b"
Then two distinct plans should exist
And each plan should have a unique plan id
Scenario: Concurrent phase transitions on different plans
Given I have a plan lifecycle service
And I have two plans at different lifecycle stages
When I transition plan A from strategize to execute
And I transition plan B from execute to apply
Then plan A should be in execute phase
And plan B should be in apply phase
# ──────────────────────────────────────────────────
# Section 2: Resource conflict scenarios
# ──────────────────────────────────────────────────
Scenario: Apply changes when target file is read-only
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a pending MODIFY change for a read-only file
When I try to apply the edge case changes
Then a PlanError should be raised mentioning file apply failure
Scenario: Apply changes with overlapping file paths in a single plan
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a CREATE change and a MODIFY change for the same file
When I apply the edge case changes
Then the file should contain the final modified content
And 2 changes should be marked as applied
Scenario: Apply CREATE change with None content
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a CREATE change with None content
When I apply the edge case changes
Then the created file should be empty
And 1 changes should be marked as applied
Scenario: Apply MOVE change with missing source file
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a MOVE change where source does not exist
When I apply the edge case changes
Then the destination file should not exist
And 1 changes should be marked as applied
Scenario: Apply DELETE change for already-deleted file
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a DELETE change for an already-deleted file
When I apply the edge case changes
Then 1 changes should be marked as applied
Scenario: Apply changes with file path containing spaces
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a CREATE change with a file path containing spaces
When I apply the edge case changes
Then the file with spaces in path should exist with correct content
Scenario: Apply changes with deeply nested directory creation
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a CREATE change in a deeply nested directory
When I apply the edge case changes
Then the deeply nested file should exist
# ──────────────────────────────────────────────────
# Section 2b: Path traversal rejection (H4)
# ──────────────────────────────────────────────────
Scenario: Apply CREATE change with relative path traversal is rejected
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a CREATE change with a path traversal in file_path
When I try to apply the edge case changes
Then a PlanError should be raised mentioning path traversal
Scenario: Apply MODIFY change with absolute path outside project is rejected
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a MODIFY change with an absolute path outside the project
When I try to apply the edge case changes
Then a PlanError should be raised mentioning path traversal
Scenario: Apply DELETE change with path traversal is rejected
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a DELETE change with a path traversal in file_path
When I try to apply the edge case changes
Then a PlanError should be raised mentioning path traversal
Scenario: Apply MOVE change with path traversal in new_path is rejected
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a MOVE change with a path traversal in new_path
When I try to apply the edge case changes
Then a PlanError should be raised mentioning path traversal
# ──────────────────────────────────────────────────
# Section 3: Validation failure chains
# ──────────────────────────────────────────────────
Scenario: Action use with multiple simultaneous argument validation failures
Given I have a plan lifecycle service
And I have an available action with multiple typed arguments
When I try to use the action with wrong types and missing required args
Then a validation error should list multiple argument errors
Scenario: Action use with unknown arguments alongside missing required
Given I have a plan lifecycle service
And I have an available action with one required argument "count" of type "int"
When I try to use the action with unknown argument "bogus" and no required args
Then a validation error should mention both missing and unknown arguments
Scenario: Plan model rejects empty description
When I try to create an edge case plan with empty description
Then a Pydantic validation error should be raised
Scenario: Plan model rejects invalid phase value
When I try to create an edge case plan with invalid phase value
Then a Pydantic validation error should be raised
Scenario: NamespacedName rejects invalid characters in namespace
When I try to parse a namespaced name with special characters "inv@lid/action"
Then a Pydantic validation error should be raised
Scenario: NamespacedName rejects invalid characters in name
When I try to parse a namespaced name with special chars in name "local/my action!"
Then a Pydantic validation error should be raised
# ──────────────────────────────────────────────────
# Section 4: Rollback edge cases
# ──────────────────────────────────────────────────
Scenario: Partial apply failure leaves earlier changes applied on disk
Given I have a temporary test directory for edge case plan service
And I have a Unit of Work instance for edge case plan testing
And I have an edge case PlanService instance
And I have a saved project with current plan for edge cases
And the plan has a valid CREATE change followed by a failing MODIFY change
When I try to apply the edge case changes
Then a PlanError should be raised mentioning file apply failure
And the first file should exist on disk despite the error
And the second file should remain unchanged on disk
Scenario: Fail strategize after start does not reset to queued
Given I have a plan lifecycle service
And I have a plan in strategize phase with processing state
When strategize fails with error "Provider timeout"
Then the lifecycle plan processing state should be "errored"
And the plan cannot be restarted from errored state
Scenario: Fail execute preserves the error message
Given I have a plan lifecycle service
And I have a plan in execute phase with processing state
When execute fails with error "Code generation failed"
Then the lifecycle plan processing state should be "errored"
And the lifecycle plan error message should be "Code generation failed"
Scenario: Fail apply after partial processing
Given I have a plan lifecycle service
And I have a plan in apply phase with processing state
When apply fails with error "Disk full during write"
Then the lifecycle plan processing state should be "errored"
And the lifecycle plan error message should be "Disk full during write"
And the plan should be terminal
Scenario: Cancel plan clears processing but does not revert to previous phase
Given I have a plan lifecycle service
And I have a plan in execute phase with processing state
When I cancel the plan with reason "User abort"
Then the lifecycle plan processing state should be "cancelled"
And the plan phase should remain "execute"
Scenario: Re-execute after errored strategize is rejected
Given I have a plan lifecycle service
And I have a plan in strategize phase with processing state
When strategize fails with error "Timed out"
And I try to execute the errored plan
Then a plan not ready error should be raised for the errored plan
Scenario: Cannot complete strategize after it has been failed
Given I have a plan lifecycle service
And I have a plan in strategize phase with processing state
When strategize fails with error "Network error"
And I try to complete strategize after failure
Then a plan error should be raised because plan is not processing