/**
 * Single directory name every Lisa scratch root nests under.
 *
 * The name is the contract: it is what makes "one entry in the shared temp
 * root, ever" checkable, and what the sweep enumerates instead of the
 * (unenumerable) platform root.
 */
export declare const SCRATCH_NAMESPACE = "lisa-scratch";
/** Prefix identifying a per-process run root inside the namespace. */
export declare const RUN_ROOT_PREFIX = "run-";
/**
 * Backstop age after which a run root is reclaimed even though its recorded pid
 * still resolves to a live process.
 *
 * Pids are recycled, so liveness alone can pin an abandoned root forever if an
 * unrelated process happens to inherit its number. Six hours is longer than any
 * legitimate suite and short enough that a recycled pid cannot hold a root
 * across a working day.
 */
export declare const DEFAULT_RECLAIM_AGE_MS: number;
/** Environment variable that relocates the namespace away from the platform temp root. */
export declare const SCRATCH_ROOT_ENV = "LISA_TEST_SCRATCH_ROOT";
/**
 * Resolves the directory the namespace lives in.
 *
 * Honours `LISA_TEST_SCRATCH_ROOT` first so an operator or CI job can point
 * scratch space at a specific volume, then `os.tmpdir()` — which itself re-reads
 * `TMPDIR` on every call, so the pre-existing `export TMPDIR=...` mitigation
 * composes with this rather than being defeated by it.
 * @returns Absolute path to the directory containing the scratch namespace.
 */
export declare const scratchBaseDir: () => string;
/**
 * Absolute path of the shared namespace directory.
 * @returns Path to `<base>/lisa-scratch`.
 */
export declare const scratchNamespaceDir: () => string;
/**
 * Builds the name of a per-process run root.
 *
 * The pid is encoded in the name because it is the only durable record of who
 * owns the directory: a killed process leaves no other trace, and the sweep has
 * to tell an abandoned root from one a sibling run is using right now.
 * @param pid - Owning process id
 * @param startedAt - Epoch milliseconds the root was created
 * @param suffix - Random suffix disambiguating two roots created in the same millisecond
 * @returns The directory name, without any leading path.
 */
export declare const runRootName: (pid: number, startedAt: number, suffix: string) => string;
/** Ownership recorded in a run root's directory name. */
export interface RunRootOwner {
    /** Process id that created the root */
    readonly pid: number;
    /** Epoch milliseconds the root was created */
    readonly startedAt: number;
}
/**
 * Recovers the pid and creation time encoded in a run root's name.
 * @param name - A directory name from inside the namespace
 * @returns The owner, or `undefined` when the name was not produced by {@link runRootName}.
 */
export declare const parseRunRootName: (name: string) => RunRootOwner | undefined;
/** Inputs deciding whether one namespace entry may be removed. */
export interface ReclaimDecisionInput {
    /** Directory name inside the namespace */
    readonly name: string;
    /** Current epoch milliseconds */
    readonly now: number;
    /** Reports whether a pid still resolves to a running process */
    readonly isProcessAlive: (pid: number) => boolean;
    /** Age after which a live-pid root is reclaimed anyway */
    readonly maxAgeMs?: number;
    /** Name of the caller's own root, which is never reclaimed */
    readonly selfName?: string;
}
/**
 * Decides whether a namespace entry is abandoned residue.
 *
 * A name this module did not produce is not judged here — see
 * {@link isStaleForeignEntry}, which reclaims it on age alone. Deleting another
 * tool's fresh data is not this sweep's business; leaving it forever would let
 * one stray directory wedge every future run.
 * @param input - The entry and the facts needed to judge it
 * @param input.name - Directory name inside the namespace
 * @param input.now - Current epoch milliseconds
 * @param input.isProcessAlive - Liveness probe for the recorded pid
 * @param input.maxAgeMs - Age after which a live-pid root is reclaimed anyway
 * @param input.selfName - Caller's own root name, never reclaimed
 * @returns True when the entry may be removed.
 */
export declare const isReclaimable: ({ name, now, isProcessAlive, maxAgeMs, selfName, }: ReclaimDecisionInput) => boolean;
/**
 * Reports whether a pid resolves to a running process.
 *
 * `kill(pid, 0)` sends no signal; it only asks the kernel whether the target
 * exists. `EPERM` means it exists and belongs to someone else, which still
 * counts as alive.
 * @param pid - Process id to probe
 * @returns True when a process with that id exists.
 */
