import { type GitRunner } from '../project.js';
/**
 * Git-worktree lifecycle for concurrent agents (#453/#735): give each agent its own
 * checkout so N runs on one repo never fight over the working tree. Pure plumbing
 * over the existing {@link GitRunner} seam; no daemon wiring, no concurrency, no
 * dashboard changes (those are the sibling #453 slices). This module only knows
 * how to add, list, remove, and prune worktrees.
 */
/** The path an agent's worktree gets (#1580): `<repo>/.the-framework/branches/<run branch name>`. */
export declare function worktreePath(repo: string, agentId: string): string;
export { AGENT_BRANCH_PREFIX, LEGACY_AGENT_BRANCH_PREFIX, agentBranchName, legacyAgentBranchName, } from '../branch-names.js';
/** One entry parsed from `git worktree list --porcelain`. */
export interface WorktreeInfo {
    /** Absolute worktree path (the main checkout included). */
    path: string;
    /** The checked-out commit. */
    head: string;
    /** The checked-out branch (short name), or absent when detached. */
    branch?: string;
}
/** Inputs to {@link addWorktree}. The caller owns branch naming (#736). */
export interface AddWorktreeOptions {
    agentId: string;
    /** The branch to create for the agent. */
    branch: string;
    /** Base ref to branch from; defaults to the repo's current HEAD. */
    base?: string;
}
/** The worktree {@link addWorktree} created. */
export interface AddedWorktree {
    path: string;
    branch: string;
}
/**
 * Create a worktree for an agent on a fresh branch: `git worktree add -b <branch>
 * <path> [base]`. Git makes the leaf dir (and any missing parents) itself. The
 * `agentId` is validated as path-safe first so a caller can never traverse out of
 * `.the-framework/branches/`. Rejects on any git failure (a caller that wants a
 * run needs its checkout, so failure must surface, not be swallowed).
 */
export declare function addWorktree(repo: string, opts: AddWorktreeOptions, agent?: GitRunner): Promise<AddedWorktree>;
/**
 * Check an *existing* branch out into an agent's worktree (#762): `git worktree add <path> <branch>`,
 * no `-b`. Continuing an agent puts it back on the branch its work is already on, rather than
 * branching again from HEAD and stranding what it did last time.
 *
 * Rejects on git failure, like {@link addWorktree}: a continued agent needs its checkout.
 */
export declare function attachWorktree(repo: string, opts: {
    agentId: string;
    branch: string;
}, agent?: GitRunner): Promise<AddedWorktree>;
/**
 * Every worktree registered for the repo (the main checkout included). Forgiving:
 * a non-repo / git failure yields `[]` so a reconcile scan never throws.
 */
export declare function listWorktrees(repo: string, agent?: GitRunner): Promise<WorktreeInfo[]>;
/**
 * Parse `git worktree list --porcelain`: blank-line-separated records, each with
 * a `worktree <path>` line, a `HEAD <sha>` line, and either `branch refs/heads/...`
 * or `detached`. Extra attributes (bare/locked/prunable) are ignored. Exported so
 * the parsing is unit-testable without a real repo.
 */
export declare function parseWorktreeList(porcelain: string): WorktreeInfo[];
/**
 * Commit whatever the agent left behind, on the agent's own branch (#786).
 *
 * An agent that edits and stops without committing is behaving as instructed: the
 * system prompt has it commit *pre-existing* changes before it starts, never its own
 * work at the end. Removing that checkout would destroy the diff (the work was never
 * staged, so it is not recoverable from git afterwards), so teardown commits it first
 * and the branch outlives the worktree.
 *
 * Returns whether the checkout is safe to remove: true when it was already clean or
 * the work is now committed, false when the commit failed (no git identity, a hook
 * refusing it). False means keep the checkout, which is the safe direction.
 *
 * Retries before giving up (#1376): the daemon's conversation committer works in the same
 * checkout and is busiest exactly when this runs (session end), so a first attempt can lose
 * an `index.lock` race. That transient loss is how a session's real work got judged
 * "committed nothing" by the handoff while the teardown's identical commit, seconds later,
 * succeeded. A short wait outlasts the committer's hold; a persistent failure (identity,
 * hooks) still comes back false.
 */
