import { type GitRunner } from './project.js';
import { type LinkedPr } from './dashboard/gh.js';
/** How long a scratch ref is left alone before it may go: safely past any provisioning. */
export declare const SCRATCH_REF_SAFE_AGE_MS: number;
/**
 * The shape of the pre-hand-off ref the cloud driver pushes: its own session id, a counter plus
 * the 8-hex tag (`cloud-1-3955352b`). Anchored tightly so a user's own `cloud-…` branch that does
 * not match the driver's naming is never even a candidate.
 */
export declare const CLOUD_SCRATCH_REF: RegExp;
/**
 * Where the sweep remembers when it first saw each `cloud-*` ref, under `.the-framework/`
 * (gitignored, like the other per-repo bookkeeping). Needed because the ref's name carries no
 * timestamp and its commit date says nothing — the driver pushes the worktree's HEAD, which is
 * however old the base commit happens to be, not when the hand-off happened.
 */
export declare const CLOUD_REFS_FILE = "cloud-refs.json";
/** Minimal fs seam so the state IO is unit-testable without touching disk. */
export interface ScratchFs {
    read(path: string): Promise<string>;
    write(path: string, contents: string): Promise<void>;
    mkdir(path: string): Promise<void>;
}
/** The first-seen state file path for a repo. */
export declare function cloudRefsStatePath(cwd: string): string;
/** Why a candidate ref was kept this sweep. Every one of these is retried on a later pass. */
export type ScratchKeptReason = 
/** Not past the safe age yet — the window a provisioning session could still be reading it. */
'young'
/** Its agent is one the daemon is still responsible for. */
 | 'busy'
/** Its tip is not provably on the default branch, so it may hold work. */
 | 'holds-work'
/** It has an open PR, which a deletion would close. */
 | 'open-pr';
/** What {@link sweepCloudScratchRefs} did to one repo's origin. */
export interface ScratchSweepResult {
    /** Refs deleted from origin (short names). */
    deleted: string[];
    /** Candidate refs kept, and why. Refs matching neither naming are never listed at all. */
    kept: {
        ref: string;
        reason: ScratchKeptReason;
    }[];
    /** Refs the sweep decided to delete but could not; retried next sweep. */
    failed: {
        ref: string;
        error: string;
    }[];
}
/** Injectable seams so the sweep is unit-testable off disk, off the network and off GitHub. */
export interface ScratchSweepDeps {
    git?: GitRunner;
    /** The branch's full PR history (default {@link ghPrsForBranch}). */
    prs?: (cwd: string, branch: string) => Promise<LinkedPr[]>;
    fs?: ScratchFs;
    /** The current time in ms (injected so tests can age refs deterministically). */
    now?: () => number;
    /** Override {@link SCRATCH_REF_SAFE_AGE_MS}. */
    ageMs?: number;
    /** Agent ids the daemon is still responsible for, whose run branches this must not touch. */
    busy?: ReadonlySet<string>;
}
/**
 * Sweep one repo's origin for the dead refs cloud hand-offs left behind (#1547), deleting the
 * ones that clear every gate. Never throws: a repo with no remote (or offline) sweeps nothing,
 * and a failed deletion is reported and retried next sweep.
 */
export declare function sweepCloudScratchRefs(cwd: string, deps?: ScratchSweepDeps): Promise<ScratchSweepResult>;
/** A running sweep, in the shape the daemon's other background services use. */
export interface CloudScratchSweep {
    /** Run one sweep now, awaiting it. Exposed for tests and for a caller that wants it on demand. */
    tick: () => Promise<void>;
    stop: () => void;
}
/** What {@link startCloudScratchSweep} needs from the daemon. */
export interface CloudScratchSweepOptions {
    /** The registered projects to sweep. */
    projects: () => Promise<readonly {
        path: string;
    }[]>;
    log: (message: string) => void;
    /** The agents the daemon is still responsible for, whose run branches this must not touch. */
    busy?: () => ReadonlySet<string>;
    /** The per-project sweep (default {@link sweepCloudScratchRefs}). */
    sweep?: (cwd: string) => Promise<ScratchSweepResult>;
}
/**
 * Sweep every registered project's leftover cloud scratch refs (#1547), one turn per call.
 *
 * Deletions and failures are said out loud, kept refs are not: a candidate that is merely not old
 * enough yet is the normal state of every ref this watches, and a line per tick about it would be
 * noise. A ref vanishing from origin with no line explaining why would read as a bug.
 */
export declare function startCloudScratchSweep(opts: CloudScratchSweepOptions): CloudScratchSweep;
//# sourceMappingURL=cloud-scratch-refs.d.ts.map