@phase2 @correction @coverage Feature: CorrectionService comprehensive coverage As a developer I want thorough unit tests for the CorrectionService So that every method and branch has coverage # ── request_correction ─────────────────────────────────────── 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