/**
 * Pre-creates git worktrees so new sessions / goals can claim one instantly
 * instead of waiting 10-30s for `git worktree add` + setup + `git push`.
 *
 * On startup, the pool fills to `targetSize` (default 2) in the background.
 * When a session or goal claims a worktree, the pool renames the branch,
 * moves the directory to its conventional path, and starts replenishing.
 *
 * If the pool is empty, callers fall back to the normal `createWorktree()` path.
 *
 * Branch naming:
 *   - Pool fill creates `pool/_pool-<id>` so session-manager's `session/*`
 *     orphan scans don't trip on in-flight pool entries.
 *   - `claim(targetBranch)` is the only claim entry point and renames the
 *     pool branch + directory to their final names synchronously before
 *     returning. On directory-rename failure the call returns null and
 *     the caller falls back to `createWorktree`. There is no persisted
 *     "degraded" state — see `docs/design/remove-session-worktree-rename.md`.
 *   - The fetch + reset + push that used to block claim now run in the
 *     background after returning the worktree to the caller.
 *   - `setComponents()` accepts the project's component list. When the
 *     components imply multi-repo, `_fill()` builds multi-repo pool sets
 *     via `createWorktreeSet` and `claim()` parallelises rename + move
 *     across repos.
 */
import { type WorktreeResult } from "../skills/git.js";
import type { Component } from "./project-config-store.js";
/** Result of a pool claim. */
export interface PoolClaimResult extends WorktreeResult {
    /**
     * Transient claim-result signal: in multi-repo, a per-repo `git branch -m`
     * failed even though the container rename succeeded. The worktree is
     * usable; callers may surface a warning. Single-repo claims never set
     * this — a directory-rename failure causes `claim()` to return null and
     * the caller falls back to `createWorktree`. Not persisted to disk.
     */
    degraded?: boolean;
    /** Multi-repo: per-repo worktree entries. Absent for single-repo entries. */
    worktrees?: Array<{
        repo: string;
        worktreePath: string;
    }>;
    /** Multi-repo: the per-branch container directory (`<wtRoot>/<branchSlug>`). */
    container?: string;
}
/** Component descriptor reserved for Phase 4 multi-repo pool sets. */
export interface PoolComponent {
    name: string;
    repo: string;
    relativePath?: string;
    worktreeSetupCommand?: string;
}
/** Whether a branch name belongs to a pool entry (current or legacy form). */
export declare function isPoolBranch(branch: string): boolean;
export declare class WorktreePool {
    private pool;
    private filling;
    private repoPath;
    private targetSize;
    /**
     * Live resolver for the project's components[] — called fresh on every
     * `_fill()` so config edits land on the next pool fill without restart.
     * When unset (or empty), the pool falls back to legacy single-repo fill
     * with no setup hook (no implicit project-yaml read — strictly opt-in).
     */
    private componentsResolver?;
    /**
     * Live resolver for the project's `base_ref` setting — called fresh on every
     * `_fill()` and `freshenInBackground()` so pool entries auto-adopt the
     * current configured integration target without a server restart. See
     * `docs/design/base-ref.md` §7.
     */
    private baseRefResolver?;
    /** Project-level worktree_root override (sibling of <rootPath>-wt by default). */
    private worktreeRoot?;
    /**
     * Construct a worktree pool.
     *
     * `opts.repoPath` SHOULD be a git toplevel. If a nested path inside a git
     * working tree is supplied (e.g. a project with `rootPath` pointing at a
     * subdirectory inside a larger repo), the constructor self-heals by
     * resolving to the toplevel via `git rev-parse --show-toplevel`. After
     * construction, `this.repoPath` is always the git root (or, when the
     * supplied path isn't a git working tree at all, the original input).
     */
    constructor(opts: {
        repoPath: string;
        targetSize?: number;
        componentsResolver?: () => Component[];
        baseRefResolver?: () => string | undefined;
        worktreeRoot?: string;
    });
    /** Whether the given components list implies multi-repo fill. */
    private isMultiRepo;
    /** Number of ready worktrees available. */
    get size(): number;
    /** Target pool size. */
    get target(): number;
    /** Whether the pool is currently filling. */
    get isFilling(): boolean;
    /** Status snapshot for the API. */
    getStatus(): {
        enabled: boolean;
        ready: number;
        target: number;
        filling: boolean;
    };
    /**
     * Start filling the pool in the background. Call once after startup.
     *
     * @param activeWorktreePaths — Worktree paths currently owned by live sessions.
     *   These are excluded from orphan reclamation to prevent the pool from stealing
     *   a session's working directory on restart.
     */
    startFilling(activeWorktreePaths?: Set<string>): void;
    /**
     * Replace the components resolver used for future pool fills. Existing
     * entries stay in the pool until claimed; the next `_fill()` calls the
     * resolver to pick up the latest project config.
     */
    setComponentsResolver(resolver: () => Component[]): void;
    /**
     * Claim a pre-built worktree and rename it for a target branch.
     *
     * Steps performed synchronously (the caller awaits the rename):
     *   1. `git branch -m pool/_pool-<id> <targetBranch>`
     *   2. Clear any inherited upstream unless it already points at
     *      `origin/<targetBranch>`.
     *   3. `git worktree move <oldPath> <newPath>` — on failure the call
     *      returns null (caller falls back to `createWorktree`). No persistent
     *      "degraded" state is emitted: post-refactor (see
     *      `docs/design/remove-session-worktree-rename.md`) we never persist a
     *      session whose dir name doesn't match its branch.
     *
     * Steps performed in the background (caller does NOT await):
     *   4. `git fetch origin` + `git reset --hard <remote-primary>`
     *   5. Explicitly push `<targetBranch>:refs/heads/<targetBranch>` and set
     *      upstream to `origin/<targetBranch>` (skipped under BOBBIT_TEST_NO_PUSH=1).
     *
     * Returns null if the pool is empty, or if the directory rename fails
     * (caller falls back to createWorktree).
     */
    claim(targetBranch: string): Promise<PoolClaimResult | null>;
    /**
     * Multi-repo claim: rename the container dir then `Promise.all` per-repo
     * `git branch -m` + `git worktree move` so each repo's admin pointer
     * tracks the new path. Per-repo failures are independent — a repo where
     * the move fails ends up degraded for that repo only.
     */
    private _claimMultiRepo;
    /**
     * Background freshen: fetch origin + reset --hard <base> + explicit branch push.
     * Resolves the base via `resolveBaseRef(repoPath, baseRefResolver())` so
     * pool entries adopt the project's currently-configured `base_ref` at the
     * moment they're freshened — no drain / no recorded-base needed.
     * Errors are non-fatal and logged — the worktree is still usable.
     */
    private freshenInBackground;
    /**
     * Internal async freshen. Exposed (package-private via `as any` access) for
     * unit tests that need to await freshen completion before asserting HEAD.
     * Not part of the public API.
     */
    private freshen;
    /**
     * Scan for orphaned pool worktrees from a previous server instance and reclaim them.
     * An orphaned pool worktree is a directory under `<repo>-wt/` whose branch is still
     * a pool branch (i.e. it was never claimed by a session/goal).
     *
     * Accepts both the new `pool/_pool-*` and legacy `session/_pool-*` prefixes.
     *
     * @param activeWorktreePaths — Paths owned by live sessions; skip these even if
     *   the branch name looks like a pool branch (the session may not have renamed it
     *   yet, or recovery may have restored the original pool branch name).
     */
    private reclaimOrphaned;
    /** Fill pool up to targetSize in the background. */
    private replenish;
    private _fill;
    /** Push a pre-existing pool entry into the in-memory pool. Used by the boot sweeper. */
    registerExternalEntry(branchName: string, worktreePath: string): void;
    /** Clean up all pool entries. Call on shutdown. */
    drain(): Promise<void>;
}
//# sourceMappingURL=worktree-pool.d.ts.map