Files
cleveragents-core/docs/adr/ADR-015-sandbox-and-checkpoint.md
T
freemo c2db74ba81
CI / lint (push) Successful in 15s
CI / build (push) Successful in 16s
CI / quality (push) Successful in 20s
CI / security (push) Successful in 35s
CI / typecheck (push) Successful in 42s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m38s
CI / integration_tests (push) Successful in 3m11s
CI / docker (push) Successful in 39s
CI / coverage (push) Successful in 4m58s
CI / benchmark-publish (push) Successful in 17m32s
Docs: Restyled ADR pages
2026-03-10 12:38:35 -04:00

9.5 KiB

adr_number, title, status_history, tier, authors, superseded_by, related_adrs, acceptance
adr_number title status_history tier authors superseded_by related_adrs acceptance
15 Sandbox and Checkpoint
2026-02-16
Proposed
Jeffrey Phillips Freeman
2026-02-16
Accepted
Jeffrey Phillips Freeman
3
Jeffrey Phillips Freeman
null
number title relationship
6 Plan Lifecycle Sandboxes are created per-plan and destroyed on plan completion or reversion
number title relationship
8 Resource System Sandbox strategy is determined by resource type (git_worktree, filesystem_copy, etc.)
number title relationship
11 Tool System Tool invocations create checkpoints for granular rollback
number title relationship
28 Agent Skills Standard (AgentSkills.io) Sub-tool-calls within Agent Skill execution are individually checkpointed
number title relationship
29 Model Context Protocol (MCP) Adoption MCP tool execution must respect sandbox boundaries via path rewriting
number title relationship
35 Decision Tree Rollback and Replay Decision-aligned checkpoints extend the checkpoint system for coordinated rollback during Execute-phase corrections
number title relationship
36 Resource DAG Operational Semantics Formalizes sandbox boundaries as a DAG property with the sandbox boundary algebra
number title relationship
38 Cross-Mechanism Sandbox Coordination Extends sandbox coordination to cross-mechanism scenarios with coherence and write-then-sync
votes_for votes_against abstentions
voter comment
Jeffrey Phillips Freeman <Jeffrey.Freeman@CleverThis.com> Lazy sandboxing with per-resource-type strategies avoids unnecessary overhead while keeping changes reversible

Context

Plans modify project resources — source code, configuration files, databases — during the Execute phase. These modifications must be isolated from the real project until they are reviewed and approved during Apply. If execution fails partway through, the system must be able to roll back to a known-good state. Different resource types require different isolation mechanisms (git worktrees for source code, filesystem copies for non-git directories, transaction rollback for databases).

Decision Drivers

  • Execute-phase modifications must be isolated from real project resources until reviewed and approved during Apply
  • Different resource types require different isolation mechanisms (git worktrees, filesystem copies, database transactions)
  • Fine-grained rollback to individual tool invocations is needed rather than reverting entire phases
  • Sandboxing overhead should be avoided for resources the plan never touches (lazy over eager)
  • Concurrent plans must not interfere with each other's sandboxed state

Decision

CleverAgents uses per-plan sandboxes with lazy sandboxing (resources sandboxed only when first accessed) and five isolation strategies selected per resource type. Checkpointing is integrated at the tool level — each tool declares whether it supports checkpoints, and the system creates checkpoints before write operations to enable fine-grained rollback.

Design

Sandbox Principles

  1. Lazy sandboxing: Resources are sandboxed only when first accessed during execution, not eagerly at plan start. This avoids unnecessary copies for resources that the plan may not touch.
  2. Per-plan sandboxes: Each plan (including child plans) has its own sandbox. No sandbox sharing between plans.
  3. Resource-defined strategy: The sandbox strategy is defined by the resource type, with a global default override via sandbox.strategy (default: git_worktree).
  4. Cleanup behavior: Cleanup before exit; abandoned sandboxes cleaned on next run; completed sandboxes based on retention policy (sandbox.cleanup: on_apply, on_terminal, or manual).

Five Isolation Strategies

git_worktree — Creates a git worktree with a plan-specific branch. Rollback via git reset/checkout. The default strategy for git-checkout resources. Provides full isolation while sharing the repository's object store.

filesystem_copy (copy_on_write) — Copies the target directory. Rollback via restoring from the original snapshot. Used for fs-directory resources.

overlay — Overlay filesystem mount. Writes go to an overlay layer; rollback by discarding the overlay. Used for fs-mount resources. More efficient than full copy for large directories.

