Files
cleveragents-core/features/correction_service_coverage.feature
freemo 55aee7cf22
CI / lint (pull_request) Successful in 18s
CI / quality (pull_request) Successful in 21s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 14s
CI / security (pull_request) Successful in 49s
CI / typecheck (pull_request) Successful in 56s
CI / integration_tests (pull_request) Successful in 2m35s
CI / unit_tests (pull_request) Successful in 14m30s
CI / docker (pull_request) Successful in 55s
CI / benchmark-regression (pull_request) Successful in 21m11s
CI / coverage (pull_request) Successful in 34m22s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 16s
CI / quality (push) Successful in 17s
CI / security (push) Successful in 29s
CI / typecheck (push) Successful in 1m0s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 4m54s
CI / benchmark-publish (push) Successful in 11m48s
CI / unit_tests (push) Successful in 16m30s
CI / docker (push) Successful in 28s
CI / coverage (push) Successful in 25m45s
fix(test): commit after each add_skill to prevent session GC rollback, and improved coverage.
The step_register_skills_table step called add_skill in a loop but only
committed once at the end. Because SkillRepository.create() obtains a
new session per call and only flushes (never commits), the intermediate
sessions could be garbage-collected before the final commit, rolling
back their transactions on the shared SQLite :memory: connection. Moving
_commit_pending inside the loop ensures each skill is durably committed
before the next session is created.

ISSUES CLOSED: #418
2026-02-24 12:19:04 -05:00

