Files
cleveragents-core/features/plan_persistence.feature
freemo 4ad51561fc perf(tests): optimize medium-slow BDD features (10-100s tier)
Cap time.sleep and asyncio.sleep globally at 10ms in before_all to
eliminate retry/backoff waits (tenacity wait_fixed, retry_auto_debug
exponential backoff). Save originals as time._original_sleep and
asyncio._original_sleep for tests that need real wall-clock delays
(CircuitBreaker recovery, debounce timers, validation timeouts).

Enhance template-DB patch: add "db." prefix to _SCENARIO_DB_PREFIXES
and check db_path.stat().st_size > 0 so 0-byte auto-created SQLite
files receive the template copy instead of falling through to real
migrations.

Replace subprocess.run CLI invocations with typer.testing.CliRunner
in module_coverage, main_coverage_complete, and coverage_extras step
files, eliminating ~6s Python cold-start overhead per call.

Switch plan_persistence and action_persistence to in-memory SQLite by
default; only cross-restart scenarios use file-based via an explicit
Given step.

Replace MigrationRunner.run_migrations with Base.metadata.create_all
in plan_service_steps for freshly created in-memory engines.

Removed leftover debug comment in environment.py.

Total tier runtime: 565s -> 21s (96% reduction), 20 features all
under 5s behave-internal time.

ISSUES CLOSED: #480
2026-03-02 02:01:27 +00:00

130 lines
6.6 KiB
Gherkin

Feature: Plan persistence via LifecyclePlanRepository
As a developer
I want plans to persist correctly through the LifecyclePlanRepository
So that plan lifecycle state is durable across operations
Background:
Given a fresh in-memory plan persistence database
And a prerequisite action "local/persist-action" exists in the database
# Create scenarios
Scenario: Create a plan and retrieve it by ID
Given a new lifecycle plan with ID "01HV000000000000000000PP01"
When I persist the plan via the plan repository
Then I can retrieve the plan by ID "01HV000000000000000000PP01"
And the persisted plan description should be "Persistence test plan"
Scenario: Create a plan preserves all identity fields
Given a new lifecycle plan with parent tree ID "01HV000000000000000000PP02" parent "01HV000000000000000000PP01" root "01HV000000000000000000PP01"
When I persist the plan via the plan repository
Then I can retrieve the plan by ID "01HV000000000000000000PP02"
And the plan parent_plan_id should be "01HV000000000000000000PP01"
And the plan root_plan_id should be "01HV000000000000000000PP01"
# Phase and state transition scenarios
Scenario: Plan persists phase transition from action to strategize
Given a persisted plan in phase "action" with state "queued"
When I update the plan phase to "strategize" with state "queued"
Then the plan persistence phase should be "strategize"
And the persisted plan processing_state should be "queued"
Scenario: Plan persists phase transition from strategize to execute
Given a persisted plan in phase "strategize" with state "complete"
When I update the plan phase to "execute" with state "queued"
Then the plan persistence phase should be "execute"
And the persisted plan processing_state should be "queued"
Scenario: Plan persists phase transition from execute to apply
Given a persisted plan in phase "execute" with state "complete"
When I update the plan phase to "apply" with state "queued"
Then the plan persistence phase should be "apply"
And the persisted plan processing_state should be "queued"
Scenario: Plan persists processing state transition to processing
Given a persisted plan in phase "strategize" with state "queued"
When I update the plan phase to "strategize" with state "processing"
Then the persisted plan processing_state should be "processing"
Scenario: Plan persists terminal applied state
Given a persisted plan in phase "apply" with state "queued"
When I update the plan phase to "apply" with state "applied"
Then the persisted plan processing_state should be "applied"
Scenario: Plan persists terminal constrained state
Given a persisted plan in phase "apply" with state "queued"
When I update the plan phase to "apply" with state "constrained"
Then the persisted plan processing_state should be "constrained"
Scenario: Plan persists terminal errored state
Given a persisted plan in phase "apply" with state "queued"
When I update the plan phase to "apply" with state "errored"
Then the persisted plan processing_state should be "errored"
Scenario: Plan persists terminal cancelled state
Given a persisted plan in phase "strategize" with state "queued"
When I update the plan phase to "strategize" with state "cancelled"
Then the persisted plan processing_state should be "cancelled"
# List filter scenarios
Scenario: List plans filtered by phase
Given 3 persisted plans in phase "strategize"
And 2 persisted plans in phase "execute"
When I list persisted plans filtered by phase "strategize"
Then I should get 3 plans in the list
Scenario: List plans filtered by processing state
Given 2 persisted plans with processing state "queued"
And 1 persisted plan with processing state "processing"
When I list plans filtered by processing_state "queued"
Then I should get 2 plans in the list
Scenario: List plans filtered by action name
Given 2 persisted plans linked to action "local/persist-action"
When I list plans filtered by action_name "local/persist-action"
Then I should get 2 plans in the list
# Plan tree link scenarios
Scenario: Plan tree preserves parent-child relationships
Given a parent plan with ID "01HV0000000000000000TREE01"
And a child plan with ID "01HV0000000000000000TREE02" under parent "01HV0000000000000000TREE01"
When I retrieve the child plan "01HV0000000000000000TREE02"
Then the child plan should reference parent "01HV0000000000000000TREE01"
And the child plan should reference root "01HV0000000000000000TREE01"
Scenario: Plan tree preserves three-level hierarchy
Given a root plan with ID "01HV0000000000000000R00T01"
And a mid plan with ID "01HV0000000000000000M0D001" under root "01HV0000000000000000R00T01"
And a leaf plan with ID "01HV0000000000000000KEAF01" under parent "01HV0000000000000000M0D001" and root "01HV0000000000000000R00T01"
When I retrieve the leaf plan "01HV0000000000000000KEAF01"
Then the leaf plan parent should be "01HV0000000000000000M0D001"
And the leaf plan root should be "01HV0000000000000000R00T01"
# Cross-restart scenarios (require file-based SQLite to survive reconnection)
Scenario: Plan status persists across database reconnection
Given the plan persistence database is file-based
And a prerequisite action "local/persist-action" exists in the database
And a persisted plan in phase "execute" with state "processing"
When I close and reopen the persistence database
Then the plan should still be in phase "execute" with state "processing"
Scenario: Plan with project links persists across reconnection
Given the plan persistence database is file-based
And a prerequisite action "local/persist-action" exists in the database
And a persisted plan with project links "proj-alpha" and "proj-beta"
When I close and reopen the persistence database
Then the plan should still have 2 project links
Scenario: Plan with arguments persists across reconnection
Given the plan persistence database is file-based
And a prerequisite action "local/persist-action" exists in the database
And a persisted plan with arguments "target" and "coverage"
When I close and reopen the persistence database
Then the plan should still have 2 arguments in order
Scenario: Plan with invariants persists across reconnection
Given the plan persistence database is file-based
And a prerequisite action "local/persist-action" exists in the database
And a persisted plan with invariant "No breaking changes"
When I close and reopen the persistence database
Then the plan should still have invariant "No breaking changes"