transaction_rollback — Database transaction with rollback capability. Used for custom database resource types. Changes within the transaction are invisible to other connections until committed.

none — No isolation. Used for read-only resources or resources that cannot be sandboxed (e.g., external APIs). Requires require_sandbox: false in the automation profile.

Multi-Resource Sandboxing

When a plan operates on multiple resources:

  • Each resource gets its own sandbox with its own strategy.
  • Apply commits each resource's sandbox separately.
  • Partial apply is possible — some resources may be committed while others are not.
  • Shared resources (linked to multiple projects in a multi-project plan) get a single sandbox.

Checkpointing

Checkpointing operates at the tool level. Each tool declares:

  • checkpointable: Boolean — whether the tool supports checkpointing.
  • checkpoint_scope: The granularity of the checkpoint — file, transaction, commit, or snapshot.
  • rollback_mechanism: How rollback is performed.

Per-source checkpoint mechanisms:

Source Mechanism
Built-in file ops Git commit in worktree
Built-in git ops Git reflog
MCP tools MCP checkpoint protocol (if supported)
Agent Skills Snapshot-based
Custom tools Tool-declared mechanism

Checkpoint creation is automatic before write operations when sandbox.checkpoint.enabled is true (default). Maximum checkpoints per plan: sandbox.checkpoint.max-per-plan (default: 50). When exceeded, oldest checkpoints are pruned (keeping the first and most recent).

Execution as Transactions

Each execution step is treated as a transaction: on success, a checkpoint is committed; on failure, the step is rolled back to the previous checkpoint. This enables fine-grained recovery without re-executing the entire plan.

Checkpoint Configuration

Key Default Description
sandbox.checkpoint.enabled true Global checkpoint enable/disable
sandbox.checkpoint.dir <data-dir>/checkpoints Storage directory (subdirectory per plan ULID)
sandbox.checkpoint.max-per-plan 50 Maximum checkpoints retained

Plans can require checkpoints via the require_checkpoints flag. If enabled, only tools with checkpointable: true are permitted.

Constraints

  • All resource modifications during Execute must happen in a sandbox. Direct modification of real resources is prohibited (unless sandbox.strategy: none is explicitly configured and the automation profile allows it).
  • Lazy sandboxing means sandbox creation is deferred until first access. The system must handle the case where sandbox creation fails at access time.
  • Checkpoint pruning must keep the first and most recent checkpoints. Intermediate checkpoints are pruned oldest-first.
  • Each plan's sandbox is independent. Cross-plan sandbox access is not permitted.
  • The require_checkpoints plan flag, when enabled, rejects tools that declare checkpointable: false.

Consequences

Positive

  • Sandboxed execution ensures that incomplete or failed work never contaminates real project resources.
  • Lazy sandboxing avoids unnecessary resource copying for resources the plan does not touch.
  • Tool-level checkpointing enables fine-grained rollback without re-executing entire phases.
  • Five strategies cover the range of resource types from git repos to databases to APIs.
  • Per-plan sandboxes prevent interference between concurrent plans.

Negative

  • Sandbox management adds complexity and resource overhead (disk space for copies/worktrees, checkpoint storage).
  • Lazy sandboxing introduces a potential failure point mid-execution when the sandbox is first created.
  • The none strategy creates a gap in isolation guarantees for resources that cannot be sandboxed.

Risks

  • Disk space exhaustion from sandbox copies and checkpoints, especially for large repositories or many concurrent plans.
  • Git worktree creation may fail if the repository is in a conflicting state (e.g., another worktree exists for the same branch).
  • Overlay filesystem may not be available on all platforms (requires kernel support).

Alternatives Considered

Eager sandboxing (sandbox all resources at plan start) — Simpler but wastes resources. A plan targeting a project with 10 linked resources may only modify 2 of them. Lazy sandboxing avoids copying the other 8.

No checkpointing (full rollback only) — Simpler but coarse-grained. If step 47 of 50 fails, the entire sandbox must be reverted instead of just step 47.

Compliance

  • Isolation tests: Integration tests verify that sandbox modifications are invisible to the real project until Apply.
  • Strategy tests: Each of the five strategies has tests for creation, modification, rollback, and cleanup.
  • Checkpoint tests: Tests verify checkpoint creation, rollback to specific checkpoints, and pruning behavior.
  • Lazy sandbox tests: Tests verify that sandbox creation is deferred until first resource access and handles creation failures gracefully.
  • Cleanup tests: Tests verify that sandbox cleanup occurs at the correct lifecycle point (on_apply, on_terminal, manual).