/**
 * job-store.ts
 *
 * Job tracking store backed by the Sanity Content Lake.
 * Provides CRUD operations for `ailf.job` documents that track
 * API-triggered pipeline evaluations.
 *
 * Job documents are created by the API gateway and updated by the
 * CLI as the pipeline progresses through steps.
 *
 * @see docs/design-docs/api-service-gateway.md
 * @see packages/studio/src/schema/job.ts — Sanity document schema
 */
import type { SanityClient } from "@sanity/client";
export type JobStatus = "completed" | "failed" | "queued" | "received" | "running" | "timed-out";
export interface JobDocument {
    apiKeyPrefix?: string;
    callback?: {
        headers?: Record<string, string>;
        url: string;
    };
    completedAt?: string;
    config?: Record<string, unknown>;
    createdAt: string;
    deadlineAt?: string;
    error?: {
        message: string;
        step?: string;
    };
    execution?: {
        backend?: string;
        runId?: string;
        runUrl?: string;
    };
    jobId: string;
    progress?: {
        completedSteps?: number;
        currentStep?: string;
        totalSteps?: number;
    };
    reportId?: string;
    startedAt?: string;
    status: JobStatus;
}
export interface CreateJobOptions {
    /** API key prefix — identifies which consumer created this job */
    apiKeyPrefix: string;
    /** Callback configuration (URL + optional headers) */
    callback?: {
        headers?: Record<string, string>;
        url: string;
    };
    /** The pipeline request config (stored as JSON blob) */
    config: Record<string, unknown>;
    /** Custom deadline in milliseconds from now (default: 45 min) */
    deadlineMs?: number;
}
export interface JobStoreOptions {
    /** Override the Sanity client (for testing) */
    client?: SanityClient;
    /** Sanity dataset name */
    dataset?: string;
    /** Sanity project ID */
    projectId?: string;
    /** Sanity API token (required for writes) */
    token?: string;
}
export declare class JobStore {
    private readonly client;
    constructor(options?: JobStoreOptions);
    /**
     * Create a new job document in the Content Lake.
     *
     * Generates a job ID (e.g. "job_a1b2c3d4e5f6") and writes the
     * initial document with status "received". The job ID is used
     * directly as the Sanity document `_id`.
     *
     * @returns The generated job ID, or null on failure
     */
    createJob(options: CreateJobOptions): Promise<string | null>;
    /**
     * Count jobs created today for a given API key prefix.
     * Used for daily eval budget enforcement.
     */
    countTodayJobs(apiKeyPrefix: string): Promise<number>;
    /**
     * Count active (non-terminal) jobs for a given API key prefix.
     * Used for concurrent job limit enforcement.
     */
    countActiveJobs(apiKeyPrefix: string): Promise<number>;
    /**
     * Find stale jobs that have exceeded their deadline.
     * Used by the timeout cron job.
     */
    findStaleJobs(): Promise<JobDocument[]>;
    /**
     * Read a job by its job ID.
     */
    readJob(jobId: string): Promise<JobDocument | null>;
    /**
     * Update a job's status and optional associated data.
     */
    updateJob(jobId: string, update: Partial<Pick<JobDocument, "completedAt" | "error" | "execution" | "progress" | "reportId" | "startedAt" | "status">>): Promise<boolean>;
    /**
     * Patch the parent ailf.evalRequest doc when this job reaches a terminal
     * state. The webhook handler writes `jobId` onto the evalRequest at
     * dispatch time, so we look the parent up by that field.
     *
     * Best-effort: returns `false` on lookup miss or write failure, never
     * throws. Closes the S1-B gap from the 2026-05-24 new-eval audit — until
     * this runs, evalRequest docs stay `status: "dispatched"` indefinitely
     * and the dashboard can't surface completion or errors to users.
     *
     * @returns true on successful patch, false on lookup miss or write error
     */
    patchEvalRequestForJob(jobId: string, patch: {
        status: "completed" | "failed";
        completedAt: string;
        reportId?: string;
        error?: string;
    }): Promise<boolean>;
}
