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