Files
cleveragents-core/features/database_models_lifecycle_coverage.feature
T
CoreRasurae f2f7aa5dc9 feat(core): add v3 lifecycle models, automation levels, subplan support, and security hardening
Implement multiple Stage A/B/E/SEC milestones for the v3 lifecycle system:
- Stage A5.3+A5.4: Add LifecycleActionModel and LifecyclePlanModel SQLAlchemy
  models with to_domain()/from_domain() conversion methods
- Stage A5.6: Implement ActionRepository with full CRUD, namespace/state
  queries, referential integrity checks, and retry decorator
- Stage E1: Add subplan domain models (ExecutionMode, SubplanMergeStrategy,
  SubplanConfig, SubplanStatus, SubplanAttempt, SubplanFailureHandler) with
  computed properties on Plan (is_subplan, is_root_plan, depth, has_subplans)
- Stage A6: Add AutomationLevel enum (MANUAL, REVIEW_BEFORE_APPLY,
  FULL_AUTOMATION), settings integration, PlanLifecycleService auto-progression,
  pause/resume, and CLI commands (--automation-level, set-automation-level)
- Stage SEC1: Remove eval()/exec() from stream_router.py, replace with named
  operation and transform registries; code blocks and unregistered transforms
  now raise StreamRoutingError
- Add langchain-anthropic dependency
- Update BDD tests for security changes and relax ADR directory requirement
2026-02-12 20:19:42 +00:00

177 lines
8.8 KiB
Gherkin

