Files
cleveragents-core/docs/modules/git-worktree-sandbox.md
T
HAL9000 f293d47d26
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 18s
CI / quality (pull_request) Successful in 37s
CI / helm (pull_request) Successful in 37s
CI / lint (pull_request) Successful in 3m20s
CI / build (pull_request) Successful in 3m21s
CI / typecheck (pull_request) Successful in 3m59s
CI / security (pull_request) Successful in 4m23s
CI / e2e_tests (pull_request) Successful in 6m19s
CI / unit_tests (pull_request) Successful in 7m58s
CI / integration_tests (pull_request) Successful in 8m33s
CI / docker (pull_request) Successful in 11s
CI / coverage (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
docs: document git worktree sandbox, ACMS hydrator, and update changelog
- Add docs/modules/git-worktree-sandbox.md: full module guide for GitWorktreeSandbox (lifecycle, state machine, API, errors, apply summary, fallback)
- Add docs/api/acms.md: context_tier_hydrator API reference (hydrate_tiers_for_plan/from_project, limits, metadata, structured logs)
- Update docs/architecture.md: add Git Worktree Sandbox section and expand ACMS hydrator coverage
- Update mkdocs.yml: surface new docs in Modules and API navigation groups
- Update docs/api/index.md: add ACMS Services entry to API index
- Update CHANGELOG.md: restructure Unreleased entries with Added/Changed/Fixed summary plus existing bug IDs
- Correct Introduced versions and remove duplicate changelog entry for ACMS fix, clarify hydrator parameter types

ISSUES CLOSED: #6837
2026-04-12 16:24:02 +00:00

8.8 KiB

Git Worktree Sandbox Module

Package: cleveragents.infrastructure.sandbox.git_worktree Introduced: v3.5.0

The Git Worktree Sandbox provides isolated, git-native sandboxing for git-checkout resources. Instead of copying files to a temporary directory, it creates a real git worktree on a dedicated branch. Changes are committed in the worktree and merged back to the original branch on commit, or discarded entirely on rollback.

For the sandbox protocol interface, see docs/development/custom_sandbox_strategy.md. For the sandbox ADR, see ADR-015 Sandbox & Checkpoint.


Purpose

The previous flat-copy sandbox (shutil.copy2) had no awareness of git history, making it impossible to produce meaningful diffs or leverage git's merge machinery. The git worktree sandbox:

  • Preserves full git history for every plan's changes
  • Enables git merge for conflict detection and resolution
  • Produces accurate insertions/deletions counts for the Apply Summary panel
  • Falls back gracefully to flat-copy for non-git resources

Lifecycle

GitWorktreeSandbox(resource_id, original_path)
    │
    ▼
sandbox.create(plan_id)
    │  Creates branch cleveragents/plan-<plan_id>
    │  Creates worktree at /tmp/ca-sandbox-<plan_id>-<random>/
    ▼
sandbox.get_path("src/foo.py")
    │  Returns /tmp/ca-sandbox-.../src/foo.py
    │  Actor writes changes here
    ▼
sandbox.commit("feat: ...")
    │  git add -A  (in worktree)
    │  git commit  (in worktree)
    │  git merge cleveragents/plan-<id>  (in original repo)
    ▼
sandbox.cleanup()
    │  git worktree remove --force <path>
    │  git branch -D cleveragents/plan-<id>
    │  git worktree prune
    ▼
  CLEANED_UP

Rollback path:

sandbox.rollback()
    │  If COMMITTED: git reset --hard <pre_merge_commit>  (original repo)
    │  git reset --hard <base_commit>  (worktree)
    │  git clean -fd  (worktree)
    ▼
  ROLLED_BACK

Status State Machine

Status Description
PENDING Sandbox created but create() not yet called
CREATED Worktree and branch exist; no writes yet
ACTIVE get_path() called; actor is writing
COMMITTED Changes committed and merged to original branch
ROLLED_BACK Changes discarded; worktree reset to base commit
ERRORED A git command failed; sandbox is unusable
CLEANED_UP Worktree and branch removed

Key Class: GitWorktreeSandbox

from cleveragents.infrastructure.sandbox.git_worktree import GitWorktreeSandbox

sandbox = GitWorktreeSandbox(
    resource_id="res-01JXYZ",
    original_path="/path/to/project",
    git_timeout=30,  # seconds; default
)

Constructor Parameters

Parameter Type Default Description
resource_id str Identifier of the resource being sandboxed
original_path str Absolute path to the git repository root
git_timeout int 30 Timeout in seconds for each git command

Methods

create(plan_id: str) → SandboxContext

Creates the worktree and branch. Must be called before any other method.

  • Branch name: cleveragents/plan-<sanitised_plan_id>
  • Worktree path: /tmp/ca-sandbox-<plan_id>-<random>/
  • SandboxContext.metadata includes strategy, branch, original_branch, base_commit, and worktree_path

Raises: SandboxCreationError if git commands fail; SandboxStateError if not in PENDING status.

get_path(resource_path: str) → str

Translates a resource-relative path to its worktree equivalent.

worktree_file = sandbox.get_path("src/cleveragents/foo.py")
# → /tmp/ca-sandbox-.../src/cleveragents/foo.py

Raises: ValueError on path traversal (.. components); SandboxStateError if sandbox is not usable.

commit(message: str | None = None) → CommitResult

Stages all changes, commits in the worktree, then merges back to the original branch. Returns a CommitResult with changed_files, added_files, deleted_files, and commit_ref.

If there are no staged changes, returns a no-op CommitResult with the base commit ref and empty file lists.

Raises: SandboxCommitError on git failure; SandboxStateError if not in CREATED or ACTIVE status.

rollback() → None

Discards all changes:

  • From ACTIVE: resets the worktree branch to base_commit
  • From COMMITTED: also resets the original branch to pre_merge_commit (undoes the merge)

!!! warning "Multi-worktree safety" Rolling back from COMMITTED executes git reset --hard on the original branch. Other git worktrees or external processes tracking the same branch will be affected.

Raises: SandboxRollbackError on git failure.

cleanup() → None

Removes the worktree directory and deletes the sandbox branch. Idempotent — safe to call multiple times. Falls back to shutil.rmtree if git worktree remove fails.


CommitResult

@dataclass
class CommitResult:
    sandbox_id: str
    success: bool
    commit_ref: str | None       # SHA of the commit in the worktree
    changed_files: list[str]     # Modified files (M status)
    added_files: list[str]       # New files (A status)
    deleted_files: list[str]     # Deleted files (D status)
    error: str | None
    timestamp: datetime

Error Types

Exception When raised
SandboxCreationError git worktree add or git rev-parse fails
SandboxCommitError git commit or git merge fails
SandboxRollbackError git reset --hard or git clean fails
SandboxStateError Method called in wrong lifecycle state

All exceptions are subclasses of SandboxError from cleveragents.infrastructure.sandbox.protocol.


Non-Git Fallback

For resources that are not git repositories, plan apply falls back to the original flat-copy strategy (shutil.copy2). The GitWorktreeSandbox itself raises SandboxCreationError if the original_path is not the root of a git repository (verified via git rev-parse --show-toplevel).


Usage Example

from cleveragents.infrastructure.sandbox.git_worktree import GitWorktreeSandbox

sandbox = GitWorktreeSandbox(
    resource_id="res-01JXYZ",
    original_path="/home/user/my-project",
)

ctx = sandbox.create(plan_id="plan-01JABC")
print(f"Worktree at: {ctx.sandbox_path}")
print(f"Branch: {ctx.metadata['branch']}")

# Actor writes files into the worktree
import pathlib
target = pathlib.Path(sandbox.get_path("src/new_feature.py"))
target.write_text("# new feature\n")

# Commit and merge back
result = sandbox.commit("feat: add new_feature module")
print(f"Commit: {result.commit_ref}")
print(f"Added: {result.added_files}")

# Always clean up
sandbox.cleanup()

Apply Summary Output

When plan apply uses the git worktree sandbox, the CLI renders a spec-aligned Apply Summary panel:

╭─ Apply Summary ──────────────────────────────────────────────╮
│ Plan ID   plan-01JABC                                        │
│ Project   local/my-project                                   │
│ Timestamp 2026-04-09 14:33:34 UTC                            │
│                                                              │
│ Artifacts                                                    │
│   src/new_feature.py                                         │
│                                                              │
│ +1 insertion  0 deletions                                    │
╰──────────────────────────────────────────────────────────────╯

╭─ Sandbox Cleanup ────────────────────────────────────────────╮
│ Worktree removed  /tmp/ca-sandbox-plan-01JABC-xxxxx/         │
│ Branch deleted    cleveragents/plan-01JABC                   │
╰──────────────────────────────────────────────────────────────╯

✓ OK  Changes applied