Files
cleveragents-core/docs/modules/git-worktree-sandbox.md
T
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

191 lines
6.6 KiB
Markdown

# 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`
```python
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.
```python
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.
```python
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.
```python
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`.
---
## Related
- [Architecture — Plan Lifecycle](../architecture.md#plan-lifecycle)
- [ADR-015 Sandbox & Checkpoint](../adr/ADR-015-sandbox-and-checkpoint.md)
- [ADR-038 Cross-Mechanism Sandbox Coordination](../adr/ADR-038-cross-mechanism-sandbox-coordination.md)
- [`cleveragents.infrastructure.sandbox`](../api/core.md)