Feature: Plan lifecycle repository and service coverage
  Additional scenarios to cover untested paths in LifecyclePlanRepository,
  ActionRepository, PlanLifecycleService, and UnitOfWork.

  Background:
    Given a coverage test service backed by SQLite

  # ── LifecyclePlanRepository direct tests ──

  Scenario: Get plan by namespaced name
    Given a coverage plan exists via the service
    When I retrieve the plan by its namespaced name from the repository
    Then the plan retrieved by name should match the original

  Scenario: Get plan by name returns None for unknown
    When I retrieve a plan by name "local/nonexistent-plan-xyz" from the repository
    Then the plan-by-name result should be None

  Scenario: Update plan persists child project links, arguments, and invariants
    Given a coverage plan with project links and invariants exists
    When I update the plan description and phase through the repository
    Then the updated plan should have the new description in the DB
    And the updated plan should retain project links
    And the updated plan should retain arguments
    And the updated plan should retain invariants

  Scenario: Delete plan removes it from the database
    Given a coverage plan exists via the service
    When I delete the plan from the repository
    Then the plan should no longer be retrievable from the DB

  Scenario: Delete returns false for non-existent plan
    When I delete a non-existent plan "01NONEXISTENT000000000000" from the repository
    Then the plan delete result should be false

  Scenario: List plans with phase filter
    Given a coverage plan exists via the service
    When I list plans filtered by phase "strategize"
    Then the listed plans should include the coverage plan

  Scenario: List plans with namespace filter
    Given a coverage plan exists via the service
    When I list plans filtered by namespace "local"
    Then the listed plans should include the coverage plan

  Scenario: List plans with action_name filter
    Given a coverage plan exists via the service
    When plcov I list plans filtered by action_name
    Then the listed plans should include the coverage plan

  Scenario: Count plans with no filters
    Given a coverage plan exists via the service
    When I count plans with no filters
    Then the count should be at least 1

  Scenario: Count plans with phase filter
    Given a coverage plan exists via the service
    When I count plans filtered by phase "strategize"
    Then the filtered count should be at least 1

  Scenario: Count plans with processing_state filter
    Given a coverage plan exists via the service
    When I count plans filtered by processing_state "queued"
    Then the filtered count should be at least 1

  Scenario: Create duplicate plan raises DuplicatePlanError
    Given a coverage plan exists via the service
    When I try to create a duplicate plan with the same ID
    Then a DuplicatePlanError should be raised

  Scenario: Update non-existent plan raises PlanNotFoundError
    When I try to update a plan that does not exist in the DB
    Then a PlanNotFoundError should be raised

  # ── ActionRepository update path ──

  Scenario: Archive action triggers action update in repository
    Given a coverage action "local/cov-archive" exists
    When I archive the coverage action "local/cov-archive"
    Then the action "local/cov-archive" should be archived in the DB

  Scenario: Action update persists inputs_schema and arguments with defaults
    Given a coverage action with inputs_schema and arguments exists
    When I update the coverage action with new description
    Then the action should retain its inputs_schema in the DB
    And the action should retain its arguments with defaults in the DB
    And the action should retain its invariants in the DB

  # ── PlanLifecycleService persistence fallback ──

  Scenario: Get plan falls back to persistence layer when not in memory
    Given a coverage plan exists via the service
    When I clear the in-memory plan cache
    And I retrieve the plan by ID through the service
    Then the plan should be loaded from the persistence layer

  # ── PlanLifecycleService constrain_apply ──

  Scenario: Constrain apply marks plan as constrained
    Given a coverage plan in apply-queued state
    When I constrain the apply with reason "Resource limit exceeded"
    Then the coverage plan processing state should be "constrained"
    And the coverage plan error message should be "Resource limit exceeded"

  # ── PlanLifecycleService auto_progress no-op ──

  Scenario: Auto progress returns plan unchanged when not auto-progressable
    Given a coverage plan exists via the service
    When I call auto_progress on the plan
    Then the plan should be returned unchanged

  # ── UnitOfWork lifecycle_plans lazy property ──

  Scenario: UnitOfWork context exposes lifecycle_plans repository
    When I open a UoW transaction and access lifecycle_plans
    Then the lifecycle_plans property should return a LifecyclePlanRepository

  # ── UnitOfWork add, flush, refresh ──

  Scenario: UnitOfWork context supports add and flush
    When I use UoW context to add a raw model entity and flush
    Then the entity should be queryable in the same session
