Files
cleveragents-core/robot/correction_subtree_isolation.robot
Luis Mendes 1ffb0fddbe
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 3m18s
CI / typecheck (pull_request) Successful in 4m11s
CI / security (pull_request) Successful in 4m13s
CI / integration_tests (pull_request) Successful in 5m56s
CI / coverage (pull_request) Successful in 10m2s
CI / quality (pull_request) Successful in 3m40s
CI / unit_tests (pull_request) Successful in 6m6s
CI / docker (pull_request) Successful in 1m2s
CI / status-check (pull_request) Successful in 1s
CI / e2e_tests (pull_request) Successful in 8m19s
CI / build (push) Successful in 14s
CI / lint (push) Successful in 3m35s
CI / typecheck (push) Successful in 3m53s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 5m54s
CI / unit_tests (push) Successful in 7m17s
CI / e2e_tests (push) Successful in 9m39s
CI / coverage (push) Successful in 11m22s
CI / benchmark-regression (pull_request) Successful in 58m8s
CI / benchmark-publish (push) Successful in 32m8s
CI / quality (push) Successful in 3m29s
CI / security (push) Successful in 3m40s
CI / docker (push) Successful in 51s
CI / status-check (push) Successful in 1s
feat(plan): decision correction recomputes only affected subtree
Enhanced the CorrectionService to properly isolate correction scope:

1. analyze_impact() now populates excluded_decisions by computing
   the set difference between all plan decisions and the affected
   subtree, ensuring root and sibling decisions are tracked.

2. Added rollback_tier computation that counts parent hops from
   the target decision to the root, enabling depth-aware rollback
   strategies (tier 0 = root targeted, tier N = N levels deep).

3. Enhanced dry-run report with excluded decisions list, rollback
   tier, and tier-0 warning when entire tree is affected.

4. Added subtree isolation validation confirming root exclusion
   and sibling non-contamination for non-root corrections.

5. Fixed status state-machine regression in execute_revert() where
   analyze_impact() overwrote status back to ANALYZING from EXECUTING.
   Guard now only transitions to ANALYZING when status is PENDING.
   execute_revert() now transitions through ANALYZING before EXECUTING
   for correct lifecycle ordering.

6. Fixed validate_subtree_isolation() to use structural-only BFS for
   the sibling invariant check, so that influence-DAG-caused sibling
   reachability is not misreported as an isolation violation (per spec
   § Affected Subtree Computation).

7. Fixed false-positive cycle-detection warnings from convergent
   (diamond) topologies by replacing per-node seen_this_round with a
   global enqueued set in BFS, preventing duplicate queue insertions
   from different parents.

8. Added dry_run enforcement guard in _assert_executable() to prevent
   execution of dry-run-only corrections per spec (§ plan correct
   --dry-run: "Show impact without executing").

9. Fixed generate_dry_run_report() to preserve request status so that
   generating a preview does not advance the correction lifecycle
   (dry-run is non-mutating per spec).  Status restoration now uses
   try/finally to guarantee recovery even when analyze_impact() raises
   after transitioning the status.

10. Improved cycle-detection log message accuracy to cover both
    structural tree and influence DAG sources.

11. Extracted cost/time estimation constants (_COST_PER_DECISION,
    _RECOMPUTE_SECONDS_PER_DECISION) from magic numbers.

12. Added terminal-state guard in analyze_impact() to reject
    re-analysis after execution (APPLIED/FAILED/CANCELLED/REJECTED),
    preventing audit-data corruption.  Promoted terminal-status set
    to a module-level _TERMINAL_STATUSES frozenset constant.

13. Added mode validation in execute_revert()/execute_append() to
    prevent mode-mismatched execution (e.g. calling execute_revert
    on an APPEND correction).

14. Fixed _collect_all_decisions() to always include the target
    decision in the universe, preventing broken partition invariant
    for isolated single-node plans.

15. Fixed tier-0 dry-run warning to only trigger when the target
    is genuinely in the structural tree (avoiding false warnings for
    nodes not present in the tree).

16. Removed duplicate as_cli_dict regression scenarios in
    resource_type_deferred_physical.feature.

ISSUES CLOSED: #845
2026-03-23 18:41:53 +00:00

138 lines
7.6 KiB
Plaintext

