Files
cleveragents-core/features/correction_checkpoint_rollback.feature
T
freemo 38e05ac45a
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 18s
CI / build (pull_request) Successful in 20s
CI / helm (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 1m0s
CI / quality (pull_request) Successful in 3m41s
CI / integration_tests (pull_request) Successful in 3m51s
CI / security (pull_request) Successful in 4m3s
CI / unit_tests (pull_request) Successful in 4m11s
CI / docker (pull_request) Successful in 1m31s
CI / coverage (pull_request) Successful in 11m48s
CI / e2e_tests (pull_request) Successful in 21m45s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 17s
CI / helm (push) Successful in 21s
CI / quality (push) Successful in 3m48s
CI / integration_tests (push) Successful in 3m58s
CI / typecheck (push) Successful in 3m58s
CI / security (push) Successful in 4m6s
CI / unit_tests (push) Successful in 7m16s
CI / lint (push) Successful in 8m14s
CI / benchmark-regression (push) Has been skipped
CI / docker (push) Successful in 1m36s
CI / e2e_tests (push) Successful in 18m9s
CI / coverage (push) Successful in 12m13s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 28m11s
CI / benchmark-regression (pull_request) Successful in 54m54s
feat(correction): wire checkpoint rollback into correction service revert flow
Implement the full correction-checkpoint rollback pipeline:

- Workspace snapshots: CheckpointService.create_workspace_snapshot()
  creates diff-based checkpoints before decision execution, storing
  only changed file paths in metadata.extra["diff_paths"]

- CorrectionService.revert_decisions(): new high-level entry point
  that creates a correction, computes impact, invokes checkpoint
  rollback, and archives artifacts in a single call

- Physical artifact archival: CheckpointService.archive_artifacts()
  moves files to .cleveragents/archived_artifacts/ instead of just
  flagging metadata. CorrectionService._archive_decision_artifacts()
  delegates to this during revert execution

- Selective rollback: CheckpointService.selective_rollback() wraps
  rollback_to_checkpoint with atomic semantics — captures HEAD before
  rollback and recovers on failure

- Diff-based storage: _compute_diff_snapshot() computes changed paths
  between checkpoints via git diff; snapshots store diff manifest and
  SHA-256 hash in metadata

- CLI: plan rollback now accepts --to-checkpoint <id> in addition to
  the positional checkpoint_id argument; uses selective_rollback for
  atomic execution

- DI wiring: Container now injects checkpoint_service into
  CorrectionService; CLI correct command uses container-provided
  service instead of ad-hoc instance (fixes bug #986)

- Checkpoint model: pre_decision added to allowed checkpoint_type
  values

- TDD: Removed @tdd_expected_fail from wiring test feature since the
  DI bug is now fixed

ISSUES CLOSED: #943
2026-03-30 17:06:49 -04:00

112 lines
7.3 KiB
Gherkin

@phase2 @correction @checkpoint @rollback
Feature: Correction checkpoint rollback wiring
As an operator
I want corrections to roll back filesystem state via workspace checkpoints
So that reverted decisions leave no stale artifacts on disk
#
# Workspace snapshot creation
#
Scenario: Workspace snapshot created before decision execution
Given ccr a checkpoint service
When ccr I create a workspace snapshot for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" decision "01DEC1S10N0000000000000000" with sandbox_ref "abc123"
Then ccr the snapshot should be created with type "pre_decision"
And ccr the snapshot should be aligned to decision "01DEC1S10N0000000000000000"
And ccr the snapshot metadata should indicate diff-based storage
Scenario: Workspace snapshot stores diff manifest in metadata
Given ccr a checkpoint service
When ccr I create a workspace snapshot for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV" decision "01DEC1S10N0000000000000000" with sandbox_ref "abc123"
Then ccr the snapshot metadata extra should contain "diff_based" as true
And ccr the snapshot metadata extra should contain a "diff_hash"
# ───────────────────────────────────────────────────────────
# CorrectionService.revert_decisions() wiring
# ───────────────────────────────────────────────────────────
Scenario: revert_decisions invokes checkpoint rollback
Given ccr a correction service with checkpoint support
When ccr I call revert_decisions for plan "01PL4N000000000000000000" targeting decision "01DEC0000000000000000000"
Then ccr the correction result should have status "applied"
And ccr the correction result should have reverted decisions
Scenario: revert_decisions without checkpoint service still succeeds
Given ccr a correction service without checkpoint support
When ccr I call revert_decisions for plan "01PL4N000000000000000000" targeting decision "01DEC0000000000000000000"
Then ccr the correction result should have status "applied"
And ccr the correction result checkpoint_restored should be false
# ───────────────────────────────────────────────────────────
# Physical artifact archival
# ───────────────────────────────────────────────────────────
Scenario: Artifacts physically moved to archive directory
Given ccr a temporary sandbox directory with artifact files
And ccr a checkpoint service
When ccr I archive artifacts from the sandbox
Then ccr the artifacts should exist in the archive directory
And ccr the artifacts should not exist in their original locations
Scenario: Archive tolerates missing artifact files
Given ccr a temporary sandbox directory without artifact files
And ccr a checkpoint service
When ccr I archive artifacts from the sandbox
Then ccr no errors should be raised
And ccr the archived count should be 0
# ───────────────────────────────────────────────────────────
# Selective rollback
# ───────────────────────────────────────────────────────────
Scenario: Selective rollback to a specific checkpoint
Given ccr a checkpoint service with sandbox for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
And ccr checkpoints "cp1" and "cp2" exist for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
When ccr I selectively rollback to checkpoint "cp1"
Then ccr the rollback should succeed
Scenario: Selective rollback is atomic on failure
Given ccr a checkpoint service with sandbox for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
When ccr I attempt selective rollback to a nonexistent checkpoint
Then ccr the sandbox should remain at the original HEAD
# ───────────────────────────────────────────────────────────
# Diff-based storage
# ───────────────────────────────────────────────────────────
Scenario: Diff-based checkpoint stores only changed file paths
Given ccr a checkpoint service with sandbox for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
And ccr an initial checkpoint exists for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
And ccr a file is modified and committed in the sandbox
When ccr I create a workspace snapshot capturing the diff
Then ccr the snapshot diff_paths should include the modified file
# ───────────────────────────────────────────────────────────
# Atomic rollback
# ───────────────────────────────────────────────────────────
Scenario: Atomic rollback fully restores on success
Given ccr a checkpoint service with sandbox for plan "01ARZ3NDEKTSV4RRFFQ69G5FAV"
And ccr a checkpoint is created from sandbox HEAD
And ccr a file is modified and committed in the sandbox
When ccr I perform selective rollback to the checkpoint
Then ccr the modified file should be reverted to its original state
# ───────────────────────────────────────────────────────────
# DI container wiring
# ───────────────────────────────────────────────────────────
Scenario: DI container wires checkpoint_service into CorrectionService
Given ccr a fresh DI container
When ccr I resolve the correction_service from the container
Then ccr the correction_service should have a non-None checkpoint_service
# ───────────────────────────────────────────────────────────
# CLI rollback --to-checkpoint
# ───────────────────────────────────────────────────────────
Scenario: plan rollback --to-checkpoint option accepted
Given ccr a CLI runner
When ccr I invoke plan rollback with --to-checkpoint option
Then ccr the command should recognize the --to-checkpoint flag