export declare const DURABLE_JOB_SCHEMA_VERSION = 1; /** How often the supervisor rewrites status.json while a job runs. */ export declare const DURABLE_JOB_HEARTBEAT_MS = 15000; /** A running job whose heartbeat is older than this earns a staleness warning, * but stays "running" while its PID is alive. */ export declare const DURABLE_JOB_HEARTBEAT_STALE_MS = 120000; export declare const DURABLE_JOB_DOCUMENT_FILENAME = "job.json"; export declare const DURABLE_JOB_STATUS_FILENAME = "status.json"; export declare const DURABLE_JOB_LOG_FILENAME = "job.log"; /** States a supervisor writes. "completed" is the only terminal one. */ export type DurableJobState = "launching" | "queued" | "running" | "completed"; /** States a reader can observe. "dead" is derived, never written. */ export type DurableJobObservedState = DurableJobState | "dead"; export interface DurableJobDocument { schema_version: number; job_id: string; /** Admission resource the job queues on. */ resource: string; /** Concurrent holders allowed on that resource. */ capacity: number; /** Human-readable description shown in listings. */ label: string; /** Argument vector of the wrapped command; argv[0] is the executable. */ argv: string[]; /** Directory the wrapped command runs in. */ cwd: string; created_at: string; } export interface DurableJobStatus { schema_version: number; job_id: string; /** PID of the supervisor, not of the wrapped command. */ pid: number; state: DurableJobState; started_at: string; updated_at: string; /** Present while the supervisor waits for an admission slot. */ queue?: { resource: string; waiting_since: string; }; exit_code?: number | null; signal?: string | null; } export interface DurableJobReport { state: DurableJobObservedState; /** The job reached "completed"; exit_code and signal are final. */ terminal: boolean; job_id: string | null; pid: number | null; resource: string | null; label: string | null; argv: string[] | null; exit_code: number | null; signal: string | null; created_at: string | null; started_at: string | null; updated_at: string | null; /** now minus status.updated_at; null without a parseable heartbeat. */ heartbeat_age_ms: number | null; queue?: { resource: string; waiting_since: string; }; job_dir: string; log_path: string; warnings: string[]; } export interface DurableJobDeps { /** PID liveness probe (injectable for tests). Default: process.kill(pid, 0). */ pidAlive?: (pid: number) => boolean; /** Evaluation instant in epoch milliseconds. Default: Date.now(). */ now?: () => number; } export type DurableJobClassification = { ok: true; report: DurableJobReport; } | { ok: false; error: string; }; export interface DurableJobListEntry { job_id: string; job_dir: string; created_at: string | null; document: DurableJobDocument | null; report: DurableJobReport | null; /** Set when the directory exists but its status document is unusable. */ error?: string; } /** Directory holding every job record under a base directory. */ export declare function jobsRoot(base: string): string; /** Directory of one job record. Does not create it. */ export declare function jobDirFor(base: string, jobId: string): string; /** Create (idempotently) the directory for one job and return its path. */ export declare function createJobDir(base: string, jobId: string): string; export declare function jobLogPath(jobDir: string): string; /** Write the immutable job description. */ export declare function writeJobDocument(jobDir: string, document: DurableJobDocument): void; /** Replace the status document atomically, so a reader never sees a torn file. */ export declare function writeJobStatus(jobDir: string, status: DurableJobStatus): void; /** Read the job description, or null when it is missing or unusable. */ export declare function readJobDocument(jobDir: string): DurableJobDocument | null; /** Read the status document, or null when it is missing or unusable. */ export declare function readJobStatus(jobDir: string): DurableJobStatus | null; /** * Classify one job directory, fail-closed. "completed" is terminal and carries * the wrapped command's exit code. Any other written state is trusted only * while the supervisor PID is alive; otherwise the job is "dead" — the record * outlived the process that owned it. */ export declare function classifyJob(jobDir: string, deps?: DurableJobDeps): DurableJobClassification; /** * Every job record under a base directory, newest first. Ordering keys on the * description's created_at, falling back to the status document's started_at, * then to the directory name, so a record missing its description still lists. */ export declare function listJobs(base: string, deps?: DurableJobDeps): DurableJobListEntry[]; /** Describe a job's outcome as a process exit code: the wrapped command's own * code, 1 when it died on a signal, 4 when the record is dead. */ export declare function jobExitCode(report: DurableJobReport): number; /** Format a duration the way the status commands do. */ export declare function formatJobAge(ms: number): string; //# sourceMappingURL=durable-job.d.ts.map