Feature: Consolidated Correction
  Combined scenarios from: correction_flows, correction_model, correction_service_coverage_r2, correction_service_new_coverage

  # ============================================================
  # Originally from: correction_flows.feature
  # Feature: Correction flows — revert and append
  # ============================================================

  Scenario: Simple revert invalidates target decision
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree where "D1" has no children
    When I execute the revert correction
    Then the correction flow result status should be "applied"
    And the reverted decisions should contain "D1"


  Scenario: Revert deep subtree invalidates all descendants
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a multi-parent decision tree with "D1" children "D2,D3" and "D2" children "D4,D5"
    When I execute the revert correction
    Then the reverted decisions should contain "D1"
    And the reverted decisions should contain "D2"
    And the reverted decisions should contain "D3"
    And the reverted decisions should contain "D4"
    And the reverted decisions should contain "D5"


  Scenario: Revert archives artifacts for each affected decision
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a simple decision tree where "D1" has children "D2"
    When I execute the revert correction
    Then the archived artifacts should include "D1.artifact"
    And the archived artifacts should include "D2.artifact"


  Scenario: Revert correction transitions through expected statuses
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    Then the correction flow status should be "pending"
    When I execute the revert correction with a decision tree where "D1" has no children
    Then the correction flow status should be "applied"

    # ───────────────────────────────────────────────────────────
    # Append scenarios
    # ───────────────────────────────────────────────────────────


  Scenario: Simple append spawns child plan
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode
    When I execute the append correction
    Then the correction flow result status should be "applied"
    And the result should have a spawned child plan id


  Scenario: Append with guidance preserves guidance on request
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode with guidance "Fix auth module"
    When I execute the append correction
    Then the correction flow guidance should be "Fix auth module"


  Scenario: Append creates new decision in result
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode
    When I execute the append correction
    Then the result new decisions should not be empty

    # ───────────────────────────────────────────────────────────
    # Impact analysis
    # ───────────────────────────────────────────────────────────


  Scenario: Impact analysis with BFS subtree traversal
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a multi-parent decision tree with "D1" children "D2,D3" and "D3" children "D6"
    When I analyze the impact
    Then the affected decisions should be "D1,D2,D3,D6"


  Scenario: Impact analysis risk level low for small subtree
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a simple decision tree where "D1" has children "D2"
    When I analyze the impact
    Then the risk level should be "low"


  Scenario: Impact analysis risk level medium for moderate subtree
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree with 7 nodes rooted at "D1"
    When I analyze the impact
    Then the risk level should be "medium"


  Scenario: Impact analysis risk level high for large subtree
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree with 15 nodes rooted at "D1"
    When I analyze the impact
    Then the risk level should be "high"


  Scenario: Impact analysis on leaf node returns only the target
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "LEAF" in revert mode
    And an empty decision tree
    When I analyze the impact
    Then the affected decisions should be "LEAF"

    # ───────────────────────────────────────────────────────────
    # Dry-run
    # ───────────────────────────────────────────────────────────


  Scenario: Dry-run report generation for revert
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a simple decision tree where "D1" has children "D2,D3"
    When I generate a dry-run report
    Then the report mode should be "revert"
    And the report decisions to invalidate should contain "D1"
    And the report estimated recompute time should be greater than 0


  Scenario: Dry-run report generates warnings for high risk
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree with 15 nodes rooted at "D1"
    When I generate a dry-run report
    Then the report warnings should contain "High risk"


  Scenario: Dry-run report generates warnings for medium risk
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree with 7 nodes rooted at "D1"
    When I generate a dry-run report
    Then the report warnings should contain "Medium risk"


  Scenario: Dry-run report for append has no decisions to invalidate
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode
    When I generate a dry-run report
    Then the report decisions to invalidate should be empty

    # ───────────────────────────────────────────────────────────
    # Error handling
    # ───────────────────────────────────────────────────────────


  Scenario: Get correction with invalid id raises not found
    Given a correction flow service
    When I try to get correction flow "nonexistent-id"
    Then a correction flow resource not found error should be raised


  Scenario: Execute already applied correction raises validation error
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And I execute the revert correction with a decision tree where "D1" has no children
    When I try to execute the revert correction again
    Then a validation error should be raised for status


  Scenario: Execute already cancelled correction raises validation error
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And I cancel the correction flow
    When I try to execute the revert correction again
    Then a validation error should be raised for status


  Scenario: Cancel already applied correction raises validation error
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And I execute the revert correction with a decision tree where "D1" has no children
    When I try to cancel the correction flow
    Then a validation error should be raised for status

    # ───────────────────────────────────────────────────────────
    # Status transitions
    # ───────────────────────────────────────────────────────────


  Scenario: Correction status transitions from pending to applied on revert
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    When I execute the revert correction with a decision tree where "D1" has no children
    Then the correction flow status should be "applied"


  Scenario: Correction status transitions from pending to cancelled
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    When I cancel the correction flow
    Then the correction flow status should be "cancelled"

    # ───────────────────────────────────────────────────────────
    # Multi-correction & listing
    # ───────────────────────────────────────────────────────────


  Scenario: Multiple corrections on same plan are listed correctly
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a correction request for plan "P1" targeting decision "D2" in append mode
    When I list correction flows for plan "P1"
    Then the correction list should have 2 items


  Scenario: List corrections filters by plan id
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a correction request for plan "P2" targeting decision "D2" in append mode
    When I list correction flows for plan "P1"
    Then the correction list should have 1 items

    # ───────────────────────────────────────────────────────────
    # Cancellation
    # ───────────────────────────────────────────────────────────


  Scenario: Cancel pending correction succeeds
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    When I cancel the correction flow
    Then the correction flow status should be "cancelled"

    # ───────────────────────────────────────────────────────────
    # Attempt tracking
    # ───────────────────────────────────────────────────────────


  Scenario: Execution records an attempt
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    When I execute the revert correction with a decision tree where "D1" has no children
    Then the attempt list should have 1 entries
    And the first attempt should be successful


  Scenario: Append execution records an attempt
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode
    When I execute the append correction
    Then the attempt list should have 1 entries

    # ───────────────────────────────────────────────────────────
    # Model validation
    # ───────────────────────────────────────────────────────────


  Scenario: CorrectionRequest rejects empty plan_id
    Given a correction flow service
    When I try to create a correction with empty plan_id
    Then a validation error should be raised for empty field


  Scenario: CorrectionRequest rejects empty target_decision_id
    Given a correction flow service
    When I try to create a correction with empty target_decision_id
    Then a validation error should be raised for empty field


  Scenario: CorrectionImpact rejects invalid risk level
    When I try to create a correction impact with risk level "critical"
    Then a correction flow pydantic validation error should be raised


  Scenario: CorrectionDryRunReport contains all expected fields
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a simple decision tree where "D1" has children "D2"
    When I generate a dry-run report
    Then the report should have a correction_id
    And the report should have an impact object
    And the report should have a warnings list


  Scenario: Execute correction dispatches to revert
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in revert mode
    And a decision tree where "D1" has no children
    When I execute correction via dispatch
    Then the correction flow result status should be "applied"
    And the reverted decisions should contain "D1"


  Scenario: Execute correction dispatches to append
    Given a correction flow service
    And a correction request for plan "P1" targeting decision "D1" in append mode
    When I execute correction via dispatch
    Then the correction flow result status should be "applied"
    And the result should have a spawned child plan id


  # ============================================================
  # Originally from: correction_model.feature
  # Feature: Correction Model
  # ============================================================

  Scenario: Create correction request in revert mode
    Given a correction service
    When I request a correction for plan "plan-1" decision "DEC-001" in revert mode with guidance "Use FastAPI instead"
    Then the correction should be created
    And the correction mode should be "revert"
    And the correction status should be "pending"
    And the correction plan_id should be "plan-1"
    And the correction target_decision_id should be "DEC-001"
    And the correction guidance should be "Use FastAPI instead"


  Scenario: Create correction request in append mode
    Given a correction service
    When I request a correction for plan "plan-2" decision "DEC-002" in append mode with guidance "Add caching layer"
    Then the correction should be created
    And the correction mode should be "append"
    And the correction status should be "pending"


  Scenario: Create dry-run correction request
    Given a correction service
    When I request a dry-run correction for plan "plan-1" decision "DEC-001" in revert mode with guidance "Use SQLite"
    Then the correction should be created
    And the correction dry_run should be true

    # ── Impact Analysis ──────────────────────────────────────────


  Scenario: Dry-run returns impact analysis
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Change framework"
    When I analyze the correction impact
    Then the impact should list affected decisions
    And the impact risk level should be "low"
    And the correction status should be "analyzing"

    # ── Cancellation ─────────────────────────────────────────────


  Scenario: Cancel a pending correction
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Change approach"
    When I cancel the correction
    Then the correction status should be "cancelled"


  Scenario: Cancel an already-cancelled correction fails
    Given a correction service
    And a cancelled correction for plan "plan-1" decision "DEC-001"
    When I try to cancel the correction
    Then a validation error should be raised with message containing "cancelled"


  Scenario: Cancel an applied correction fails
    Given a correction service
    And an applied correction for plan "plan-1" decision "DEC-001"
    When I try to cancel the correction
    Then a validation error should be raised with message containing "applied"

    # ── Listing ──────────────────────────────────────────────────


  Scenario: List corrections by plan
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Fix endpoint"
    And a correction request for plan "plan-1" decision "DEC-002" in append mode with guidance "Add logging"
    And a correction request for plan "plan-2" decision "DEC-003" in revert mode with guidance "Change DB"
    When I list corrections for plan "plan-1"
    Then I should get 2 corrections
    When I list corrections for plan "plan-2"
    Then I should get 1 corrections
    When I list all corrections
    Then I should get 3 corrections

    # ── Retrieval ────────────────────────────────────────────────


  Scenario: Get correction by ID
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Test retrieval"
    When I get the correction by its ID
    Then the correction should be found
    And the correction guidance should be "Test retrieval"


  Scenario: Get non-existent correction raises error
    Given a correction service
    When I try to get correction "nonexistent-id"
    Then a resource not found error should be raised

    # ── Validation ───────────────────────────────────────────────


  Scenario: Invalid decision ID rejection
    Given a correction service
    When I try to request a correction with empty decision ID
    Then a validation error should be raised with message containing "decision_id"


  Scenario: Invalid plan ID rejection
    Given a correction service
    When I try to request a correction with empty plan ID
    Then a validation error should be raised with message containing "plan_id"


  Scenario: Empty guidance is accepted
    Given a correction service
    When I try to request a correction with empty guidance
    Then the correction should be created


  Scenario: Whitespace-only guidance is accepted
    Given a correction service
    When I try to request a correction with whitespace-only guidance
    Then the correction should be created

    # ── Status Transitions ───────────────────────────────────────


  Scenario: Correction status transitions through execution
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Execute me"
    Then the correction status should be "pending"
    When I execute the correction
    Then the correction status should be "applied"


  Scenario: Execute already-applied correction fails
    Given a correction service
    And an applied correction for plan "plan-1" decision "DEC-001"
    When I try to execute the correction
    Then a validation error should be raised with message containing "applied"


  Scenario: Execute already-cancelled correction fails
    Given a correction service
    And a cancelled correction for plan "plan-1" decision "DEC-001"
    When I try to execute the correction
    Then a validation error should be raised with message containing "cancelled"

    # ── Execution Result ─────────────────────────────────────────


  Scenario: Revert execution produces reverted decisions
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Revert this"
    When I execute the correction
    Then the result should have reverted decisions
    And the result status should be "applied"


  Scenario: Append execution produces no reverted decisions
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in append mode with guidance "Append this"
    When I execute the correction
    Then the result should have no reverted decisions
    And the result status should be "applied"

    # ── Attempts ─────────────────────────────────────────────────


  Scenario: Execution records an attempt
    Given a correction service
    And a correction request for plan "plan-1" decision "DEC-001" in revert mode with guidance "Track attempt"
    When I execute the correction
    Then there should be 1 attempt recorded
    And the attempt should be successful

    # ── Model Validation ─────────────────────────────────────────


  Scenario: CorrectionRequest validates non-empty plan_id
    When I try to create a CorrectionRequest with empty plan_id
    Then a pydantic validation error should be raised


  Scenario: CorrectionRequest validates non-empty target_decision_id
    When I try to create a CorrectionRequest with empty target_decision_id
    Then a pydantic validation error should be raised


  Scenario: CorrectionRequest accepts empty guidance
    When I try to create a CorrectionRequest with empty guidance
    Then the correction should be created


  Scenario: CorrectionImpact validates risk_level
    When I try to create a CorrectionImpact with invalid risk_level "extreme"
    Then a pydantic validation error should be raised


  Scenario: CorrectionImpact accepts valid risk levels
    When I create a CorrectionImpact with risk_level "low"
    Then the impact should be created
    When I create a CorrectionImpact with risk_level "medium"
    Then the impact should be created
    When I create a CorrectionImpact with risk_level "high"
    Then the impact should be created

    # ── Enum Tests ───────────────────────────────────────────────


  Scenario: CorrectionMode enum values
    Then CorrectionMode.REVERT should equal "revert"
    And CorrectionMode.APPEND should equal "append"


  Scenario: CorrectionStatus enum values
    Then CorrectionStatus.PENDING should equal "pending"
    And CorrectionStatus.ANALYZING should equal "analyzing"
    And CorrectionStatus.EXECUTING should equal "executing"
    And CorrectionStatus.APPLIED should equal "applied"
    And CorrectionStatus.FAILED should equal "failed"
    And CorrectionStatus.CANCELLED should equal "cancelled"

    # ── CorrectionResult Model ──────────────────────────────────


  Scenario: CorrectionResult with defaults
    When I create a CorrectionResult with correction_id "corr-1" and status "applied"
    Then the result should have empty new_decisions
    And the result should have empty reverted_decisions
    And the result error_message should be none

    # ── CorrectionAttempt Model ─────────────────────────────────


  Scenario: CorrectionAttempt default values
    When I create a CorrectionAttempt for correction "corr-1"
    Then the attempt success should be false
    And the attempt completed_at should be none
    And the attempt details should be empty


  # ============================================================
  # Originally from: correction_service_coverage_r2.feature
  # Feature: CorrectionService exception-handling coverage (round 2)
  # ============================================================

  Scenario: execute_revert catches internal error and returns FAILED result
    Given r2corr-a fresh correction service
    Given r2corr-a stored revert correction for plan "P1" targeting "D1"
    And r2corr-analyze_impact is patched to raise RuntimeError "boom in analyze"
    When r2corr-I execute revert on the stored correction
    Then r2corr-the revert result status should be "failed"
    And r2corr-the revert result error_message should contain "boom in analyze"
    And r2corr-the stored correction status should be "failed"
    And r2corr-the first attempt should have success false
    And r2corr-the first attempt details should contain error key
    And r2corr-the first attempt details error should contain "boom in analyze"
    And r2corr-the first attempt completed_at should be set
    And r2corr-the result should be stored in the service results dict


  Scenario: execute_revert exception path preserves attempt count
    Given r2corr-a fresh correction service
    Given r2corr-a stored revert correction for plan "P1" targeting "D2"
    And r2corr-analyze_impact is patched to raise ValueError "bad value"
    When r2corr-I execute revert on the stored correction
    Then r2corr-the attempts for the stored correction should have 1 entry
    And r2corr-the first attempt should have success false


  Scenario: execute_revert exception with TypeError message
    Given r2corr-a fresh correction service
    Given r2corr-a stored revert correction for plan "P1" targeting "D3"
    And r2corr-analyze_impact is patched to raise TypeError "wrong type"
    When r2corr-I execute revert on the stored correction
    Then r2corr-the revert result status should be "failed"
    And r2corr-the revert result error_message should contain "wrong type"
    And r2corr-the stored correction status should be "failed"

    # -------------------------------------------------------------------
    # execute_append – exception path (lines 320-328)
    # -------------------------------------------------------------------


  Scenario: execute_append catches internal error and returns FAILED result
    Given r2corr-a fresh correction service
    Given r2corr-a stored append correction for plan "P1" targeting "A1"
    And r2corr-ULID is patched to raise RuntimeError "ulid broken"
    When r2corr-I execute append on the stored correction
    Then r2corr-the append result status should be "failed"
    And r2corr-the append result error_message should contain "ulid broken"
    And r2corr-the stored correction status should be "failed"
    And r2corr-the first attempt should have success false
    And r2corr-the first attempt details should contain error key
    And r2corr-the first attempt details error should contain "ulid broken"
    And r2corr-the first attempt completed_at should be set
    And r2corr-the append result should be stored in the service results dict


  Scenario: execute_append exception path preserves attempt count
    Given r2corr-a fresh correction service
    Given r2corr-a stored append correction for plan "P1" targeting "A2"
    And r2corr-ULID is patched to raise ValueError "ulid value error"
    When r2corr-I execute append on the stored correction
    Then r2corr-the attempts for the stored correction should have 1 entry
    And r2corr-the first attempt should have success false


  Scenario: execute_append exception with OSError message
    Given r2corr-a fresh correction service
    Given r2corr-a stored append correction for plan "P1" targeting "A3"
    And r2corr-ULID is patched to raise OSError "system failure"
    When r2corr-I execute append on the stored correction
    Then r2corr-the append result status should be "failed"
    And r2corr-the append result error_message should contain "system failure"
    And r2corr-the stored correction status should be "failed"

    # -------------------------------------------------------------------
    # execute_correction dispatch into exception paths
    # -------------------------------------------------------------------


  Scenario: dispatch to revert hits exception path when analyze_impact fails
    Given r2corr-a fresh correction service
    Given r2corr-a stored revert correction for plan "P1" targeting "DR1"
    And r2corr-analyze_impact is patched to raise RuntimeError "dispatch revert boom"
    When r2corr-I dispatch execute correction on the stored correction
    Then r2corr-the dispatch result status should be "failed"
    And r2corr-the dispatch result error_message should contain "dispatch revert boom"


  Scenario: dispatch to append hits exception path when ULID fails
    Given r2corr-a fresh correction service
    Given r2corr-a stored append correction for plan "P1" targeting "DA1"
    And r2corr-ULID is patched to raise RuntimeError "dispatch append boom"
    When r2corr-I dispatch execute correction on the stored correction
    Then r2corr-the dispatch result status should be "failed"
    And r2corr-the dispatch result error_message should contain "dispatch append boom"


  # ============================================================
  # Originally from: correction_service_new_coverage.feature
  # Feature: CorrectionService comprehensive coverage
  # ============================================================

  Scenario: Create a revert correction with valid parameters
    Given a fresh correction service instance
    When I create a correction for plan "PX1" targeting "DX1" in revert mode
    Then the new correction should be stored in the service
    And the new correction plan_id should equal "PX1"
    And the new correction target_decision_id should equal "DX1"
    And the new correction mode should equal "revert"
    And the new correction status should equal "pending"
    And the new correction dry_run should be false


  Scenario: Create correction with empty plan_id raises ValidationError
    Given a fresh correction service instance
    When I attempt to create a correction with an empty plan_id
    Then a service ValidationError should have been raised


  Scenario: Create correction with empty target_decision_id raises ValidationError
    Given a fresh correction service instance
    When I attempt to create a correction with an empty target_decision_id
    Then a service ValidationError should have been raised


  Scenario: Create correction with guidance and dry_run flag
    Given a fresh correction service instance
    When I create a correction for plan "PX1" targeting "DX1" in append mode with guidance "Refactor auth" and dry_run true
    Then the new correction guidance should equal "Refactor auth"
    And the new correction dry_run should be true
    And the new correction mode should equal "append"

    # ── analyze_impact ───────────────────────────────────────────


  Scenario: Analyze impact with no children yields single node and low risk
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I analyze impact with an empty decision tree
    Then the impact affected decisions should be exactly "DX1"
    And the impact risk level should equal "low"
    And the impact rollback tier should equal "full"
    And the impact estimated cost should equal 1.5
    And the impact artifacts to archive should be exactly "DX1.artifact"
    And the impact affected files should be exactly "DX1.py"


  Scenario: Analyze impact with deep BFS tree traversal
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "A"
    When I analyze impact with tree "A->B,C;B->D,E;C->F"
    Then the impact affected decisions should be exactly "A,B,C,D,E,F"
    And the impact risk level should equal "medium"


  Scenario: Analyze impact with medium risk subtree of 4 nodes
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "R"
    When I analyze impact with tree "R->C1,C2,C3,C4"
    Then the impact risk level should equal "medium"
    And the impact affected decisions count should be 5


  Scenario: Analyze impact with high risk subtree of 11 or more nodes
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "R"
    When I analyze impact with a chain tree of 12 nodes rooted at "R"
    Then the impact risk level should equal "high"
    And the impact affected decisions count should be 12


  Scenario: Analyze impact with non-existent correction raises ResourceNotFoundError
    Given a fresh correction service instance
    When I attempt to analyze impact for correction "bogus-id-999"
    Then a service ResourceNotFoundError should have been raised


  Scenario: Analyze impact sets status to analyzing
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I analyze impact with an empty decision tree
    Then the stored correction status should be "analyzing"


  Scenario: Analyze impact for append mode yields append_only rollback tier
    Given a fresh correction service instance
    And a stored append correction for plan "PX1" targeting "DX1"
    When I analyze impact with an empty decision tree
    Then the impact rollback tier should equal "append_only"

    # ── generate_dry_run_report ──────────────────────────────────


  Scenario: Dry-run report for revert with high risk includes high-risk warning
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "R"
    When I generate a dry-run report with a chain tree of 15 nodes rooted at "R"
    Then the dry-run report mode should equal "revert"
    And the dry-run report warnings should include "High risk"
    And the dry-run report warnings should include "Revert will invalidate"
    And the dry-run report decisions to invalidate should not be empty
    And the dry-run report estimated recompute time should be 30.0


  Scenario: Dry-run report for revert with medium risk includes medium-risk warning
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "R"
    When I generate a dry-run report with a chain tree of 7 nodes rooted at "R"
    Then the dry-run report warnings should include "Medium risk"
    And the dry-run report warnings should include "Revert will invalidate"


  Scenario: Dry-run report for append has empty decisions to invalidate
    Given a fresh correction service instance
    And a stored append correction for plan "PX1" targeting "DX1"
    When I generate a dry-run report with an empty decision tree
    Then the dry-run report decisions to invalidate should be empty
    And the dry-run report mode should equal "append"

    # ── execute_revert ───────────────────────────────────────────


  Scenario: Execute revert with simple tree returns applied result
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I execute revert with tree "DX1->DX2"
    Then the revert result status should equal "applied"
    And the revert result reverted decisions should include "DX1"
    And the revert result reverted decisions should include "DX2"
    And the revert result archived artifacts should include "DX1.artifact"
    And the revert result archived artifacts should include "DX2.artifact"


  Scenario: Execute revert records a successful attempt with completed_at
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I execute revert with an empty decision tree
    Then the service attempts for the correction should have 1 entry
    And the first attempt should have success true
    And the first attempt completed_at should not be none

    # ── execute_append ───────────────────────────────────────────


  Scenario: Execute append creates a child plan and new decision
    Given a fresh correction service instance
    And a stored append correction for plan "PX1" targeting "DX1"
    When I execute append for the stored correction
    Then the append result status should equal "applied"
    And the append result spawned_child_plan_id should not be none
    And the append result new decisions should not be empty

    # ── execute_correction dispatch ──────────────────────────────


  Scenario: Execute correction dispatches to revert for REVERT mode
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I execute correction via the dispatch method with tree "DX1->DX2"
    Then the dispatched result status should equal "applied"
    And the dispatched result reverted decisions should include "DX1"


  Scenario: Execute correction dispatches to append for APPEND mode
    Given a fresh correction service instance
    And a stored append correction for plan "PX1" targeting "DX1"
    When I execute correction via the dispatch method with no tree
    Then the dispatched result status should equal "applied"
    And the dispatched result spawned_child_plan_id should not be none

    # ── get_correction ───────────────────────────────────────────


  Scenario: Get correction with valid id returns the request
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I get the stored correction by its id
    Then the retrieved correction plan_id should equal "PX1"
    And the retrieved correction target_decision_id should equal "DX1"


  Scenario: Get correction with invalid id raises ResourceNotFoundError
    Given a fresh correction service instance
    When I attempt to get correction with id "nonexistent-xyz"
    Then a service ResourceNotFoundError should have been raised

    # ── list_corrections ─────────────────────────────────────────


  Scenario: List corrections without filter returns all corrections
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    And a stored append correction for plan "PX2" targeting "DX2"
    When I list all service corrections without filter
    Then the service corrections list should have 2 items


  Scenario: List corrections with plan_id filter returns only matching
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    And a stored append correction for plan "PX1" targeting "DX2"
    And a stored revert correction for plan "PX2" targeting "DX3"
    When I list service corrections for plan "PX1"
    Then the service corrections list should have 2 items
    When I list service corrections for plan "PX2"
    Then the service corrections list should have 1 items

    # ── list_attempts ────────────────────────────────────────────


  Scenario: List attempts for a valid correction returns attempts
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    And the stored correction has been reverted with an empty tree
    When I list attempts for the stored correction
    Then the attempts list should have 1 entry

    # ── cancel_correction ────────────────────────────────────────


  Scenario: Cancel correction in pending status succeeds
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    When I cancel the stored correction
    Then the stored correction status should be "cancelled"


  Scenario: Cancel correction in applied status raises ValidationError
    Given a fresh correction service instance
    And a stored revert correction for plan "PX1" targeting "DX1"
    And the stored correction has been reverted with an empty tree
    When I attempt to cancel the stored correction
    Then a service ValidationError should have been raised

    # ── _classify_risk boundary tests ────────────────────────────


  Scenario: Classify risk at exact boundary values
    Given a fresh correction service instance
    Then classifying risk for 0 affected nodes should return "low"
    And classifying risk for 1 affected nodes should return "low"
    And classifying risk for 3 affected nodes should return "low"
    And classifying risk for 4 affected nodes should return "medium"
    And classifying risk for 10 affected nodes should return "medium"
    And classifying risk for 11 affected nodes should return "high"
    And classifying risk for 100 affected nodes should return "high"

    # ── _compute_affected_subtree BFS order ──────────────────────


  Scenario: Compute affected subtree follows BFS order
    Given a fresh correction service instance
    When I compute affected subtree for "A" with tree "A->B,C;B->D;C->E"
    Then the affected subtree should be exactly "A,B,C,D,E" in order


  Scenario: Compute affected subtree with no children returns only root
    Given a fresh correction service instance
    When I compute affected subtree for "LEAF" with an empty tree
    Then the affected subtree should be exactly "LEAF" in order


  Scenario: Compute affected subtree with wide tree
    Given a fresh correction service instance
    When I compute affected subtree for "R" with tree "R->A,B,C,D,E"
    Then the affected subtree should be exactly "R,A,B,C,D,E" in order
    And the affected subtree count should be 6

