/** * Branch-lock engine — runtime enforcement for agent git isolation (T1118). * * Implements all four protection layers: * * - L1: Git worktree creation, merge-completion (ADR-062), and cleanup. * - L2: Shim symlink materialisation + spawn env construction. * - L3: Filesystem hardening via chmod (+ optional chattr on Linux). * - L4: Not here — L4 lives in validate-engine and session domain handlers. * * Worktree integration uses `git merge --no-ff` exclusively per ADR-062. * The legacy cherry-pick integration path was removed in T1624. * * All git operations use execFileSync with explicit arg arrays (no shell * interpolation) to prevent command injection. * * @task T1118 * @adr ADR-055 * @adr ADR-062 */ import type { AgentWorktreeState, EvidenceAtom, FsHardenCapabilities, FsHardenState, WorktreeCleanupResult, WorktreeDisposalBlockers, WorktreeLifecycleState, WorktreeSpawnResult } from '@cleocode/contracts'; /** * Resolve the worktree root directory for a project. * * Delegates to the canonical paths-SSoT helpers in `@cleocode/paths`. The * resolved directory follows the XDG canonical layout per D029: * * Linux: ~/.local/share/cleo/worktrees// * macOS: ~/Library/Application Support/cleo/worktrees// * Windows: %LOCALAPPDATA%\cleo\Data\worktrees\\ * * T9984: previously hand-rolled `createHash('sha256').update(projectRoot)` + * `process.env['XDG_DATA_HOME']` — both violations of the paths-SSoT lint * (`packages/paths/` is the only legitimate source of these computations). * Now routes through `computeProjectHash` and `resolveWorktreeRootForHash`. * * @param projectRoot - Absolute path to the project root. * @returns Absolute path to the worktree root directory. * * @task T1118 * @task T1120 * @task T9984 */ export declare function resolveAgentWorktreeRoot(projectRoot: string): string; /** * Read a task's worktree lifecycle state through one typed model (T10871): * the worktree git has registered for the task (its path, branch and lock), * else the canonical path; how CLEO provisioned it (newest `create`/`adopt` * lifecycle row); and whether it has uncommitted changes. Read-only. * * @param projectRoot - Absolute path to the project root. * @param taskId - Task whose worktree is read. * @returns The state; `registered`/`exists` false when there is no worktree. * * @task T10871 */ export declare function readWorktreeLifecycleState(projectRoot: string, taskId: string): WorktreeLifecycleState; /** * Create a git worktree for a spawned agent task. * * Delegates to the `@cleocode/worktree` facade ({@link createWorktree}), which * owns `git worktree add`/`lock`, the per-task lock, the lifecycle audit row * (`create`, or `adopt` for a re-attached worktree) and the sentinel index * (T10858). Branch `task/` is cut from the orchestrator's HEAD; an * existing worktree for the task is re-attached, never destroyed. No * `.worktreeinclude` copy or dependency install runs, as before. * * @param taskId - The task ID driving the spawn. * @param projectRoot - Absolute path to the project root. * @returns The created worktree state. * * @task T1118 * @task T1120 * @task T11122 * @task T11123 * @task T10858 */ export declare function createAgentWorktree(taskId: string, projectRoot: string): Promise; /** * POSIX single-quote one shell word: wrap it in `'...'` and rewrite each * embedded `'` as `'\''`. The result is one literal word for any input — no * word splitting, parameter, command or glob expansion — so a copy-pasted * `cd` into a worktree under `Application Support` parses (T12528). * * @param value - Raw path. * @returns The single-quoted shell word. */ export declare function shellQuote(value: string): string; /** * Construct the spawn env-var injection + preamble for the agent. * * Called by orchestrateSpawn after createAgentWorktree to produce the * env block and prompt preamble that bind the agent to its worktree. * * @param worktree - The created worktree state. * @param shim - The {@link ensureGitShimDir} result; strict protection and the * PATH entry apply only when it is installed (T13522). A bare directory * string is taken as installed (legacy callers). * @param identity - Per-agent session + agent identity to inject (T11343). * `sessionId` → `CLEO_SESSION_ID`, `agentId` → `CLEO_AGENT_ID`. Only set * when non-empty so an unallocated identity never clobbers an inherited env. * @returns Spawn result with env vars, CWD, and prompt preamble. * * @task T1118 * @task T1120 * @task T1121 * @task T11343 */ export declare function buildWorktreeSpawnResult(worktree: AgentWorktreeState, shim: string | GitShimInstall, identity?: { sessionId?: string | null; agentId?: string | null; }): WorktreeSpawnResult; /** * Prune orphaned agent worktrees for a project. * * T11123: Delegates to `pruneWorktrees` from `@cleocode/worktree` which uses * the NAPI `pruneWorktrees` / `destroyWorktree` bindings (Rust worktrunk-core) * instead of raw `git worktree prune/unlock/remove` shell-outs. * * @param projectRoot - Absolute path to the project root. * @param taskIds - Optional set of known-active task IDs to preserve. * @returns Cleanup result. * * @task T1118 * @task T1120 * @task T11123 */ export declare function pruneOrphanedWorktrees(projectRoot: string, taskIds?: Set): WorktreeCleanupResult; /** * Result of a single-task worktree prune operation. * * @task T1462 */ export interface PruneWorktreeResult { /** Task ID whose worktree was targeted. */ taskId: string; /** Outcome: 'pruned' — cleaned up, 'skipped' — no worktree found, 'error' — failed. */ status: 'pruned' | 'skipped' | 'error'; /** Whether the worktree directory was removed. */ worktreeRemoved: boolean; /** Whether the task branch was deleted. */ branchDeleted: boolean; /** Whether the worktree was dirty (had uncommitted changes) when pruned. */ wasDirty: boolean; /** Error message if any step failed. */ error?: string; /** Set (with `status: 'skipped'`) when the worktree was kept because something still needs its files (T13696). */ kept?: WorktreeDisposalBlockers; } /** * Prune the worktree for a single completed or cancelled task. * * This function does NOT integrate commits — it is called after * {@link completeAgentWorktreeViaMerge} (or `cleo complete`) has already * recorded the task as done. It simply removes the worktree filesystem entry * and the `task/` branch if the branch has no commits ahead of the * base ref. * * Behaviour: * - Returns `{ status: 'skipped' }` when no worktree exists for the task. * - Unlocks the worktree before removing (handles locked worktrees created by spawn). * - Falls back to `rmSync` if `git worktree remove` fails. * - Deletes `task/` branch only when it has 0 commits ahead of the * current HEAD (i.e. the branch has already been merged or is empty). * When commits are still present the branch is left in place and reported in * the result — callers should use `completeAgentWorktreeViaMerge` first. * - Always writes a `--force` remove with an audit log entry (`.cleo/audit/worktree-prune.jsonl`) * when the worktree is detected as dirty. * - Keeps the worktree (`{ status: 'skipped', kept }`) while another checkout * symlinks into it or it holds evidence found nowhere else (T13696). * - Never throws — failures are returned in `{ status: 'error', error }`. * * @param taskId - The CLEO task ID (e.g. "T1462"). * @param projectRoot - Absolute path to the project root. * @param opts.auditLogPath - Override path for the audit JSONL (testing). * @param opts.evidence - The task's recorded evidence atoms (T13696). * @returns Prune outcome. * * @task T1462 * @adr ADR-055 */ export declare function pruneWorktree(taskId: string, projectRoot: string, opts?: { auditLogPath?: string; evidence?: readonly EvidenceAtom[]; }): PruneWorktreeResult; /** Result of {@link ensureGitShimDir}. */ export interface GitShimInstall { /** Directory to prepend to a worker's PATH. */ readonly dir: string; /** True only when an executable `git` launcher now points at the real shim. */ readonly installed: boolean; /** The shim entry point used, when one was found. */ readonly shimBinPath: string | null; /** Why the shim is not installed. */ readonly reason?: string; } /** * Install the git shim launcher in the project's `.cleo/bin/git-shim/` dir * (T1118, wired in by T13522). Idempotent. * * The shim is resolved from the `@cleocode/git-shim` package the running CLI * was installed with, not from the project's node_modules, so a standalone * project gets it too. When it cannot be found or the launcher cannot be * written, nothing is installed and `installed` is `false`: callers then * advertise `CLEO_BRANCH_PROTECTION=unavailable` rather than a fence that is * not there. * * @param projectRoot - Absolute path to the project root. * @param shimBinPath - The shim entry point (tests); defaults to the installed package's. * @returns Where the shim lives and whether it is installed. * @task T1118 * @task T13522 */ export declare function ensureGitShimDir(projectRoot: string, shimBinPath?: string): GitShimInstall; /** * Detect platform capabilities for filesystem hardening. * * @returns Capability report. * * @task T1118 * @task T1122 */ export declare function detectFsHardenCapabilities(): FsHardenCapabilities; /** * Apply filesystem hardening to the orchestrator's .git/HEAD file. * * On Linux/macOS: chmod 400 the HEAD file. * When CLEO_HARD_LOCK=1: additionally attempt chattr +i (Linux) or chflags uchg (macOS). * * @param gitRoot - Absolute path to the git root directory. * @param opts.hardLock - Whether to apply immutable-file hardening. * @returns The applied harden state. * * @task T1118 * @task T1122 */ export declare function applyFsHarden(gitRoot: string, opts?: { hardLock?: boolean; }): FsHardenState; /** * Restore filesystem hardening (unlock HEAD) on session end or cleanup. * * @param hardenState - The state returned by applyFsHarden. * * @task T1118 * @task T1122 */ export declare function removeFsHarden(hardenState: FsHardenState): void; /** * Build the complete env block for a worker spawn with L1+L2 applied. * * @param worktreeResult - Result from buildWorktreeSpawnResult. * @param baseEnv - Base environment (defaults to process.env). * @returns Merged environment record. * * @task T1118 * @task T1120 * @task T1121 */ export declare function buildAgentEnv(worktreeResult: WorktreeSpawnResult, baseEnv?: Record): Record; //# sourceMappingURL=branch-lock.d.ts.map