Files
cleveragents-core/docs/modules/git-worktree-sandbox.md
T
HAL9000 18d00c04c4
CI / lint (pull_request) Failing after 1m15s
CI / quality (pull_request) Successful in 1m21s
CI / typecheck (pull_request) Successful in 1m34s
CI / security (pull_request) Successful in 1m37s
CI / coverage (pull_request) Has been skipped
CI / unit_tests (pull_request) Failing after 1m37s
CI / docker (pull_request) Has been skipped
CI / build (pull_request) Successful in 33s
CI / helm (pull_request) Successful in 26s
CI / push-validation (pull_request) Successful in 19s
CI / e2e_tests (pull_request) Successful in 3m20s
CI / integration_tests (pull_request) Successful in 4m32s
CI / status-check (pull_request) Failing after 3s
fix(skills): implement multi-scope agent skill discovery for global, project, and local tiers
Implements AgentSkillDiscovery class to support discovering Agent Skills from
multiple configured directories across three scopes (global, project, local).
Handles name collisions with precedence: local > project > global.

Adds comprehensive BDD test coverage for multi-scope discovery scenarios including:
- Global-only, project-only, and local-only discovery
- Combined discovery from all scopes
- Name collision resolution with proper precedence
- Non-existent and empty scope directory handling
- Multiple skills in same scope discovery

ISSUES CLOSED: #9369
2026-05-06 19:55:22 +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.