Files
cleveragents-core/docs/modules/git-worktree-sandbox.md
HAL9000 48532de1cd
CI / helm (pull_request) Successful in 22s
CI / push-validation (pull_request) Successful in 26s
CI / typecheck (pull_request) Successful in 52s
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m20s
CI / e2e_tests (pull_request) Successful in 3m12s
CI / build (pull_request) Successful in 3m22s
CI / quality (pull_request) Successful in 3m42s
CI / security (pull_request) Successful in 4m15s
CI / integration_tests (pull_request) Successful in 8m53s
CI / unit_tests (pull_request) Successful in 8m58s
CI / docker (pull_request) Successful in 1m22s
CI / coverage (pull_request) Successful in 11m5s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (push) Waiting to run
CI / push-validation (push) Successful in 18s
CI / helm (push) Successful in 24s
CI / lint (push) Successful in 27s
CI / build (push) Successful in 33s
CI / security (push) Successful in 1m7s
CI / quality (push) Successful in 3m39s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Waiting to run
CI / integration_tests (push) Successful in 4m8s
CI / e2e_tests (push) Successful in 6m15s
CI / unit_tests (push) Successful in 8m10s
CI / docker (push) Successful in 10s
CI / coverage (push) Successful in 10m10s
CI / status-check (push) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 56m36s
docs: add context hydration and git worktree sandbox module docs
- Add docs/modules/context-hydration.md: documents the ACMS context
  hydration pipeline (context_tier_hydrator) that fixes the empty
  ContextTierService bug (#1028). Covers hydrate_tiers_from_project,
  hydrate_tiers_for_plan, file listing strategies, limits, and
  fragment metadata.

- Add docs/modules/git-worktree-sandbox.md: documents the
  GitWorktreeSandbox class that isolates plan apply changes in a
  dedicated git branch/worktree and merges back on commit (#4454).
  Covers full lifecycle, error types, branch naming, and fallback
  for non-git projects.

- Update docs/architecture.md: add Git Worktree Sandbox Apply section
  and extend ACMS section with context hydration note.

- Update mkdocs.yml: add both new module pages to the Modules nav.

ISSUES CLOSED: #6841
2026-04-12 16:42:19 +00:00

6.6 KiB

Git Worktree Sandbox

Package: cleveragents.infrastructure.sandbox.git_worktree Introduced: Unreleased (issue #4454)

The git worktree sandbox isolates plan modifications in a dedicated git branch and worktree. On commit, changes are merged back to the original branch via git merge. On rollback, the worktree is discarded entirely. This replaces the previous flat shutil.copy2 apply strategy for git-checkout resources.


Purpose

When a plan applies changes to a git-checkout resource, the changes must be isolated from the working tree until the user approves them. The git worktree sandbox achieves this by:

  1. Creating a new branch cleveragents/plan-<plan_id> from the current HEAD.
  2. Creating a temporary git worktree at a system temp directory.
  3. Letting the actor write changes inside the worktree.
  4. On commit: staging all changes, committing them in the worktree, then merging the sandbox branch back into the original branch.
  5. On rollback: resetting the worktree (and optionally the original branch) to the base commit and discarding the worktree.

Non-git projects fall back to the original flat file copy strategy.


GitWorktreeSandbox

from cleveragents.infrastructure.sandbox.git_worktree import GitWorktreeSandbox

sandbox = GitWorktreeSandbox(
    resource_id="01HZ...",
    original_path="/path/to/repo",
)

Implements the Sandbox protocol.

Constructor parameters:

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

Lifecycle

PENDING ──► create() ──► CREATED ──► get_path() ──► ACTIVE
                                                        │
                                              commit() ─┤─► COMMITTED ──► cleanup() ──► CLEANED_UP
                                                        │
                                            rollback() ─┴─► ROLLED_BACK ──► cleanup() ──► CLEANED_UP

create(plan_id) → SandboxContext

Creates the worktree and branch.

ctx = sandbox.create(plan_id="plan-01HZ...")
# ctx.sandbox_path — path to the worktree
# ctx.metadata["branch"] — e.g. "cleveragents/plan-plan-01HZ..."
# ctx.metadata["base_commit"] — HEAD SHA at creation time

Raises SandboxCreationError if the path is not a git repository root or if git worktree add fails.

get_path(resource_path) → str

Translates a resource-relative path to an absolute path inside the worktree. Rejects .. path traversal attempts.

worktree_file = sandbox.get_path("src/main.py")
# → "/tmp/ca-sandbox-plan-01HZ.../src/main.py"

commit(message=None) → CommitResult

Stages all changes in the worktree, commits them, then merges the sandbox branch into the original branch.

result = sandbox.commit("feat: implement new feature")
# result.success — True on success
# result.commit_ref — SHA of the sandbox commit
# result.changed_files — list of modified file paths
# result.added_files — list of newly added file paths
# result.deleted_files — list of deleted file paths

If there are no staged changes, returns a CommitResult with empty file lists and no new commit.

Raises SandboxCommitError if the commit or merge fails.

rollback()

Discards all worktree changes.

  • From ACTIVE: resets the worktree branch to the base commit.
  • From COMMITTED: also resets the original branch to the pre-merge commit (fully undoes 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.

cleanup()

Removes the worktree directory and deletes the sandbox branch. Idempotent — safe to call multiple times.


Apply Summary

When plan apply uses the git worktree strategy, the CLI displays a spec-aligned Apply Summary:

╭─ Apply Summary ──────────────────────────────────────╮
│ Plan ID:    plan-01HZ...                             │
│ Artifacts:  3 files changed                          │
│ Insertions: +142                                     │
│ Deletions:  -17                                      │
│ Project:    local/my-project                         │
│ Timestamp:  2026-04-09 17:30:00                      │
╰──────────────────────────────────────────────────────╯
╭─ Sandbox Cleanup ────────────────────────────────────╮
│ ✓ Worktree removed                                   │
│ ✓ Branch deleted                                     │
╰──────────────────────────────────────────────────────╯
✓ OK  Changes applied

Error Types

Exception When Raised
SandboxCreationError git worktree add fails or path is not a git root
SandboxCommitError git commit or git merge fails
SandboxRollbackError git reset --hard fails during rollback
SandboxStateError Method called in an invalid lifecycle state

All exceptions are importable from cleveragents.infrastructure.sandbox.protocol.


Branch Naming

Branch names are sanitised from the plan ID:

  • Only alphanumeric characters, hyphens, underscores, slashes, and dots are kept.
  • Runs of disallowed characters are collapsed into a single hyphen.
  • The final branch name has the form cleveragents/plan-<sanitised_plan_id>.

Fallback for Non-Git Projects

PlanLifecycleService detects whether the resource is a git-checkout type. If not, it falls back to the original flat file copy strategy (shutil.copy2). The git worktree sandbox is only used for resources where resource_type_name is git-checkout or git.