import type { RunLogger } from "../observability/runLog.js"; export declare const STALE_LOCK_MS = 30000; /** * Injectable monotonic-ish clock for the lock. Defaults to {@link Date.now}; tests * pass a controllable stub so staleness / timeout windows are exercised * deterministically without sleeping real wall-clock time. Every time read inside * the lock — owner-token minting, staleness comparison, deadline, backoff clamp — * routes through the `now` carried on the active options, so a single injected clock * governs the whole acquisition. `STALE_LOCK_MS` is unchanged (a duration, not a * clock) and stays exported. */ export type Clock = () => number; /** * Windows can report EPERM/EACCES for a real create/delete race, but those * errors are also what a sandbox or ACL uses when the parent directory cannot * be written. Only the former is contention. Keep the decision pure so the * boundary is testable; the caller supplies the parent-directory probe. */ export declare function isTransientPermissionContention(code: string | undefined, parentDirectoryWritable: boolean): boolean; export declare class FileLockTimeoutError extends Error { constructor(lockPath: string); } /** Optional seams for the lock: the injectable {@link Clock} + heartbeat cadence. */ export interface LockOptions { /** Clock used for all time reads in this acquisition. Defaults to {@link Date.now}. */ now?: Clock; /** * Cadence at which {@link withFileLock} refreshes the HELD lock's mtime (see * the heartbeat rationale on {@link withFileLock}). Defaults to a third of * {@link STALE_LOCK_MS}; tests inject a short interval to exercise the * refresh without waiting tens of seconds. */ heartbeatIntervalMs?: number; } export declare function acquireLock(lockPath: string, timeoutMs?: number, logger?: RunLogger, options?: LockOptions): Promise; export declare function releaseLock(lockPath: string, ownerToken: string): Promise; export declare function withFileLock(lockPath: string, fn: () => Promise, timeoutMs?: number, logger?: RunLogger, options?: LockOptions): Promise; /** * Locked read-mutate-write over a JSON artifact: `mutate` receives the current * parsed value (`undefined` when the file does not yet exist) and returns the * next value, which is written back under the same file lock — closing the * TOCTOU window between reading a JSON artifact and writing it back that a * caller doing its own read + lock + write can reintroduce. Uses the same * atomic acquire/heartbeat/release machinery as {@link withFileLock}. */ export declare function lockedJsonMutate(lockPath: string, jsonPath: string, mutate: (current: unknown) => T, options?: { timeoutMs?: number; logger?: RunLogger; } & LockOptions): Promise; //# sourceMappingURL=fileLock.d.ts.map