export declare const isProcessAlive: (pid: number) => boolean;
/**
 * Decides whether an entry this module did not create may be removed.
 *
 * Age is the only signal available: a foreign name carries no owner, so there is
 * nothing to ask the kernel about. Reclaiming on the same backstop the pid arm
 * uses means the namespace self-heals from anything parked in it — an older
 * release's naming scheme, a stray `mktemp` — without this sweep ever deleting
 * something a live tool is still writing to.
 *
 * The alternative was to treat a foreign name as a hard failure. That was tried
 * and rejected: it wedges permanently on one stray directory, and the message a
 * downstream user gets — "run roots must be named by runRootName()" — names
 * something they cannot act on.
 * @param entryPath - Absolute path of the entry
 * @param now - Current epoch milliseconds
 * @param maxAgeMs - Age past which a foreign entry is reclaimed
 * @returns True when the entry is old enough to remove.
 */
export declare const isStaleForeignEntry: (entryPath: string, now: number, maxAgeMs: number) => boolean;
/**
 * Lists the namespace's direct children, treating an absent namespace as empty.
 *
 * A directory that cannot be read is not a directory that is empty — but for the
 * one case that occurs here, the namespace not existing yet, the two are the
 * same answer and every caller wants to continue rather than fail.
 * @param dir - Namespace directory to list
 * @returns The entry names, or an empty list.
 */
export declare const readNamespaceEntries: (dir: string) => readonly string[];
/** Outcome of one sweep of the namespace. */
export interface SweepResult {
    /** Names removed as abandoned residue */
    readonly removed: readonly string[];
    /** Names left in place because a live owner still holds them */
    readonly kept: readonly string[];
}
/** Options controlling one sweep. */
export interface SweepOptions {
    /** Namespace directory to sweep (defaults to the resolved namespace) */
    readonly dir?: string;
    /** Current epoch milliseconds */
    readonly now?: number;
    /** Liveness probe, overridable for tests */
    readonly isProcessAlive?: (pid: number) => boolean;
    /** Age after which a live-pid root is reclaimed anyway */
    readonly maxAgeMs?: number;
    /** Caller's own root name, never reclaimed */
    readonly selfName?: string;
}
/**
 * Removes abandoned run roots from the namespace.
 *
 * This is the arm of the design that survives a kill. It runs at the START of a
 * run precisely because the run that leaked cannot be the one to clean up.
 * @param options - Sweep inputs
 * @param options.dir - Namespace directory to sweep
 * @param options.now - Current epoch milliseconds
 * @param options.isProcessAlive - Liveness probe for recorded pids
 * @param options.maxAgeMs - Age after which a live-pid root is reclaimed anyway
 * @param options.selfName - Caller's own root name, never reclaimed
 * @returns Which entries were removed and which were kept.
 */
export declare const sweepScratchNamespace: ({ dir, now, isProcessAlive: alive, maxAgeMs, selfName, }?: SweepOptions) => SweepResult;
/**
 * Creates a run root owned by the current process and returns its path.
 * @param options - Overrides for the namespace directory and clock
 * @param options.dir - Namespace directory to create the root inside
 * @param options.now - Epoch milliseconds recorded in the root's name
 * @returns Absolute path of this process's run root.
 */
export declare const createRunRoot: ({ dir, now, }?: {
    readonly dir?: string;
    readonly now?: number;
}) => string;
/**
 * Reclaims abandoned roots, then allocates one for this process.
 *
 * The order is the point, and it is why this is one function rather than two
 * calls at the call site: reclaiming AFTER allocating leaves a window in which
 * the namespace holds both, and reclaiming somewhere else entirely is how a
 * caller ends up allocating without ever reclaiming at all.
 * @param dir - Namespace directory
 * @returns Absolute path of the newly created run root.
 */
export declare const reclaimAndCreateRunRoot: (dir: string) => string;
/**
 * Removes a directory tree, ignoring an already-absent path.
 * @param dir - Directory to remove
 */
export declare const removeScratchDir: (dir: string) => void;
//# sourceMappingURL=scratch.d.ts.map