*** Settings ***
Documentation Integration tests for correction subtree isolation.
... Verifies that decision corrections recompute only the
... affected subtree while excluding root and sibling nodes.
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment
Suite Teardown Cleanup Test Environment
*** Variables ***
${HELPER} robot/helper_correction_subtree_isolation.py
*** Test Cases ***
Leaf Node Isolation
[Documentation] Target a leaf — only the leaf is affected
[Tags] phase2 correction subtree isolation
${result}= Run Process ${PYTHON} ${HELPER} leaf-isolation cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} leaf-isolation-ok
Middle Node Isolation
[Documentation] Target a middle node — middle and descendants affected
[Tags] phase2 correction subtree isolation
${result}= Run Process ${PYTHON} ${HELPER} middle-node-isolation cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} middle-node-isolation-ok
Root Targets All Decisions
[Documentation] Target root — all decisions affected, none excluded
[Tags] phase2 correction subtree isolation
${result}= Run Process ${PYTHON} ${HELPER} root-targets-all cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} root-targets-all-ok
Rollback Tier Computation
[Documentation] Verify tier depth at depth 0, 1, 2, and 3
[Tags] phase2 correction subtree tier
${result}= Run Process ${PYTHON} ${HELPER} rollback-tier-computation cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} rollback-tier-computation-ok
Enhanced Dry Run Report
[Documentation] Dry-run report includes excluded decisions and tier
[Tags] phase2 correction subtree dryrun
${result}= Run Process ${PYTHON} ${HELPER} dry-run-report-enhanced cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} dry-run-report-enhanced-ok
Dry Run Tier Zero Warning
[Documentation] Root targeting triggers tier-0 warning
[Tags] phase2 correction subtree dryrun tier
${result}= Run Process ${PYTHON} ${HELPER} dry-run-tier-zero-warning cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} dry-run-tier-zero-warning-ok
Subtree Isolation Validation
[Documentation] Isolation validation passes for non-root targets
[Tags] phase2 correction subtree validation
${result}= Run Process ${PYTHON} ${HELPER} subtree-isolation-validation cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} subtree-isolation-validation-ok
Edge Case Empty Tree
[Documentation] Edge cases: empty tree, unknown node, root parent
[Tags] phase2 correction subtree edge
${result}= Run Process ${PYTHON} ${HELPER} edge-case-empty-tree cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} edge-case-empty-tree-ok
Influence DAG Traversal
[Documentation] Influence edges pull additional decisions into affected set
[Tags] phase2 correction subtree influence
${result}= Run Process ${PYTHON} ${HELPER} influence-dag-traversal cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} influence-dag-traversal-ok
Append Mode Correction
[Documentation] Append mode spawns a child plan without impact analysis
[Tags] phase2 correction subtree append
${result}= Run Process ${PYTHON} ${HELPER} append-mode-correction cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} append-mode-correction-ok
Dry Run Enforcement
[Documentation] Dry-run corrections cannot be executed
[Tags] phase2 correction subtree dryrun enforcement
${result}= Run Process ${PYTHON} ${HELPER} dry-run-enforcement cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} dry-run-enforcement-ok
Execute Revert Non Dry Run
[Documentation] Revert correction executes end-to-end with correct results
[Tags] phase2 correction subtree revert
${result}= Run Process ${PYTHON} ${HELPER} execute-revert-non-dry-run cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} execute-revert-non-dry-run-ok
Status Guard Enforcement
[Documentation] Applied and cancelled corrections cannot be re-executed
[Tags] phase2 correction subtree guard
${result}= Run Process ${PYTHON} ${HELPER} status-guard-enforcement cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} status-guard-enforcement-ok
Mode Mismatch Enforcement
[Documentation] execute_revert on append and execute_append on revert both raise
[Tags] phase2 correction subtree guard
${result}= Run Process ${PYTHON} ${HELPER} mode-mismatch-enforcement cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} mode-mismatch-enforcement-ok
Diamond DAG Topology
[Documentation] Convergent (diamond) DAG topology does not cause duplicate visits
[Tags] phase2 correction subtree influence diamond
${result}= Run Process ${PYTHON} ${HELPER} diamond-dag-topology cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} diamond-dag-topology-ok
Dry Run Exception Recovery
[Documentation] Dry-run report restores status even when analyze_impact fails
[Tags] phase2 correction subtree dryrun recovery
${result}= Run Process ${PYTHON} ${HELPER} dry-run-exception-recovery cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} dry-run-exception-recovery-ok
Execute Revert With Influence Edges
[Documentation] Revert correction works correctly with influence DAG edges
[Tags] phase2 correction subtree revert influence
${result}= Run Process ${PYTHON} ${HELPER} execute-revert-with-influence cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} execute-revert-with-influence-ok
DAG Only Nodes In Excluded Set
[Documentation] Nodes appearing only in the influence DAG are in the excluded set
[Tags] phase2 correction subtree influence excluded
${result}= Run Process ${PYTHON} ${HELPER} dag-only-nodes-excluded cwd=${WORKSPACE} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} dag-only-nodes-excluded-ok