/** * Cross-process advisory file lock. * * Decibel's stores are plain files in `.decibel/`, written concurrently by * every MCP client, CLI invocation, hook, and migration script on the machine. * An in-process mutex is useless here — the contending writers are separate * processes, often separate installs. * * Acquisition is `open(path, 'wx')`: O_EXCL, which either creates the file * atomically or fails with EEXIST. There is no read-then-write window for a * second caller to slip through, which is the property that makes this safe * where a "does a lock exist?" check would not be. * * The lock is advisory: it only protects callers that take it. That is why the * operations it guards should *also* be individually safe (e.g. creating a file * with O_EXCL so a colliding write fails loudly). Old clients, one-off scripts, * and migrations are part of the threat model and will not take the lock. */ export interface FileLockOptions { /** Give up acquiring after this long. */ timeoutMs?: number; /** A lock older than this is presumed abandoned by a crashed holder. */ staleMs?: number; /** Delay between acquisition attempts. */ retryIntervalMs?: number; } /** Thrown when the lock could not be acquired before the timeout. */ export declare class FileLockTimeoutError extends Error { constructor(lockPath: string, timeoutMs: number, holder?: string); } /** * Run `fn` while holding an exclusive cross-process lock. * * The lock is always released, including when `fn` throws — a failed write must * not wedge every other writer on the machine. */ export declare function withFileLock(lockPath: string, fn: () => Promise, options?: FileLockOptions): Promise; //# sourceMappingURL=fileLock.d.ts.map