- Add docs/modules/git-worktree-sandbox.md: full guide for GitWorktreeSandbox including lifecycle, class reference, usage example, rollback semantics, apply phase panels, and error handling (PR #5998) - Add docs/modules/context-tier-hydration.md: full guide for context tier hydration including API reference, file listing strategies, limits/filters, fragment metadata, and LLMExecuteActor integration (PR #4219) - Update docs/architecture.md: add Sandbox System section covering GitWorktreeSandbox and context tier hydration - Update CHANGELOG.md: add Fixed entries for plan use UNIQUE constraint violation (#4174) and duplicate execute dispatch (#2265) - Update mkdocs.yml: add new module docs to navigation
7.6 KiB
Git Worktree Sandbox
The Git Worktree Sandbox provides isolated, branch-based staging for
LLM-generated file changes during plan execution. It is the default sandbox
strategy for resources of type git-checkout and replaces the earlier
flat-directory shutil.copy2 approach for git-backed projects.
Implemented in PR #5998 (merged 2026-04-09). Spec reference: §13225–13276.
Overview
When a plan enters the Execute phase for a git-checkout resource, the sandbox:
- Creates a new git branch
cleveragents/plan-<plan_id>from the currentHEADof the repository. - Adds a git worktree at a temporary directory pointing to that branch.
- Writes all LLM file output into the worktree (not the main working tree).
- On Apply, merges the worktree branch back into the project's current
branch via
git merge. - Displays spec-aligned panels: Apply Summary, Sandbox Cleanup, and Next Steps.
- Removes the worktree and deletes the sandbox branch on cleanup.
Non-git projects fall back to the original flat-directory sandbox using
shutil.copy2.
Architecture
graph LR
subgraph "Execute Phase"
LLM["LLM Actor"] -->|writes files| WT["Git Worktree\n(temp dir)"]
WT -->|on branch| SB["cleveragents/plan-<id>"]
end
subgraph "Apply Phase"
SB -->|git merge| MAIN["Project Branch\n(original HEAD)"]
MAIN -->|cleanup| DEL["Worktree removed\nBranch deleted"]
end
The worktree is completely isolated from the main working tree. Concurrent plans on the same repository each get their own branch and worktree directory, preventing interference.
Class Reference
GitWorktreeSandbox
from cleveragents.infrastructure.sandbox.git_worktree import GitWorktreeSandbox
Implements the Sandbox protocol.
Constructor
GitWorktreeSandbox(
resource_id: str,
original_path: str,
git_timeout: int = 30,
)
| Parameter | Type | Description |
|---|---|---|
resource_id |
str |
Identifier of the resource being sandboxed. |
original_path |
str |
Absolute path to the git repository root. |
git_timeout |
int |
Timeout in seconds for each git command (default: 30). |
Raises: ValueError if any argument is invalid.
Lifecycle Methods
| Method | Description |
|---|---|
create(plan_id) |
Creates the worktree and branch. Returns SandboxContext. |
get_path(resource_path) |
Translates a resource-relative path to the worktree path. |
commit(message=None) |
Stages all changes, commits in the worktree, and merges to the original branch. |
rollback() |
Resets the worktree to the base commit; if already committed, also resets the original branch to the pre-merge commit. |
cleanup() |
Removes the worktree and deletes the sandbox branch. Idempotent. |
Status Transitions
PENDING → CREATED → ACTIVE → COMMITTED → CLEANED_UP
↘ ROLLED_BACK ↗
ERRORED (any failure)
Usage Example
from cleveragents.infrastructure.sandbox.git_worktree import GitWorktreeSandbox
sandbox = GitWorktreeSandbox(
resource_id="01HZ...",
original_path="/home/user/my-project",
)
# Create the worktree
ctx = sandbox.create(plan_id="01HZ...")
print(ctx.sandbox_path) # /tmp/ca-sandbox-01HZ...-xxxxx
# Resolve a path inside the worktree
worktree_file = sandbox.get_path("src/main.py")
# Write files (done by LLM actor)
with open(worktree_file, "w") as f:
f.write("# LLM-generated content\n")
# Commit and merge back
result = sandbox.commit("feat: LLM-generated changes")
print(result.commit_ref) # git commit hash
print(result.added_files) # ["src/main.py"]
print(result.changed_files) # []
# Cleanup
sandbox.cleanup()
Branch Naming
Sandbox branches follow the pattern:
cleveragents/plan-<sanitised_plan_id>
The plan ID is sanitised to be git-safe: only alphanumerics, hyphens, underscores, slashes, and dots are kept; runs of other characters are collapsed to a single hyphen.
Rollback Semantics
rollback() supports two scenarios:
| Status at rollback | Behaviour |
|---|---|
ACTIVE |
Resets the worktree branch to the base commit and cleans untracked files. |
COMMITTED |
Also resets the original branch to the pre-merge commit (git reset --hard), fully undoing the merge. |
!!! warning "Multi-worktree safety"
Rolling back from COMMITTED executes git reset --hard on the original
branch. If other git worktrees or external processes are tracking the same
branch, they will be affected.
Apply Phase Panels
When plan apply completes for a git-checkout resource, the CLI renders
three spec-aligned panels:
=== "Apply Summary"
┌─ Apply Summary ──────────────────────────────────────────────────┐ │ Plan ID: 01HZ... │ │ Artifacts: 3 files │ │ Changes: +42 / -7 │ │ Project: local/my-project │ │ Applied at: 2026-04-09 14:33:34 │ └──────────────────────────────────────────────────────────────────┘
=== "Sandbox Cleanup"
┌─ Sandbox Cleanup ────────────────────────────────────────────────┐ │ ✓ Worktree removed │ │ ✓ Branch merged to main │ └──────────────────────────────────────────────────────────────────┘
=== "Next Steps"
┌─ Next Steps ─────────────────────────────────────────────────────┐ │ 1. Review changes: git diff HEAD~1 │ │ 2. Commit if satisfied: git commit --amend │ └──────────────────────────────────────────────────────────────────┘ ✓ OK Changes applied
Error Handling
All git operations are wrapped with:
- Timeout: Each command has a configurable timeout (default 30 s).
subprocess.TimeoutExpiredraisesSandboxCreationError,SandboxCommitError, orSandboxRollbackErroras appropriate. - Non-zero exit:
subprocess.CalledProcessErroris caught and re-raised as the appropriate sandbox error with the git stderr included. - Cleanup fallback: If
git worktree removefails, the directory is removed manually withshutil.rmtree.
Related
docs/modules/shell-safety.md— shell danger detectiondocs/architecture.md— sandbox section- ADR-015 Sandbox & Checkpoint
- ADR-038 Cross-Mechanism Sandbox Coordination
- Source:
src/cleveragents/infrastructure/sandbox/git_worktree.py