ExAthena.Agents.Worktree (ExAthena v0.4.4)

Copy Markdown View Source

Git-worktree isolation for subagents.

When a subagent's isolation: :worktree is set, the parent's cwd is checked: must be inside a git repo, must have git on PATH, and (by default) must have a clean working tree. If any safety check fails, the caller falls back to :in_process cleanly.

Worktrees are created under ~/.cache/ex_athena/worktrees/<sess>/<name>-<n>, branched off HEAD. After the subagent finishes:

  • If it left changes in the worktree, the path + branch are surfaced in the spawn result so the caller can review/merge.
  • If the worktree is clean, it's removed via git worktree remove --force.

The WorktreeSweeper GenServer (see ExAthena.Agents.WorktreeSweeper) GCs orphaned worktrees on application start.

This module deliberately uses System.cmd/3 directly (not Tools.Bash) so worktree creation/teardown bypasses the parent's permission gate — otherwise a parent in :plan mode could never spawn a worktree-isolated subagent.

Summary

Functions

Decide what to do with a worktree after the subagent finishes.

Decide isolation strategy for def against the parent's cwd.

Functions

finalize(info)

@spec finalize(map()) :: {:kept, map()} | {:removed, map()} | {:error, term()}

Decide what to do with a worktree after the subagent finishes.

Returns {:kept, info} if the worktree had changes (caller is expected to surface the path + branch), or {:removed, info} when cleanup succeeded. Failure to remove is logged but non-fatal; the sweeper will catch it later.

resolve(definition, cwd, session_id)

@spec resolve(ExAthena.Agents.Definition.t(), String.t(), String.t()) ::
  {:worktree, map()} | {:in_process, atom()}

Decide isolation strategy for def against the parent's cwd.

Returns one of:

  • {:worktree, %{path: ..., branch: ...}} — created and ready.
  • {:in_process, reason} — fell back; reason is a short atom explaining why (:no_git, :not_a_repo, :dirty_tree, :create_failed).
  • {:in_process, :requested} — the def explicitly asks for in-process; no checks were attempted.