@phase1 @database @models @lifecycle
Feature: Lifecycle Data Persistence and Retrieval
As a system operator
I want lifecycle actions and plans to survive database round-trips faithfully
So that no data is lost or corrupted when storing and loading lifecycle records
Background:
Given the lifecycle database is ready
And a lifecycle database session is open
@lifecycle_action @to_domain
Scenario: A stored action retains its identity and naming when loaded
Given an action record exists with valid attributes and tags
When the action record is loaded as a domain object
Then the loaded action should preserve its original identifier
And the loaded action should preserve its namespace and short name
And the loaded action should preserve its description fields
And the loaded action should preserve its actor assignments
And the loaded action should preserve its state and flags
And the loaded action should preserve its timestamps
And the loaded action should preserve its tags
@lifecycle_action @to_domain
Scenario: A stored action with input arguments loads them correctly
Given an action record exists with a structured arguments schema
When the action record is loaded as a domain object
Then the loaded action should contain the expected argument entries
And each argument entry should have the correct name and type
@lifecycle_action @to_domain
Scenario: A stored action with no inputs or tags loads empty collections
Given an action record exists with no inputs and no tags
When the action record is loaded as a domain object
Then the loaded action should have an empty arguments collection
And the loaded action should have an empty tags collection
@lifecycle_action @from_domain
Scenario: A fully populated action domain object is stored correctly
Given a complete action domain object is prepared
When the action domain object is stored as a database record
Then the stored record should preserve the action identifier
And the stored record should preserve the name components
And the stored record should preserve the description fields
And the stored record should preserve the actor assignments
And the stored record should serialize the arguments as JSON
And the stored record should serialize the tags as JSON
And the stored record should preserve the state value
And the stored record should format timestamps as ISO strings
@lifecycle_action @from_domain
Scenario: An action with an enumerated state stores the enum value
Given an action domain object is prepared with an enumerated state
When the action domain object is stored as a database record
Then the stored record state should equal the enum value
@lifecycle_action @from_domain
Scenario: An action with a custom string state stores it verbatim
Given an action-like object is prepared with a custom string state
When the custom-state action is stored as a database record
Then the stored record state should equal the custom string
@lifecycle_plan @parse_iso
Scenario: A valid ISO-8601 timestamp string is parsed to a datetime
When a valid ISO-8601 string is parsed as a timestamp
Then the parsed timestamp should be the expected datetime value
@lifecycle_plan @parse_iso
Scenario: A missing timestamp value parses to nothing
When an absent value is parsed as a timestamp
Then the parsed timestamp should be absent
@lifecycle_plan @to_iso
Scenario: A datetime is formatted as an ISO-8601 string
When a datetime value is formatted as an ISO string
Then the formatted string should match ISO-8601 format
@lifecycle_plan @to_iso
Scenario: An absent datetime formats to nothing
When an absent datetime is formatted as an ISO string
Then the formatted value should be absent
@lifecycle_plan @to_domain
Scenario: A plan in the action phase loads with its action state
Given a plan record exists in the action phase with draft state
When the plan record is loaded as a domain object
Then the loaded plan should preserve its identity
And the loaded plan should be in the action phase
And the loaded plan action state should be draft
And the loaded plan processing state should be absent
And the loaded plan should preserve its description
And the loaded plan should preserve its timestamps
And the loaded plan should preserve its metadata
@lifecycle_plan @to_domain
Scenario: A plan in the strategize phase loads with its processing state
Given a plan record exists in the strategize phase with processing state
When the plan record is loaded as a domain object
Then the loaded plan should be in the strategize phase
And the loaded plan processing state should be processing
And the loaded plan action state should be absent
@lifecycle_plan @to_domain
Scenario: A completed plan loads all phase timestamps correctly
Given a plan record exists with all phase timestamps populated
When the plan record is loaded as a domain object
Then the loaded plan timestamps should include the strategize window
And the loaded plan timestamps should include the execute window
And the loaded plan timestamps should include the apply window
@lifecycle_plan @to_domain
Scenario: A plan with associated projects and tags loads them as lists
Given a plan record exists with associated project identifiers and tags
When the plan record is loaded as a domain object
Then the loaded plan should contain the expected project identifiers
And the loaded plan should contain the expected tags
@lifecycle_plan @from_domain
Scenario: A plan with an action state stores the state correctly
Given a plan domain object is prepared in the action phase with an available state
When the plan domain object is stored as a database record
Then the stored plan record should have state "available"
And the stored plan record should preserve the plan identifier
And the stored plan record should preserve the phase
And the stored plan record should serialize the project identifiers as JSON
And the stored plan record should serialize the plan tags as JSON
And the stored plan record should format plan timestamps as ISO strings
And the stored plan record automation level should be "manual"
@lifecycle_plan @from_domain
Scenario: A plan with a processing state stores the state correctly
Given a plan domain object is prepared in the strategize phase with a queued state
When the plan domain object is stored as a database record
Then the stored plan record should have state "queued"
And the stored plan record phase should be "strategize"
@lifecycle_plan @from_domain
Scenario: A plan with no explicit state defaults to queued
Given a plan domain object is prepared with neither action nor processing state
When the stateless plan domain object is stored as a database record
Then the stored plan record should have state "queued"
@lifecycle_plan @from_domain
Scenario: A plan with all phase timestamps stores them as ISO strings
Given a plan domain object is prepared with all phase timestamps
When the plan domain object is stored as a database record
Then the stored plan record should have all phase timestamps as ISO strings
@lifecycle_plan @from_domain
Scenario: A plan with non-default automation level stores the real value
Given a plan domain object is prepared with automation level "full_automation"
When the plan domain object is stored as a database record
Then the stored plan record automation level should be "full_automation"
@lifecycle_plan @from_domain
Scenario: A plan with review-before-apply automation level stores correctly
Given a plan domain object is prepared with automation level "review_before_apply"
When the plan domain object is stored as a database record
Then the stored plan record automation level should be "review_before_apply"
@lifecycle_plan @from_domain
Scenario: A plan stored with an explicit action_id preserves it
Given a plan domain object is prepared in the action phase with an available state
When the plan domain object is stored with an explicit action identifier
Then the stored plan record should preserve the supplied action identifier
@lifecycle_action @round_trip
Scenario: An action survives a full save-and-reload cycle unchanged
Given a complete action domain object is prepared
When the action is saved to the database and reloaded as a domain object
Then the reloaded action should match the original action
@lifecycle_plan @round_trip
Scenario: A plan survives a full save-and-reload cycle unchanged
Given a plan record exists in the action phase with draft state
When the plan record is saved and then reloaded as a domain object
Then the reloaded plan should preserve its identity and phase