import type { DeepReadonly } from "../eval/label/types.js"; export type LockHolder = { pid: number; token: string; acquiredAt: string; }; export type AcquireRunDirLockArgs = { dir: string; reportWarning(message: string): void; }; export type RunDirLock = { holder: DeepReadonly; release(): void; }; /** * One writer at a time for a run directory. * * This is integrity protection, not collaboration. Sign-off touches several * files in an order that matters, and two writers interleaving could publish * two revisions racing for the same version number. "There is only one * annotator" does not stop that annotator opening two terminals. * * A stale lock is never taken over automatically. Guessing that a holder is * dead and stealing the directory is exactly the move that turns a crash into * corrupted data, so an abandoned lock is reported and left for a person. */ export declare function acquireRunDirLock(args: AcquireRunDirLockArgs): RunDirLock; export type AcquireOwnedFileLockArgs = { lockFile: string; reportWarning(message: string): void; }; export type OwnedFileLock = RunDirLock; /** * @internal Acquire exactly `lockFile` (created `wx`, so an existing file is * another holder); release removes only that same file, after proving the * ownership token inside it is still ours. The run-directory lock and the * labeling locks (one per session draft, one per lineage publication) are * this one primitive at different paths. */ export declare function acquireOwnedFileLock(args: AcquireOwnedFileLockArgs): OwnedFileLock; /** Only ESRCH means the process is gone. EPERM means it exists and belongs to * someone else, which is very much alive. */ export declare function processState(pid: number): "alive" | "gone" | "unknown";