> For the complete documentation index, see [llms.txt](https://docs.fritesai.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fritesai.com/architecture/isolation.md).

# Isolation

The `@frites/isolation` package (`packages/isolation`) gives each child agent its own git worktree to edit in, captures the resulting diff, and lands an approved diff on a fresh branch. `WorktreeManager` implements the `WorktreeManagerLike` interface the [core engine](/architecture/core-engine.md) depends on, so the engine has zero git coupling. See the package overview in [services/isolation](/services/isolation.md).

The authoritative implementation result is never the child's output text; it is the git diff captured from its worktree. This is what makes the worktree path frites's strongest verification surface.

## Worktree lifecycle

### Resolve base

`resolveBase(repoPath, ref?)` first asserts the path is a git repo (`assertGitRepo` runs `git rev-parse --is-inside-work-tree`; a non-repo raises an instructive error pointing at `git init`). It then resolves the base ref (default `HEAD`) to a concrete SHA with `git rev-parse`, so every child branches from the same immutable commit.

### Create

`create(repoPath, runId, agentId, baseSha)` runs:

```
git worktree add --quiet -b frites/run/<runId>/<agentId> .frites/worktrees/<runId>/<agentId> <baseSha>
```

The worktree path lives under `.frites/worktrees/<runId>/<agentId>` inside the repo (gitignored, local to the repo). The branch is namespaced `frites/run/<runId>/<agentId>` so it can never collide at the ref level with the apply branch `frites/apply/<runId>`. Git refs are files, so a branch named `frites/<runId>` could not coexist with `frites/<runId>/<agentId>`.

The engine creates worktrees concurrently (one per child) and registers each handle in its shared `handles` map the instant `create` returns, so cleanup always covers them on any later throw.

## captureDiff

After a child exits, `captureDiff(worktreePath)` reads the actual change out of git:

1. `git add -A`: stage everything, including new files, so the diff is complete.
2. `git diff --staged --no-color -- . <excludes>`: the unified diff.
3. `git diff --staged --name-only -- . <excludes>`: the touched-file list.

The excludes (`DIFF_EXCLUDES`) drop `node_modules`, `dist`, and `.frites` so generated artifacts never pollute candidate diffs. A candidate is usable only when its status is `succeeded` and it touched at least one file; this captured diff is the candidate's `diff` and `filesTouched`.

## Seeding the synthesis worktree

`applyDiffToWorktree(worktreePath, diff)` exists to seed the [synthesis](/architecture/core-engine.md) worktree from a known-good tree. It runs `git apply --3way --index`, applying a captured candidate diff into a worktree created from the same base SHA (so the 3-way apply is conflict-free). `--index` stages the result, and the diff is newline-terminated if needed. This method is optional on the interface; when it is absent or throws, synthesis falls back to fresh-from-base.

## Apply to branch

`applyToBranch(repoPath, runId, diff)` is the one mandatory human gate. It is separate from implementation and lands an approved diff:

1. Assert the path is a git repo.
2. **Require a clean working tree**: `git status --porcelain` must be empty, else it throws asking the user to commit or stash first (frites is about to switch branches).
3. `git switch -c frites/apply/<runId>`: create and check out a fresh branch.
4. `git apply --3way --index` the diff. If apply fails, it throws with the branch already checked out so the user can resolve manually.

It never touches the user's current branch history, never auto-merges, and never pushes. The MCP `frites_apply` tool drives this path; with synthesis, a reviewer can pass an explicit `candidateId` to land a tighter passing child instead of the recommendation. See the [safety model](/product/safety-model.md) for the apply gate's place in the blast-radius controls.

## Cleanup assumptions

`cleanup(repoPath, handle)` tears down one worktree:

```
git worktree remove --force <path>
git branch -D <branch>
git worktree prune
```

`--force` and `prune` make cleanup reliable even when a worktree was left dirty or a crash interrupted a run. The engine runs cleanup for every registered handle (children and synthesis alike) inside a single `finally` via `Promise.allSettled`, so one failed removal never blocks the others. Because the other passing children's worktrees stay alive on disk until that `finally`, the synthesizer can reference them read-only during a run.

## Related

* [Isolation service](/services/isolation.md): package overview.
* [Core engine](/architecture/core-engine.md): how the engine drives the worktree manager.
* [Safety model](/product/safety-model.md): the apply gate and blast-radius controls.
* [Agents and runners](/architecture/agents-and-runners.md): how children run inside these worktrees.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fritesai.com/architecture/isolation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
