import { type GitRunner } from './project.js';
import { type WorktreeDirEntry } from './store/index.js';
/** The filesystem the reconcile needs; `node:fs/promises` in production. */
export interface LinksFs {
    /** Names under `dir`; a missing dir yields `[]`. */
    readdir(dir: string): Promise<string[]>;
    /** Recursive mkdir. */
    mkdir(dir: string): Promise<void>;
    /** Create a symlink at `path` pointing to `target`. */
    symlink(target: string, path: string): Promise<void>;
    /** A symlink's target, or `undefined` when `path` is missing or not a symlink. */
    readlink(path: string): Promise<string | undefined>;
    /** Remove one file or symlink. */
    unlink(path: string): Promise<void>;
    /** Whether anything (file, dir, or dangling link) sits at `path`. */
    lexists(path: string): Promise<boolean>;
}
/** A {@link LinksFs} over `node:fs/promises`, dynamically imported like {@link nodeDirLister}. */
export declare function nodeLinksFs(): LinksFs;
/** Injectable seams for {@link reconcileBranchLinks}. */
export interface BranchLinksDeps {
    git?: GitRunner;
    fs?: LinksFs;
    /** The checkouts on disk (default {@link worktreeDirEntries}). */
    worktrees?: (cwd: string) => Promise<WorktreeDirEntry[]>;
    /** The branch a worktree is on (default {@link currentBranch}). */
    branchOf?: (path: string) => Promise<string | undefined>;
    /** Hide a repo-root entry from git (default {@link excludeFromGit} over `git`). */
    exclude?: (repo: string, rule: string) => Promise<void>;
}
/**
 * Bring one project's `branches/` links in line with its worktrees: one link per worktree, named
 * as the branch the worktree is on right now, plus the repo-root shortcut. Renames are covered by
 * the same rule — the old name stops being wanted and is dropped, the new one is created.
 *
 * Touches only what is provably ours: a link is created, replaced, or removed only when it points
 * (or would point) into `worktrees/`; anything else at those paths — a user's own file, dir, or
 * symlink — is left alone. Never throws.
 */
export declare function reconcileBranchLinks(cwd: string, deps?: BranchLinksDeps): Promise<void>;
/** A running reconcile pass, in the shape the daemon's other background services use. */
export interface BranchLinksPass {
    /** Run one pass now, awaiting it. */
    tick: () => Promise<void>;
    stop: () => void;
}
/** What {@link startBranchLinksPass} needs from the daemon. */
export interface BranchLinksOptions {
    projects: () => Promise<readonly {
        path: string;
    }[]>;
    /** The per-project reconcile (default {@link reconcileBranchLinks}). */
    reconcile?: (cwd: string) => Promise<void>;
}
/**
 * Keep every registered project's branch links current, one turn per call. Runs on the daemon's
 * clock; renames and reclaimed worktrees settle within a tick, and a freshly-allocated worktree
 * gets its link immediately because allocation calls the reconcile too. Quiet on purpose: links
 * are presentation, and narrating every rename would drown the log.
 */
export declare function startBranchLinksPass(opts: BranchLinksOptions): BranchLinksPass;
//# sourceMappingURL=branch-links.d.ts.map