import { type ExecutionEnv, type ExecutionEnvFactory } from "@sema-agent/core"; /** Structured logger surface this wrapper uses (matches the service `logger`; all calls optional-chained). */ export interface WorktreeIsolationLogger { info?(event: string, fields?: Record): void; warn?(event: string, fields?: Record): void; } /** Options for {@link withWorktreeIsolation}. ALL fields are operator-supplied (config/closure) — NONE come * from a `TaskSpec` or the factory `ctx` (that is the trust boundary; see the file header). */ export interface WorktreeIsolationOptions { /** * The operator-trusted base repository root — where `git worktree add/remove/prune` run (the base env's cwd * for the git command). MUST be an absolute path to a git repo. This is a CLOSURE value (config), never a * task input, so an untrusted caller can never redirect worktree creation to another path. */ repoRoot: string; /** * Operator-trusted allowlist of permitted repo roots. {@link repoRoot} MUST be contained within (or equal * to) one of these — checked at wrap time, fails LOUD otherwise. Defence in depth against a mis-wired * deployment (e.g. a `REPO_ROOT` env accidentally pointed outside the intended tree). Default: `[repoRoot]` * (repoRoot trivially permits itself) — pass a broader set only when the operator intends multiple roots. */ allowedRoots?: string[]; /** * The SHARED base {@link ExecutionEnv} used to run the git worktree commands (`add`/`remove`/`prune`). Its * own cwd is irrelevant (core passes `cwd: repoRoot` explicitly on every git call) — it only needs a working * `exec` with `git` on PATH. For the host lane this is a host env; we keep it as a single long-lived env per * deployment (git ops are cheap and serial-safe). The reaper reuses it for {@link pruneWorktrees}. */ baseEnvForGit: ExecutionEnv; /** * Env-SPECIFIC constructor of a worktree-ROOTED {@link ExecutionEnv} (the only lane-specific bit). Host lane: * `(dir) => new RemoteHostExecutionEnv({ workspaceDir: dir })` — a host env whose fs/shell operate relative * to `dir` AND whose own `destroy()` does NOT delete `dir` (persistent-dir mode), so core's destroy wrapper * owns removal via `git worktree remove`. A single-E2B/k8s deployment would pass a remote env rooted at the * worktree dir (follow-on — see file header re: suspend incompatibility on the host lane). */ rootEnvAt: (worktreeDir: string) => ExecutionEnv | Promise; /** Base commit/ref for every worktree (default core's `HEAD` at creation time). Operator-supplied. */ commit?: string; logger?: WorktreeIsolationLogger; } /** * Wrap a deployment's `executionEnvFactory` so an agent with `ctx.isolation === "worktree"` runs in its own * detached git worktree. See the file header for the full contract + trust gate + caveats. * * Throws at WRAP time (fail-loud, not faked) if `repoRoot` is not contained within `allowedRoots` — a * mis-wired deployment must not silently git-worktree an arbitrary path. */ export declare function withWorktreeIsolation(baseFactory: ExecutionEnvFactory, opts: WorktreeIsolationOptions): ExecutionEnvFactory; /** * Best-effort reaper hook: deregister worktrees orphaned by a process crash (the Runner never reached * `destroy`). Core's {@link pruneWorktrees} runs `git worktree prune` against the base repo — it cleans up * registrations whose worktree dirs are already gone. Wired into the service reaper (userland; core ships no * post-kill Runner hook). NEVER throws (a prune failure is logged, never fatal). * * NOTE: `git worktree prune` only deregisters worktrees whose DIRECTORY is missing. A crashed run that left * the dir intact is NOT reaped by prune alone — that is acceptable for v1 (the worktree lives under the known * `.sema-worktrees/` parent and is human-/script-reapable; a stricter age-based sweep is a follow-on). */ export declare function reapOrphanWorktrees(baseEnvForGit: ExecutionEnv, repoRoot: string, logger?: WorktreeIsolationLogger): Promise; //# sourceMappingURL=worktree-isolation.d.ts.map