Files
cleveragents-core/features/influence_dag_traversal.feature
freemo 8e6642e8c9
CI / lint (pull_request) Successful in 13s
CI / typecheck (pull_request) Successful in 31s
CI / security (pull_request) Successful in 32s
CI / quality (pull_request) Successful in 15s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 1m17s
CI / integration_tests (pull_request) Successful in 2m50s
CI / coverage (pull_request) Successful in 4m16s
CI / unit_tests (pull_request) Successful in 6m28s
CI / docker (pull_request) Successful in 39s
CI / lint (push) Successful in 12s
CI / typecheck (push) Successful in 31s
CI / security (push) Successful in 29s
CI / quality (push) Successful in 15s
CI / build (push) Successful in 21s
CI / unit_tests (push) Successful in 2m11s
CI / benchmark-regression (push) Has been skipped
CI / docker (push) Successful in 40s
CI / integration_tests (push) Successful in 2m58s
CI / coverage (push) Successful in 6m20s
CI / benchmark-publish (push) Successful in 14m5s
CI / benchmark-regression (pull_request) Successful in 33m18s
feat(decision): implement influence DAG traversal in correction affected subtree computation
Extended _compute_affected_subtree() to BFS over both the structural tree
(parent-child plan relationships) and decision_dependencies edges (influence
DAG). The algorithm performs a single O(V+E) BFS pass that unions neighbors
from both edge sources, using a visited set for cycle detection to guard
against data corruption.

Decision creation now supports dependency_decision_ids parameter in
record_decision() which populates the in-memory influence DAG store.
get_influence_edges() returns the adjacency list format consumed by
CorrectionService.

All public CorrectionService methods (analyze_impact, execute_revert,
execute_correction, generate_dry_run_report) accept an optional
influence_edges parameter while remaining backward-compatible (defaults
to None, preserving structural-only traversal when not provided).

Key design decisions:
- Single BFS pass over union of structural + influence edges rather than
  separate traversals, ensuring O(V+E) complexity and consistent visit order
- Cycle detection via visited set with warning log (not an error) since
  cycles indicate data corruption, not a programming error
- Influence edge logging: traversal emits count of influence edges processed
  for observability
- Backward-compatible API: existing callers that only pass decision_tree
  continue to work identically

ISSUES CLOSED: #542
2026-03-04 15:36:34 +00:00

125 lines
5.6 KiB
Gherkin

Feature: Influence DAG traversal in correction affected subtree
The affected subtree computation must traverse BOTH the structural
tree (parent-child) AND the influence DAG (decision_dependencies)
edges so that corrections cascade through influence relationships.
# ================================================================
# Structural-only (existing behaviour preserved)
# ================================================================
Scenario: Structural-only subtree with no influence edges
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree where "D1" has children "D2,D3" and "D2" has children "D4"
And no influence edges
When I analyze the impact with influence support
Then the affected decision set should be "D1,D2,D3,D4"
Scenario: Structural-only single node
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree with no children for "D1"
And no influence edges
When I analyze the impact with influence support
Then the affected decision set should be "D1"
# ================================================================
# Influence-only (new behaviour)
# ================================================================
Scenario: Influence-only affected subtree finds linked decisions
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree with no children for "D1"
And influence edges where "D1" influences "D5,D6" and "D5" influences "D7"
When I analyze the impact with influence support
Then the affected decision set should be "D1,D5,D6,D7"
Scenario: Influence-only with no structural children
Given an influence-aware correction service
And a correction request targeting decision "DX" in plan "P1" for revert
And a structural tree with no children for "DX"
And influence edges where "DX" influences "DY"
When I analyze the impact with influence support
Then the affected decision set should be "DX,DY"
# ================================================================
# Combined structural + influence (union)
# ================================================================
Scenario: Combined structural and influence subtree is the union
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree where "D1" has children "D2,D3"
And influence edges where "D1" influences "D4" and "D3" influences "D5"
When I analyze the impact with influence support
Then the affected decision set should be "D1,D2,D3,D4,D5"
Scenario: Overlapping structural and influence edges deduplicate
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree where "D1" has children "D2"
And influence edges where "D1" influences "D2"
When I analyze the impact with influence support
Then the affected decision set should be "D1,D2"
# ================================================================
# Cycle detection (corrupt data)
# ================================================================
Scenario: Cycle in influence DAG is handled gracefully
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree with no children for "D1"
And influence edges with a cycle "D1" to "D2" to "D3" back to "D1"
When I analyze the impact with influence support
Then the affected decision set should be "D1,D2,D3"
And no infinite loop occurred
Scenario: Self-loop in influence DAG is handled gracefully
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree with no children for "D1"
And influence edges where "D1" influences "D1"
When I analyze the impact with influence support
Then the affected decision set should be "D1"
# ================================================================
# Decision creation populates decision_dependencies
# ================================================================
Scenario: Decision creation records influence dependencies
Given a decision service for influence tracking
When I record a root decision "strategy_choice" for the tracked plan
And I record a child decision "implementation_choice" depending on the root decision
Then the influence edges for the tracked plan should link the root to the child
Scenario: Decision creation without dependencies records no edges
Given a decision service for influence tracking
When I record a root decision "strategy_choice" for the tracked plan
Then the influence edges for the tracked plan should be empty
# ================================================================
# Revert execution with influence edges
# ================================================================
Scenario: Revert with influence edges invalidates all affected
Given an influence-aware correction service
And a correction request targeting decision "D1" in plan "P1" for revert
And a structural tree where "D1" has children "D2"
And influence edges where "D1" influences "D3"
When I execute the revert with influence support
Then the reverted decisions should include "D1"
And the reverted decisions should include "D2"
And the reverted decisions should include "D3"