Files
cleveragents-core/docs/reference/sandbox.md
T
HAL9000 e7e7eedc4f docs: add git worktree sandbox guide, extend sandbox/plan-apply/context-tiers refs
- docs/modules/git-worktree-sandbox.md: new module guide for GitWorktreeSandbox
  (PR #5998) covering execute/apply phases, non-git fallback, conflict handling,
  and context hydration integration
- docs/reference/sandbox.md: add Strategy Selection section and Git Worktree
  Sandbox section documenting execute/apply phases and non-git fallback
- docs/reference/plan_apply.md: add Git Worktree Merge-Based Apply section with
  CLI output panels and fallback behaviour; update intro to reference PR #5998
- docs/reference/context_tiers.md: add Context Tier Hydration section documenting
  ContextTierHydrator (PR #4219), hydration algorithm, exclusion rules,
  configuration parameters, and LLMExecuteActor integration
- mkdocs.yml: add Git Worktree Sandbox to Modules nav
2026-04-28 09:25:34 +00:00

6.0 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

Strategy Selection

The sandbox strategy is chosen automatically based on the resource type:

  • Git repositories (git-checkout resources): git_worktree strategy is used. The plan's changes are committed to an isolated branch cleveragents/plan-<plan_id> inside a git worktree, keeping the working tree clean until apply.
  • Non-git directories: copy_on_write strategy is used. The resource directory is copied to a temporary location; changes are written there and copied back on apply.
  • No isolation needed: none strategy writes directly to the resource.

Git Worktree Sandbox

The GitWorktreeSandbox provides full git-native isolation for plan execution on git-checkout resources. It was introduced in v3.5.0 (PR #5998) to replace flat shutil.copy2 apply with a proper git merge workflow.

Execute Phase

  1. A git worktree is created at a temporary path for the plan's linked git-checkout resource.
  2. A new branch cleveragents/plan-<plan_id> is checked out inside the worktree.
  3. LLM-generated file output is written to the worktree directory.
  4. Changes are committed to the worktree branch — no merge yet.
  5. The worktree path is stored as a sandbox reference for the apply phase.

Apply Phase

  1. The worktree branch is merged into the project's current branch via git merge --no-ff.
  2. The CLI displays spec-aligned output panels:
    • Apply Summary: Plan ID, artifact count, insertions/deletions, project name, applied-at timestamp.
    • Sandbox Cleanup: worktree removed, branch merged to main.
    • Next Steps: review git diff, commit changes.
    • Footer: ✓ OK Changes applied
  3. The worktree is removed after a successful merge.

Non-Git Fallback

If the linked resource is not a git repository, the sandbox falls back to the copy_on_write strategy: files are copied from the sandbox directory to the project directory using shutil.copy2. Path traversal guards prevent writes outside the project root. Protected directories (.git, .cleveragents, node_modules) are skipped.

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)