Files
freemo 0ca1303927
CI / lint (pull_request) Successful in 23s
CI / quality (pull_request) Successful in 29s
CI / security (pull_request) Successful in 54s
CI / typecheck (pull_request) Successful in 59s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 25s
CI / integration_tests (pull_request) Successful in 4m33s
CI / benchmark-regression (pull_request) Successful in 22m32s
CI / unit_tests (pull_request) Successful in 30m28s
CI / docker (pull_request) Successful in 39s
CI / coverage (pull_request) Successful in 1h39m42s
CI / lint (push) Successful in 12s
CI / quality (push) Successful in 20s
CI / build (push) Successful in 24s
CI / security (push) Successful in 28s
CI / typecheck (push) Successful in 1m0s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 4m35s
CI / benchmark-publish (push) Successful in 13m36s
CI / coverage (push) Has been cancelled
CI / unit_tests (push) Has been cancelled
CI / docker (push) Has been cancelled
feat(sandbox): add checkpoint and rollback hooks
Introduce a lightweight checkpoint/rollback system for sandbox state
during plan execute and apply flows.  CheckpointManager snapshots
the sandbox working directory before each phase and can restore it
on failure, giving the execution engine a reliable undo mechanism.

Key changes:
- SandboxCheckpoint model, Checkpointable protocol, and
  CheckpointManager in infrastructure/sandbox/checkpoint.py
- PlanExecutor gains optional checkpoint_manager with pre/post
  execute hooks and automatic rollback on failure
- PlanApplyService gains optional checkpoint_manager with pre-apply
  checkpoint and rollback helper
- 12 BDD scenarios (features/sandbox_checkpoints.feature)
- 5 Robot Framework smoke tests (robot/sandbox_checkpoint_smoke.robot)
- ASV benchmarks for creation, rollback, and listing operations
- Reference documentation in docs/reference/sandbox.md

ISSUES CLOSED: #183
2026-02-27 23:08:55 +00:00

3.9 KiB

Sandbox Infrastructure

Overview

The sandbox infrastructure provides resource isolation during plan execution. Each sandbox creates an isolated environment where a plan can read and write to a resource without affecting the original until changes are explicitly committed.

Sandbox Strategies

Strategy Class Description
none NoSandbox No isolation; writes go directly to the original
copy_on_write CopyOnWriteSandbox Filesystem copy for isolation
git_worktree GitWorktreeSandbox Git worktree for git repositories

Sandbox Lifecycle

PENDING -> CREATED -> ACTIVE -> COMMITTED -> CLEANED_UP
                        |           |
                        |           +-> CLEANED_UP
                        |
                        +-> ROLLED_BACK -> ACTIVE
                        |
                        +-> ERRORED -> CLEANED_UP

Checkpoint and Rollback Hooks

Purpose

Checkpoint hooks preserve sandbox state at key points during plan execute/apply flows. When a failure occurs, the CheckpointManager can restore a sandbox to a previously captured checkpoint.

SandboxCheckpoint Model

A frozen Pydantic model capturing a point-in-time snapshot:

Field Type Description
checkpoint_id str ULID identifier
sandbox_id str Sandbox that was checkpointed
plan_id str Plan owning the sandbox
phase str Lifecycle phase (pre_execute, post_execute, pre_apply)
created_at datetime When captured
metadata dict[str, str] Key-value metadata (status, reason, etc.)
snapshot_path str Path to the snapshot directory

CheckpointManager API

mgr = CheckpointManager()

# Create a snapshot before execute
cp = mgr.create_checkpoint(sandbox, plan_id, "pre_execute", {})

# Create a snapshot after successful execute
cp2 = mgr.create_checkpoint(sandbox, plan_id, "post_execute", {"status": "success"})

# Rollback on failure
success = mgr.rollback_to(cp)

# List all checkpoints for a sandbox
checkpoints = mgr.list_checkpoints(sandbox.sandbox_id)

# Delete a checkpoint
mgr.delete_checkpoint(cp.checkpoint_id)

Checkpoint Lifecycle

  1. Pre-execute checkpoint: Created before the execute phase starts. Captures the sandbox state so that a failed execution can be rolled back.

  2. Post-execute checkpoint: Created after a successful execute phase. Preserves the post-execution state before apply begins.

  3. Pre-apply checkpoint: Created before the apply phase starts. Allows rollback if the apply fails or encounters merge conflicts.

  4. Rollback on failure: When execute or apply fails, the system attempts to restore the sandbox to the most recent checkpoint.

Integration with Plan Executor

The PlanExecutor accepts an optional checkpoint_manager parameter. When provided, checkpoint hooks are automatically invoked:

  • Before run_execute: create_checkpoint(sandbox, plan_id, "pre_execute")
  • After successful execute: create_checkpoint(sandbox, plan_id, "post_execute")
  • On execute failure: rollback_to(last_checkpoint)

When no CheckpointManager is injected, all hooks are silently skipped.

Integration with Plan Apply Service

The PlanApplyService also accepts an optional checkpoint_manager:

  • Before apply: create_checkpoint(sandbox, plan_id, "pre_apply")
  • On apply failure: rollback_to(last_checkpoint)

Thread Safety

The CheckpointManager is thread-safe. All mutable state is protected by a reentrant lock (threading.RLock).

Snapshot Storage

Snapshots are stored in temporary directories under the system temp folder. Each snapshot is a full copy of the sandbox working directory at the time of checkpoint creation. Snapshots are cleaned up when:

  • A checkpoint is explicitly deleted via delete_checkpoint()
  • The checkpoint manager goes out of scope (manual cleanup recommended)