343 lines
17 KiB
Gherkin
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Feature: CorrectionService full coverage
As a developer maintaining CorrectionService
I want every line and branch fully tested
So that correction_service.py achieves 100% coverage
Background:
Given a coverage test correction service
# -------------------------------------------------------------------
# __init__
# -------------------------------------------------------------------
Scenario: Service initializes with empty internal dictionaries
Then the coverage service corrections dict should be empty
And the coverage service impacts dict should be empty
And the coverage service attempts dict should be empty
And the coverage service results dict should be empty
# -------------------------------------------------------------------
# request_correction happy paths
# -------------------------------------------------------------------
Scenario: Create a revert correction with defaults
When I cov-request a correction for plan "P1" targeting "D1" in revert mode
Then the cov-request should be stored in the service
And the cov-request plan_id should be "P1"
And the cov-request target_decision_id should be "D1"
And the cov-request mode should be "revert"
And the cov-request status should be "pending"
And the cov-request dry_run should be false
And the cov-request guidance should be empty
Scenario: Create an append correction with guidance and dry_run
When I cov-request a correction for plan "P2" targeting "D2" in append mode with guidance "fix things" and dry_run
Then the cov-request should be stored in the service
And the cov-request plan_id should be "P2"
And the cov-request target_decision_id should be "D2"
And the cov-request mode should be "append"
And the cov-request dry_run should be true
And the cov-request guidance should be "fix things"
# -------------------------------------------------------------------
# request_correction validation errors
# -------------------------------------------------------------------
Scenario: Empty plan_id raises ValidationError
When I cov-attempt to create a correction with empty plan_id and target "D1"
Then a cov ValidationError should have been raised
Scenario: Whitespace-only plan_id raises ValidationError
When I cov-attempt to create a correction with plan_id " " and target "D1"
Then a cov ValidationError should have been raised
Scenario: Empty target_decision_id raises ValidationError
When I cov-attempt to create a correction with plan_id "P1" and empty target
Then a cov ValidationError should have been raised
Scenario: Whitespace-only target_decision_id raises ValidationError
When I cov-attempt to create a correction with plan_id "P1" and target " "
Then a cov ValidationError should have been raised
# -------------------------------------------------------------------
# analyze_impact BFS traversal
# -------------------------------------------------------------------
Scenario: Analyze impact with no decision tree yields single-node result
Given a cov-stored revert correction for plan "P1" targeting "ROOT"
When I cov-analyze impact with an empty tree
Then the cov-impact affected decisions should be "ROOT"
And the cov-impact risk level should be "low"
And the cov-impact rollback tier should be "full"
And the cov-impact estimated cost should be 1.5
And the cov-impact artifacts to archive should be "ROOT.artifact"
And the cov-impact affected files should be "ROOT.py"
Scenario: Analyze impact with tree having children
Given a cov-stored revert correction for plan "P1" targeting "A"
When I cov-analyze impact with adjacency "A->B,C;B->D"
Then the cov-impact affected decisions should be "A,B,C,D"
And the cov-impact risk level should be "medium"
And the cov-impact estimated cost should be 6.0
And the cov-impact affected decisions count should be 4
Scenario: Analyze impact for append mode sets rollback tier to append_only
Given a cov-stored append correction for plan "P1" targeting "X"
When I cov-analyze impact with an empty tree
Then the cov-impact rollback tier should be "append_only"
Scenario: Analyze impact for nonexistent correction raises ResourceNotFoundError
When I cov-attempt to analyze impact for correction id "BOGUS_ID"
Then a cov ResourceNotFoundError should have been raised
Scenario: Analyze impact sets status to analyzing
Given a cov-stored revert correction for plan "P1" targeting "N1"
When I cov-analyze impact with an empty tree
Then the cov-stored correction status should be "analyzing"
# -------------------------------------------------------------------
# generate_dry_run_report
# -------------------------------------------------------------------
Scenario: Dry-run report for low-risk revert with single decision
Given a cov-stored revert correction for plan "P1" targeting "SOLO"
When I cov-generate dry-run report with an empty tree
Then the cov dry-run mode should be "revert"
And the cov dry-run warnings should be empty
And the cov dry-run decisions to invalidate should be "SOLO"
And the cov dry-run estimated recompute time should be 2.0
Scenario: Dry-run report for medium-risk revert with multiple decisions
Given a cov-stored revert correction for plan "P1" targeting "R"
When I cov-generate dry-run report with adjacency "R->C1,C2,C3,C4"
Then the cov dry-run warnings should contain "Medium risk"
And the cov dry-run warnings should contain "Revert will invalidate 5 decisions"
And the cov dry-run decisions to invalidate count should be 5
And the cov dry-run estimated recompute time should be 10.0
Scenario: Dry-run report for high-risk revert
Given a cov-stored revert correction for plan "P1" targeting "H"
When I cov-generate dry-run report with a chain of 12 nodes rooted at "H"
Then the cov dry-run warnings should contain "High risk"
And the cov dry-run warnings should contain "Revert will invalidate 12 decisions"
And the cov dry-run decisions to invalidate count should be 12
Scenario: Dry-run report for append mode has empty decisions_to_invalidate
Given a cov-stored append correction for plan "P1" targeting "APP"
When I cov-generate dry-run report with an empty tree
Then the cov dry-run mode should be "append"
And the cov dry-run decisions to invalidate should be empty list
And the cov dry-run warnings should be empty
Scenario: Dry-run report for nonexistent correction raises error
When I cov-attempt to generate dry-run report for correction id "NO_SUCH"
Then a cov ResourceNotFoundError should have been raised
# -------------------------------------------------------------------
# execute_revert
# -------------------------------------------------------------------
Scenario: Execute revert on a pending correction succeeds
Given a cov-stored revert correction for plan "P1" targeting "T1"
When I cov-execute revert with adjacency "T1->T2"
Then the cov revert result status should be "applied"
And the cov revert result reverted decisions should include "T1"
And the cov revert result reverted decisions should include "T2"
And the cov revert result archived artifacts should include "T1.artifact"
And the cov revert result archived artifacts should include "T2.artifact"
And the cov-stored correction status should be "applied"
And the cov attempts for the stored correction should have 1 entry
And the cov first attempt should be successful
And the cov first attempt completed_at should be set
Scenario: Execute revert with empty tree marks only the target
Given a cov-stored revert correction for plan "P1" targeting "ONLY"
When I cov-execute revert with empty tree
Then the cov revert result status should be "applied"
And the cov revert result reverted decisions should include "ONLY"
Scenario: Execute revert on already-applied correction raises ValidationError
Given a cov-stored revert correction for plan "P1" targeting "R1"
And the cov-stored correction has been executed via revert with empty tree
When I cov-attempt to execute revert on the stored correction
Then a cov ValidationError should have been raised
# -------------------------------------------------------------------
# execute_append
# -------------------------------------------------------------------
Scenario: Execute append on a pending correction succeeds
Given a cov-stored append correction for plan "P1" targeting "A1"
When I cov-execute append for the stored correction
Then the cov append result status should be "applied"
And the cov append result spawned_child_plan_id should not be none
And the cov append result new_decisions should not be empty
And the cov-stored correction status should be "applied"
And the cov attempts for the stored correction should have 1 entry
And the cov first attempt should be successful
And the cov first attempt details should contain spawned_child_plan_id
Scenario: Execute append on already-applied correction raises ValidationError
Given a cov-stored append correction for plan "P1" targeting "A2"
And the cov-stored correction has been executed via append
When I cov-attempt to execute append on the stored correction
Then a cov ValidationError should have been raised
# -------------------------------------------------------------------
# execute_correction (dispatch)
# -------------------------------------------------------------------
Scenario: Dispatch routes revert mode to execute_revert
Given a cov-stored revert correction for plan "P1" targeting "DR"
When I cov-dispatch execute correction with adjacency "DR->DR2"
Then the cov dispatch result status should be "applied"
And the cov dispatch result reverted decisions should include "DR"
And the cov dispatch result reverted decisions should include "DR2"
Scenario: Dispatch routes append mode to execute_append
Given a cov-stored append correction for plan "P1" targeting "DA"
When I cov-dispatch execute correction with no tree
Then the cov dispatch result status should be "applied"
And the cov dispatch result spawned_child_plan_id should not be none
# -------------------------------------------------------------------
# get_correction
# -------------------------------------------------------------------
Scenario: Get correction by id returns correct request
Given a cov-stored revert correction for plan "PG" targeting "DG"
When I cov-get the stored correction by id
Then the cov-retrieved correction plan_id should be "PG"
And the cov-retrieved correction target_decision_id should be "DG"
Scenario: Get correction for nonexistent id raises ResourceNotFoundError
When I cov-attempt to get correction with id "MISSING"
Then a cov ResourceNotFoundError should have been raised
# -------------------------------------------------------------------
# list_corrections
# -------------------------------------------------------------------
Scenario: List all corrections without filter
Given a cov-stored revert correction for plan "PA" targeting "DA"
And a cov-stored revert correction for plan "PB" targeting "DB"
When I cov-list all corrections without filter
Then the cov corrections list should have at least 2 items
Scenario: List corrections filtered by plan_id
Given a cov-stored revert correction for plan "PX" targeting "DX"
Given a cov-stored append correction for plan "PY" targeting "DY"
When I cov-list corrections for plan "PX"
Then the cov corrections list should have 1 item
Scenario: List corrections filtered by plan_id with no matches
When I cov-list corrections for plan "NONEXISTENT_PLAN"
Then the cov corrections list should have 0 items
# -------------------------------------------------------------------
# list_attempts
# -------------------------------------------------------------------
Scenario: List attempts before any execution returns empty
Given a cov-stored revert correction for plan "P1" targeting "D1"
When I cov-list attempts for the stored correction
Then the cov attempts list should have 0 items
Scenario: List attempts after execution returns the attempt
Given a cov-stored revert correction for plan "P1" targeting "D1"
And the cov-stored correction has been executed via revert with empty tree
When I cov-list attempts for the stored correction
Then the cov attempts list should have 1 item
Scenario: List attempts for nonexistent correction raises error
When I cov-attempt to list attempts for correction id "NOPE"
Then a cov ResourceNotFoundError should have been raised
# -------------------------------------------------------------------
# cancel_correction
# -------------------------------------------------------------------
Scenario: Cancel a pending correction succeeds
Given a cov-stored revert correction for plan "P1" targeting "D1"
When I cov-cancel the stored correction
Then the cov-stored correction status should be "cancelled"
Scenario: Cancel an analyzing correction succeeds
Given a cov-stored revert correction for plan "P1" targeting "D1"
And the cov-stored correction has been analyzed with empty tree
When I cov-cancel the stored correction
Then the cov-stored correction status should be "cancelled"
Scenario: Cancel an already-applied correction raises ValidationError
Given a cov-stored revert correction for plan "P1" targeting "D1"
And the cov-stored correction has been executed via revert with empty tree
When I cov-attempt to cancel the stored correction
Then a cov ValidationError should have been raised
Scenario: Cancel an already-cancelled correction raises ValidationError
Given a cov-stored revert correction for plan "P1" targeting "D1"
When I cov-cancel the stored correction
And I cov-attempt to cancel the stored correction
Then a cov ValidationError should have been raised
# -------------------------------------------------------------------
# _classify_risk (static)
# -------------------------------------------------------------------
Scenario Outline: Risk classification boundary values
Then cov classifying risk for <count> affected returns "<expected>"
Examples:
| count | expected |
| 0 | low |
| 1 | low |
| 3 | low |
| 4 | medium |
| 10 | medium |
| 11 | high |
| 50 | high |
# -------------------------------------------------------------------
# _compute_affected_subtree (static)
# -------------------------------------------------------------------
Scenario: Compute affected subtree with empty tree returns only root
When I cov-compute subtree for "ROOT" with empty tree
Then the cov subtree should be "ROOT"
Scenario: Compute affected subtree with linear chain
When I cov-compute subtree for "A" with adjacency "A->B;B->C;C->D"
Then the cov subtree should be "A,B,C,D"
And the cov subtree count should be 4
Scenario: Compute affected subtree with branching tree
When I cov-compute subtree for "R" with adjacency "R->L,M;L->LL,LR"
Then the cov subtree should be "R,L,M,LL,LR"
Scenario: Compute affected subtree starting at leaf node
When I cov-compute subtree for "LEAF" with adjacency "ROOT->LEAF"
Then the cov subtree should be "LEAF"
And the cov subtree count should be 1
# -------------------------------------------------------------------
# _assert_executable internal helper (via execute_revert / execute_append)
# -------------------------------------------------------------------
Scenario: Execute revert on FAILED correction raises ValidationError
Given a cov-stored revert correction for plan "P1" targeting "F1"
And the cov-stored correction status is forced to "failed"
When I cov-attempt to execute revert on the stored correction
Then a cov ValidationError should have been raised
Scenario: Execute append on EXECUTING correction raises ValidationError
Given a cov-stored append correction for plan "P1" targeting "E1"
And the cov-stored correction status is forced to "executing"
When I cov-attempt to execute append on the stored correction
Then a cov ValidationError should have been raised
Scenario: Execute append on CANCELLED correction raises ValidationError
Given a cov-stored append correction for plan "P1" targeting "C1"
And the cov-stored correction status is forced to "cancelled"
When I cov-attempt to execute append on the stored correction
Then a cov ValidationError should have been raised