Files
cleveragents-core/features/consolidated_plan_model_lifecycle.feature
T
HAL9000 f808abff86 chore(ci): fix pre-commit hook failures
Fix JSON syntax errors in .devcontainer/devcontainer.json (removed
invalid JS-style // comments) and .devcontainer/opencode.json (removed
90+ trailing commas). Apply auto-fixes for end-of-file and trailing
whitespace issues across 100+ files. Fix SIM105 ruff violations in
benchmarks/core_circuit_breaker_bench.py (use contextlib.suppress).

Note: The security fix from issue #7478 (validate_path startswith bypass)
was already delivered to master in commit e18ac5f2. This PR as currently
structured is non-atomic (35 commits across 10+ issues) and needs
significant restructure before merge. This commit only addresses the
CI/pre-commit failures.

ISSUES CLOSED: #7478
2026-06-14 09:51:14 -04:00

962 lines
37 KiB
Gherkin

Feature: Consolidated Plan Model Lifecycle
Combined scenarios from: plan_hierarchy_and_failure_handler, plan_lifecycle_helpers_coverage, plan_lifecycle_service_persistence_coverage, plan_lifecycle_transitions_r2, plan_model, plan_model_coverage, plan_model_uncovered_lines
# ============================================================
# Originally from: plan_hierarchy_and_failure_handler.feature
# Feature: Plan Hierarchy and Subplan Failure Handling
# ============================================================
@subplan_hierarchy
Scenario: A standalone plan is not considered a subplan
Given a plan that was created independently
Then the plan should not be recognized as a subplan
@subplan_hierarchy
Scenario: A plan spawned by another plan is a subplan
Given a plan that was spawned by another plan
Then the plan should be recognized as a subplan
@subplan_hierarchy
Scenario: A plan with no designated root is considered the root
Given a plan with no designated root
Then the plan should be recognized as a root plan
@subplan_hierarchy
Scenario: A plan whose root is itself is considered the root
Given a plan whose designated root is itself
Then the plan should be recognized as a root plan
@subplan_hierarchy
Scenario: A plan whose root is a different plan is not the root
Given a plan whose designated root is a different plan
Then the plan should not be recognized as a root plan
@subplan_hierarchy
Scenario: A root plan reports a depth of zero
Given a plan with no designated root
Then the plan hierarchy depth should be 0
@subplan_hierarchy
Scenario: A non-root plan reports a placeholder depth
Given a plan whose designated root is a different plan
Then the plan hierarchy depth should be -1
@subplan_hierarchy
Scenario: A plan with no child work has no subplans
Given a plan that has no child work tracked
Then the plan should report having no subplans
@subplan_hierarchy
Scenario: A plan with tracked child work has subplans
Given a plan that has tracked child work
Then the plan should report having subplans
@failure_handler
Scenario: The failure handler halts remaining work when fail-fast is enabled
Given a subplan configuration with fail-fast enabled and parallel work
And a subplan that has failed
When the failure handler evaluates whether to halt remaining work
Then the remaining work should be halted
@failure_handler
Scenario: The failure handler halts remaining work for sequential execution
Given a subplan configuration with fail-fast disabled and sequential work
And a subplan that has failed
When the failure handler evaluates whether to halt remaining work
Then the remaining work should be halted
@failure_handler
Scenario: The failure handler allows remaining work for parallel execution without fail-fast
Given a subplan configuration with fail-fast disabled and parallel work
And a subplan that has failed
When the failure handler evaluates whether to halt remaining work
Then the remaining work should continue
@failure_handler
Scenario: The failure handler allows remaining work for dependency-ordered execution without fail-fast
Given a subplan configuration with fail-fast disabled and dependency-ordered work
And a subplan that has failed
When the failure handler evaluates whether to halt remaining work
Then the remaining work should continue
@failure_handler
Scenario: The failure handler does not retry when retries are disabled
Given a subplan configuration with retries disabled
And a subplan that failed with error "ValidationError occurred"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: The failure handler does not retry when all attempts are exhausted
Given a subplan configuration allowing up to 2 retries
And a subplan on attempt 3 that failed with error "TimeoutError"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: A configuration error is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "ConfigurationError: bad config"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: An authentication error is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "AuthenticationError: invalid token"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: A missing resource error is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "MissingResourceError: file not found"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: A circular dependency error is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "CircularDependencyError: cycle detected"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: A validation error is eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "ValidationError: schema mismatch"
When the failure handler evaluates whether to retry the failed work
Then the failed work should be retried
@failure_handler
Scenario: A timeout error is eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "TimeoutError: deadline exceeded"
When the failure handler evaluates whether to retry the failed work
Then the failed work should be retried
@failure_handler
Scenario: A temporary resource error is eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "TemporaryResourceError: service unavailable"
When the failure handler evaluates whether to retry the failed work
Then the failed work should be retried
@failure_handler
Scenario: A merge conflict error is eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "MergeConflictError: conflicting changes"
When the failure handler evaluates whether to retry the failed work
Then the failed work should be retried
@failure_handler
Scenario: An unrecognized error type is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with error "SomeUnknownError: unexpected"
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
@failure_handler
Scenario: A failure with no error message is not eligible for retry
Given a subplan configuration allowing up to 3 retries
And a subplan on attempt 1 that failed with no error message
When the failure handler evaluates whether to retry the failed work
Then the failed work should not be retried
# ============================================================
# Originally from: plan_lifecycle_helpers_coverage.feature
# Feature: Plan lifecycle helper coverage
# ============================================================
Scenario: Lifecycle service helper builds a plan lifecycle service
When I call the plan lifecycle service helper
Then the lifecycle service helper should return a plan lifecycle service
# ============================================================
# Originally from: plan_lifecycle_service_persistence_coverage.feature
# Feature: PlanLifecycleService persistence fallback coverage
# ============================================================
Scenario: get_action falls back to persistence layer when not in memory
Given a plan lifecycle service with a mock unit of work
Given an action "local/db-only-action" exists only in the persistence layer
When I call get_action with "local/db-only-action"
Then the returned action should have namespaced name "local/db-only-action"
And the action "local/db-only-action" should now be cached in memory
Scenario: get_action_by_name falls back to persistence layer when not in memory
Given a plan lifecycle service with a mock unit of work
Given an action "local/db-only-named" exists only in the persistence layer for name lookup
When I call get_action_by_name with "local/db-only-named"
Then the returned action from name lookup should have namespaced name "local/db-only-named"
And the action "local/db-only-named" should now be cached in memory after name lookup
# ============================================================
# Originally from: plan_lifecycle_transitions_r2.feature
# Feature: PlanLifecycleService lifecycle transition branch coverage (round 2)
# ============================================================
Scenario: use_action on non-reusable action archives it after plan creation
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a non-reusable action "local/r2-oneshot" exists
When r2plc-I use the non-reusable action to create a plan
Then r2plc-the action "local/r2-oneshot" should be archived
And r2plc-a plan should have been created from the action
# -------------------------------------------------------------------
# execute_plan persisted mode (line 216 True via _commit_plan)
# -------------------------------------------------------------------
Scenario: execute_plan transitions and persists via _commit_plan
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a plan in STRATEGIZE COMPLETE state
When r2plc-I call execute_plan in persisted mode
Then r2plc-the plan should be in EXECUTE phase
And r2plc-the mock UoW should have received a plan update call
# -------------------------------------------------------------------
# apply_plan persisted mode (line 216 True via _commit_plan)
# -------------------------------------------------------------------
Scenario: apply_plan transitions and persists via _commit_plan
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a plan in EXECUTE COMPLETE state
When r2plc-I call apply_plan in persisted mode
Then r2plc-the plan should be in APPLY phase
And r2plc-the mock UoW should have received a plan update call
# -------------------------------------------------------------------
# cancel_plan persisted mode (line 216 True via _commit_plan)
# -------------------------------------------------------------------
Scenario: cancel_plan persists cancellation via _commit_plan
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a plan in STRATEGIZE phase
When r2plc-I cancel the plan with reason "user requested"
Then r2plc-the plan processing state should be "cancelled"
And r2plc-the mock UoW should have received a plan update call
# -------------------------------------------------------------------
# pause_plan and resume_plan persisted mode
# -------------------------------------------------------------------
Scenario: pause_plan persists via _commit_plan
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a plan in STRATEGIZE phase
When r2plc-I pause the plan
Then r2plc-the plan automation profile should be manual
And r2plc-the mock UoW should have received a plan update call
Scenario: resume_plan persists and auto-progresses via _commit_plan
Given r2plc-a fresh plan lifecycle service with mock UoW
Given r2plc-a plan in STRATEGIZE phase
When r2plc-I resume the plan with profile "auto"
Then r2plc-the plan automation profile should be "auto"
# ============================================================
# Originally from: plan_model.feature
# Feature: Plan Domain Model
# ============================================================
Scenario: Parse simple name defaults to local namespace
When I parse the namespaced name "my-action"
Then the parsed namespace should be "local"
And the parsed item name should be "my-action"
And the parsed server should be empty
Scenario: Parse name with explicit local namespace
When I parse the namespaced name "local/my-action"
Then the parsed namespace should be "local"
And the parsed item name should be "my-action"
Scenario: Parse name with organization namespace
When I parse the namespaced name "myorg/my-action"
Then the parsed namespace should be "myorg"
And the parsed item name should be "my-action"
Scenario: Parse name with server qualifier
When I parse the namespaced name "prod:myorg/my-action"
Then the parsed server should be "prod"
And the parsed namespace should be "myorg"
And the parsed item name should be "my-action"
Scenario: NamespacedName string representation
Given I have a namespaced name with server "prod" namespace "myorg" and name "my-action"
Then the namespaced string representation should be "prod:myorg/my-action"
Scenario: NamespacedName without server
Given I have a namespaced name with namespace "local" and name "test-plan"
Then the namespaced string representation should be "local/test-plan"
Scenario: Invalid namespace with special characters fails
When I try to create a namespaced name with namespace "my@org" and name "test"
Then a validation error should be raised
Scenario: Empty namespace defaults to local
Given I create a namespaced name with an empty namespace and name "test-plan"
Then the parsed namespace should be "local"
# PlanPhase Tests
Scenario: Plan phases are in correct order
Then the plan phases should be in order "action, strategize, execute, apply"
Scenario: STRATEGIZE phase is the starting phase
Given I create a new plan
Then the plan phase should be "strategize"
# PlanState Tests
Scenario: New plan starts in STRATEGIZE with QUEUED processing state
Given I create a PlanModel in strategize phase
Then the plan phase should be "strategize"
And the plan processing state should be "queued"
Scenario: Strategize phase uses ProcessingState
Given I create a PlanModel in strategize phase
Then the plan processing state should be "queued"
Scenario: Plan in strategize phase defaults to QUEUED processing state
Given I create a PlanModel in strategize phase
Then the plan processing state should be "queued"
And the plan state should be "queued"
Scenario: Strategize phase defaults processing_state to QUEUED
Given I create a PlanModel in strategize phase
Then the plan processing state should be "queued"
# Plan Identity Tests
Scenario: Plan requires valid ULID
When I try to create a plan identity with invalid ULID "not-a-ulid"
Then a validation error should be raised
Scenario: Plan identity with valid ULID succeeds
When I create a plan identity with ULID "01ARZ3NDEKTSV4RRFFQ69G5FAV"
Then the plan identity should be valid
Scenario: Plan identity supports parent and root plan IDs
When I create a plan identity with parent "01ARZ3NDEKTSV4RRFFQ69G5FAV" and root "01ARZ3NDEKTSV4RRFFQ69G5FAW"
Then the parent plan ID should be "01ARZ3NDEKTSV4RRFFQ69G5FAV"
And the root plan ID should be "01ARZ3NDEKTSV4RRFFQ69G5FAW"
# Plan Lifecycle Tests
Scenario: New plan starts in STRATEGIZE phase with QUEUED state
Given I create a new plan with description "Test plan"
Then the plan phase should be "strategize"
And the plan processing state should be "queued"
And the plan should not be terminal
Scenario: Plan in STRATEGIZE with QUEUED cannot transition
Given I create a PlanModel in strategize phase
Then the plan cannot transition to next phase
Scenario: New plan in STRATEGIZE with QUEUED cannot transition
Given I create a PlanModel in strategize phase
Then the plan cannot transition to next phase
Scenario: Processing complete allows transition
Given I create a plan in execute phase with complete processing state
Then the plan can transition to next phase
Scenario: Get next phase from STRATEGIZE is EXECUTE
Given I create a new plan
Then the next phase should be "execute"
Scenario: Get next phase from APPLY is None (terminal phase)
Given I create a plan in apply phase as terminal
Then the next phase should be empty
Scenario: Unknown phase returns no next phase
Given I create a plan with an unknown phase value
Then the next phase should be empty
# Phase Transition Validation Tests
Scenario: Valid transition from STRATEGIZE to EXECUTE
Then transition from "strategize" to "execute" should be valid
Scenario: Valid transition from EXECUTE to APPLY
Then transition from "execute" to "apply" should be valid
Scenario: Valid transition from APPLY to STRATEGIZE (revert via constrained)
Then transition from "apply" to "strategize" should be valid
Scenario: Invalid transition from STRATEGIZE to APPLY
Then transition from "strategize" to "apply" should be invalid
Scenario: Valid transition from ACTION to STRATEGIZE
Then transition from "action" to "strategize" should be valid
# Error State Tests
Scenario: Plan in errored state is_errored returns True
Given I create a PlanModel in strategize phase with errored state
Then the plan should be errored
Scenario: Plan in processing state is_errored returns False
Given I create a PlanModel in strategize phase with processing state
Then the plan should not be errored
Scenario: Cancelled plan is terminal
Given I create a PlanModel in strategize phase with cancelled state
Then the plan should be terminal
# Model Validation Tests
Scenario: Plan requires description
When I try to create a plan without description
Then a validation error should be raised
Scenario: Plan description cannot be empty
When I try to create a plan with empty description
Then a validation error should be raised
Scenario: Invalid phase value raises validation error
When I try to create a plan with invalid phase value
Then a validation error should be raised
Scenario: Apply phase cannot transition to next phase
Given I create a plan in apply phase as terminal
Then the plan cannot transition to next phase
# ============================================================
# Originally from: plan_model_coverage.feature
# Feature: Plan Model Coverage — New Fields and Helpers
# ============================================================
Scenario: Invalid name with special characters raises validation error
When I try to create a namespaced name with namespace "local" and name "test@action"
Then a validation error should be raised
# ProjectLink.validate_alias classmethod
Scenario: ProjectLink.validate_alias accepts a valid alias
When I validate the project link alias "my-service"
Then the alias should be valid
Scenario: ProjectLink.validate_alias rejects an alias starting with a digit
When I validate the project link alias "1bad-alias"
Then the alias should be invalid
Scenario: ProjectLink.validate_alias rejects an alias with uppercase
When I validate the project link alias "BadAlias"
Then the alias should be invalid
Scenario: ProjectLink.validate_alias rejects an empty alias
When I validate an empty project link alias
Then the alias should be invalid
# ProjectLink field validator — invalid alias on construction
Scenario: Creating a ProjectLink with an invalid alias raises validation error
When I try to create a project link with alias "INVALID!"
Then a validation error should be raised
Scenario: Creating a ProjectLink with a valid alias succeeds
When I create a project link with alias "api-svc"
Then the project link alias should be "api-svc"
# Plan — APPLY phase with APPLIED processing_state is terminal
Scenario: APPLY phase with APPLIED processing state is terminal
When I create a plan in apply phase with applied processing state
Then the plan processing state should be "applied"
And the plan should be terminal
# Plan — duplicate project link alias uniqueness
Scenario: Duplicate project link aliases raise validation error
When I try to create a plan with duplicate project link aliases
Then a validation error should be raised
Scenario: Distinct project link aliases are accepted
When I create a plan with distinct project link aliases
Then the plan should have 2 project links
# Plan.as_cli_dict — base fields
Scenario: as_cli_dict includes base identification fields
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should contain key "plan_id"
And the CLI dict should contain key "name"
And the CLI dict should contain key "action"
And the CLI dict should contain key "phase"
And the CLI dict should contain key "state"
And the CLI dict should contain key "description"
And the CLI dict should contain key "created_at"
And the CLI dict should contain key "updated_at"
# Plan.as_cli_dict — definition_of_done
Scenario: as_cli_dict includes definition_of_done when set
Given I create a plan with definition of done "all tests pass"
When I call as_cli_dict
Then the CLI dict key "definition_of_done" should be "all tests pass"
Scenario: as_cli_dict omits definition_of_done when not set
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "definition_of_done"
# Plan.as_cli_dict — automation profile provenance
Scenario: as_cli_dict includes automation profile with provenance
Given I create a plan with automation profile "trusted" from "action"
When I call as_cli_dict
Then the CLI dict key "automation_profile" should be "trusted"
And the CLI dict key "automation_profile_source" should be "action"
Scenario: as_cli_dict omits automation profile when not set
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "automation_profile"
# Plan.as_cli_dict — project links
Scenario: as_cli_dict renders project links with alias and read_only
Given I create a plan with project links
When I call as_cli_dict
Then the CLI dict key "projects" should be a list of length 2
Scenario: as_cli_dict omits projects when none are linked
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "projects"
# Plan.as_cli_dict — invariants
Scenario: as_cli_dict renders invariants with source tags
Given I create a plan with invariants
When I call as_cli_dict
Then the CLI dict key "invariants" should be a list of length 2
Scenario: as_cli_dict omits invariants when empty
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "invariants"
# Plan.as_cli_dict — arguments
Scenario: as_cli_dict renders arguments in stable order
Given I create a plan with arguments
When I call as_cli_dict
Then the CLI dict should contain key "arguments"
And the CLI dict arguments should preserve order
Scenario: as_cli_dict omits arguments when empty
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "arguments"
# Plan.as_cli_dict — actor fields
Scenario: as_cli_dict includes strategy_actor when set
Given I create a plan with strategy actor "local/planner"
When I call as_cli_dict
Then the CLI dict key "strategy_actor" should be "local/planner"
Scenario: as_cli_dict includes execution_actor when set
Given I create a plan with execution actor "local/coder"
When I call as_cli_dict
Then the CLI dict key "execution_actor" should be "local/coder"
Scenario: as_cli_dict omits actor fields when not set
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "strategy_actor"
And the CLI dict should not contain key "execution_actor"
# Plan.as_cli_dict — error message
Scenario: as_cli_dict includes error when present
Given I create a plan with error message "sandbox timeout"
When I call as_cli_dict
Then the CLI dict key "error" should be "sandbox timeout"
Scenario: as_cli_dict omits error when not present
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "error"
# Plan.as_cli_dict — parent plan and subplan count
Scenario: as_cli_dict includes parent_plan_id for subplans
Given I create a subplan for CLI output
When I call as_cli_dict
Then the CLI dict should contain key "parent_plan_id"
Scenario: as_cli_dict includes subplan_count when subplans exist
Given I create a plan with subplan statuses
When I call as_cli_dict
Then the CLI dict key "subplan_count" should be 1
Scenario: as_cli_dict omits parent and subplan fields for root plan
Given I create a plan for CLI output
When I call as_cli_dict
Then the CLI dict should not contain key "parent_plan_id"
And the CLI dict should not contain key "subplan_count"
# ---- is_subplan / is_root_plan / depth properties ----
Scenario: Root plan is not a subplan and has depth zero
Given I create a plan for CLI output
Then the plan should not be a subplan
And the plan should be a root plan
And the plan depth should be 0
Scenario: Child plan is a subplan and has depth minus one
Given I create a child plan with a parent
Then the plan should be a subplan
And the plan should not be a root plan
And the plan depth should be -1
# ---- SubplanFailureHandler.should_stop_others ----
Scenario: Failure handler stops others when fail_fast is true
Given a subplan config with fail_fast enabled and sequential mode
And a failed subplan status
When I check should_stop_others
Then should_stop_others should be true
Scenario: Failure handler stops others in sequential mode
Given a subplan config with fail_fast disabled and sequential mode
And a failed subplan status
When I check should_stop_others
Then should_stop_others should be true
Scenario: Failure handler does not stop others in parallel mode without fail_fast
Given a subplan config with fail_fast disabled and parallel mode
And a failed subplan status
When I check should_stop_others
Then should_stop_others should be false
# ---- SubplanFailureHandler.should_retry ----
Scenario: Failure handler does not retry when retry_failed is false
Given a subplan config with retry disabled
And a failed subplan status with error "TimeoutError"
When I check should_retry
Then should_retry should be false
Scenario: Failure handler does not retry when max retries exceeded
Given a subplan config with max retries 1
And a failed subplan status on attempt 2 with error "TimeoutError"
When I check should_retry
Then should_retry should be false
Scenario: Failure handler retries retriable failure within limit
Given a subplan config with retry enabled and max retries 2
And a failed subplan status on attempt 1 with error "TimeoutError"
When I check should_retry
Then should_retry should be true
Scenario: Failure handler does not retry non-retriable error
Given a subplan config with retry enabled and max retries 2
And a failed subplan status on attempt 1 with error "ConfigurationError"
When I check should_retry
Then should_retry should be false
Scenario: Failure handler does not retry unknown error
Given a subplan config with retry enabled and max retries 2
And a failed subplan status on attempt 1 with error "SomeUnknownError"
When I check should_retry
Then should_retry should be false
# ============================================================
# Originally from: plan_model_uncovered_lines.feature
# Feature: Plan Hierarchy and Subplan Failure Handling
# ============================================================
@subplan_hierarchy
Scenario: A standalone plan is not considered a subplan
Given an uncovered-lines plan that was created independently
Then the uncovered-lines plan should not be recognized as a subplan
@subplan_hierarchy
Scenario: A plan spawned by another plan is a subplan
Given an uncovered-lines plan that was spawned by another plan
Then the uncovered-lines plan should be recognized as a subplan
@subplan_hierarchy
Scenario: A plan with no designated root is considered the root
Given an uncovered-lines plan with no designated root
Then the uncovered-lines plan should be recognized as a root plan
@subplan_hierarchy
Scenario: A plan whose root is itself is considered the root
Given an uncovered-lines plan whose designated root is itself
Then the uncovered-lines plan should be recognized as a root plan
@subplan_hierarchy
Scenario: A plan whose root is a different plan is not the root
Given an uncovered-lines plan whose designated root is a different plan
Then the uncovered-lines plan should not be recognized as a root plan
@subplan_hierarchy
Scenario: A root plan reports a depth of zero
Given an uncovered-lines plan with no designated root
Then the uncovered-lines plan hierarchy depth should be 0
@subplan_hierarchy
Scenario: A non-root plan reports a placeholder depth
Given an uncovered-lines plan whose designated root is a different plan
Then the uncovered-lines plan hierarchy depth should be -1
@subplan_hierarchy
Scenario: A plan with no child work has no subplans
Given an uncovered-lines plan that has no child work tracked
Then the uncovered-lines plan should report having no subplans
@subplan_hierarchy
Scenario: A plan with tracked child work has subplans
Given an uncovered-lines plan that has tracked child work
Then the uncovered-lines plan should report having subplans
@failure_handler
Scenario: The failure handler halts remaining work when fail-fast is enabled
Given an uncovered-lines subplan configuration with fail-fast enabled and parallel work
And an uncovered-lines subplan that has failed
When the uncovered-lines failure handler evaluates whether to halt remaining work
Then the uncovered-lines remaining work should be halted
@failure_handler
Scenario: The failure handler halts remaining work for sequential execution
Given an uncovered-lines subplan configuration with fail-fast disabled and sequential work
And an uncovered-lines subplan that has failed
When the uncovered-lines failure handler evaluates whether to halt remaining work
Then the uncovered-lines remaining work should be halted
@failure_handler
Scenario: The failure handler allows remaining work for parallel execution without fail-fast
Given an uncovered-lines subplan configuration with fail-fast disabled and parallel work
And an uncovered-lines subplan that has failed
When the uncovered-lines failure handler evaluates whether to halt remaining work
Then the uncovered-lines remaining work should continue
@failure_handler
Scenario: The failure handler allows remaining work for dependency-ordered execution without fail-fast
Given an uncovered-lines subplan configuration with fail-fast disabled and dependency-ordered work
And an uncovered-lines subplan that has failed
When the uncovered-lines failure handler evaluates whether to halt remaining work
Then the uncovered-lines remaining work should continue
@failure_handler
Scenario: The failure handler does not retry when retries are disabled
Given an uncovered-lines subplan configuration with retries disabled
And an uncovered-lines subplan that failed with error "ValidationError occurred"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: The failure handler does not retry when all attempts are exhausted
Given an uncovered-lines subplan configuration allowing up to 2 retries
And an uncovered-lines subplan on attempt 3 that failed with error "TimeoutError"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: A configuration error is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "ConfigurationError: bad config"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: An authentication error is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "AuthenticationError: invalid token"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: A missing resource error is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "MissingResourceError: file not found"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: A circular dependency error is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "CircularDependencyError: cycle detected"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: A validation error is eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "ValidationError: schema mismatch"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should be retried
@failure_handler
Scenario: A timeout error is eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "TimeoutError: deadline exceeded"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should be retried
@failure_handler
Scenario: A temporary resource error is eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "TemporaryResourceError: service unavailable"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should be retried
@failure_handler
Scenario: A merge conflict error is eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "MergeConflictError: conflicting changes"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should be retried
@failure_handler
Scenario: An unrecognized error type is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with error "SomeUnknownError: unexpected"
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried
@failure_handler
Scenario: A failure with no error message is not eligible for retry
Given an uncovered-lines subplan configuration allowing up to 3 retries
And an uncovered-lines subplan on attempt 1 that failed with no error message
When the uncovered-lines failure handler evaluates whether to retry the failed work
Then the uncovered-lines failed work should not be retried