export declare function commitPendingWork(path: string, agent?: GitRunner, retry?: {
    attempts?: number;
    delayMs?: number;
}): Promise<boolean>;
/**
 * Remove an agent's worktree. Tolerant of an already-gone / never-registered path so
 * teardown stays idempotent (the agent child is detached; the daemon only holds its pid).
 *
 * Plain removal first: it refuses a checkout git considers unclean, which after
 * {@link commitPendingWork} means a state we did not anticipate. Falling back to
 * `--force` keeps teardown working (an ignored build artifact must not strand a
 * worktree forever), but it says so, because forcing past unknown state is exactly
 * how uncommitted work got deleted in the first place.
 */
export declare function removeWorktree(repo: string, path: string, agent?: GitRunner): Promise<void>;
/**
 * The branch checked out at `path`, or `undefined` when detached / not a repo.
 * Forgiving, like {@link listWorktrees}: callers use it to decide, not to fail.
 */
export declare function currentBranch(path: string, agent?: GitRunner): Promise<string | undefined>;
/**
 * Rename an agent's branch once the agent names the session (#736): the worktree is
 * created on `tf-agent-<agentId>` before a name exists, and this puts the
 * readable `tf-<sessionName>` on it.
 *
 * Only renames when `path` is still on `from`. The #326 system prompt currently
 * tells the agent to create and check out its own `tf-<name>` branch,
 * and until that step is dropped there (the prompt ships verbatim from the issue,
 * so it is not ours to edit) the agent may already have moved off `from` — in
 * which case it named the branch itself and there is nothing to rename. Returns
 * whether it renamed, and never throws: an agent must not die over a branch name.
 */
export declare function renameAgentBranch(path: string, from: string, to: string, agent?: GitRunner): Promise<boolean>;
/**
 * `git worktree prune`: drop administrative entries for worktree dirs a crash left
 * behind. Never removes a live worktree, so it is always safe. Forgiving.
 */
export declare function pruneWorktrees(repo: string, agent?: GitRunner): Promise<void>;
/** Runs `du`, resolving its stdout. Injectable so the size read can be tested without a real tree. */
export type SizeRunner = (path: string) => Promise<string>;
/** A {@link SizeRunner} over `du -sk`: one process, and it does not follow the symlinked deps (#736). */
export declare function nodeSizeRunner(): SizeRunner;
/**
 * A worktree's size on disk in bytes, or undefined when it cannot be read (#798). Best-effort by
 * design: this only ever labels a "remove this" button, so a missing number costs nothing while a
 * throw or a hang would cost the panel it sits in. `du` is absent on Windows, which reads as
 * unknown like any other failure.
 */
export declare function worktreeSize(path: string, agent?: SizeRunner): Promise<number | undefined>;
/**
 * Whether a branch is on the remote, with the local tip already there (E5).
 *
 * The one predicate the whole retention story is built on: nothing local is ever the last copy of
 * work, so anything the remote has may be deleted and anything it does not have stays. It replaced
 * three interacting rules — a clean finish removes the checkout, a failure keeps it, a merged
 * branch reclaims it later — each of which asked *what state did this session end in* rather than
 * *is this recoverable*.
 *
 * `git rev-parse` of the remote-tracking ref, then a merge-base check: the ref existing is not
 * enough, because a branch pushed and then committed to again has a tip the remote has never seen.
 * Reads only local refs (no fetch), so it is cheap enough to ask on every teardown — the remote ref
 * is written by the push this is checking for, which is what makes that sound.
 *
 * Anything unreadable answers `false`. A repo with no remote configured therefore keeps every
 * checkout, which is the honest outcome: there is nowhere for the work to be recoverable from.
 */
export declare function branchPushed(repo: string, branch: string, agent?: GitRunner): Promise<boolean>;
/**
 * Whether the checkout has nothing uncommitted — the read half of {@link commitPendingWork}, for
 * a decision that must not commit on the way to its answer: removing a publish-nothing session's
 * checkout requires a clean tree, and grabbing someone's half-typed edits as a commit to find
 * that out would be the intrusion the question exists to avoid. Throws when git cannot answer,
 * so the caller keeps the checkout rather than guessing.
 */
export declare function worktreeClean(path: string, agent?: GitRunner): Promise<boolean>;
/**
 * Whether the repo has any remote configured at all. What the sweep asks once per project: with
 * no remote, {@link branchPushed} is false for every checkout and the push cannot land, so the
 * whole per-checkout probe-and-push cycle is doomed before it starts — and that answer cannot
 * change between two rows of the same sweep. Anything unreadable answers `false`, like
 * {@link branchPushed}: keeping a checkout is the safe direction.
 */
export declare function repoHasRemote(repo: string, agent?: GitRunner): Promise<boolean>;
//# sourceMappingURL=worktree.d.ts.map