/**
 * report-store.ts
 *
 * Persistent report store backed by the Sanity Content Lake.
 * Provides write, read, and lineage-query operations for evaluation reports.
 *
 * The Sanity Content Lake is the system of record (P1: immutable events).
 * Reports are stored as typed documents in the shared dataset, enabling
 * GROQ queries, Studio dashboards, and webhook-driven notifications.
 *
 * If Sanity is unreachable, the store logs a warning and returns gracefully
 * (P5: local-first — the pipeline never fails because of a store write).
 *
 * @see docs/design-docs/report-store/architecture.md
 * @see docs/design-docs/report-store/domain-model.md
 */
import type { SanityClient } from "@sanity/client";
import type { ArtifactRef, ArtifactType, LoadBaselineResult, SynthesisCostTelemetry } from "./_vendor/ailf-core/index.d.ts";
import type { ComparisonReport, ISOTimestamp, LineageQuery, Report, ReportId, ReportProvenance, ScoreSummary } from "./pipeline/types.js";
/**
 * Result of an auto-comparison, bundling the ComparisonReport with the
 * baseline report ID so the caller can record lineage (comparedAgainst).
 */
export interface AutoCompareResult {
    /** The report ID of the baseline used for comparison */
    baselineReportId: ReportId;
    /** The computed comparison report */
    comparison: ComparisonReport;
}
export interface ReportStoreOptions {
    /** 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 ReportStore {
    private readonly client;
    constructor(options?: ReportStoreOptions);
    /**
     * Auto-compare: find the most recent comparable report and compute
     * a ComparisonReport using the existing compare() primitive.
     *
     * Baseline selection order:
     * 1. Explicit lineage — if `provenance.lineage.rerunOf` is set,
     *    compare against that specific report (deterministic re-run comparison)
     * 2. Fuzzy matching — most recent report with same mode + source name
     *
     * Returns the comparison plus the baseline report ID so the caller
     * can record `provenance.lineage.comparedAgainst`.
     *
     * @param scopedAreas When provided, the baseline's scores are filtered to
     *   only include these areas before comparison. This prevents mismatched
     *   areas from polluting the overall delta (e.g., release auto-scope
     *   evaluates only GROQ but the baseline has all areas).
     * @returns The comparison result with baseline ID, or null if no baseline found
     */
    autoCompare(currentSummary: ScoreSummary, provenance: ReportProvenance, completedAt: ISOTimestamp, scopedAreas?: Set<string>): Promise<AutoCompareResult | null>;
    /**
     * Find a report by its evaluation fingerprint (cross-environment cache lookup).
     *
     * Returns the most recent non-debug report whose provenance contains a
     * matching `evalFingerprint`. Used by the pipeline to skip the expensive
     * eval step when identical inputs have already been evaluated.
     *
     * Advisory lookup: a `ReportSchemaValidationError` from a corrupt prior
     * doc is logged + counted, then null is returned so the current eval
     * proceeds. Use `read(id)` when callers ask for a specific document by id.
     *
     * @returns The cached report, or null if no match or on error
     * @see docs/design-docs/content-lake-eval-caching.md
     */
    findByFingerprint(fingerprint: string): Promise<null | Report>;
    /**
     * Find the most recent comparable report for auto-comparison.
     *
     * Uses GROQ to match on key provenance dimensions (mode, source name)
     * and returns the most recent report before the given timestamp.
     *
     * "Comparable" means: same evaluation mode + same source name.
     * More granular matching (areas, models) can be added as needed.
     *
     * Advisory lookup: see `findByFingerprint` — a malformed prior baseline
     * is logged + counted and null is returned so the current run still
     * publishes its report.
     *
     * @see docs/design-docs/report-store/architecture.md — Auto-comparison
     */
    findComparableBaseline(query: LineageQuery): Promise<null | Report>;
    /**
     * Fetch the most recent report from the Content Lake.
     *
     * Mirrors the API gateway's `ReportStoreApi.latest()` signature
     * (`packages/api/src/lib/sanity.ts`). Used by `ailf interpret latest`
     * when no explicit report ID is supplied.
     *
     * @param query Optional narrowing by `mode` and/or `source.name`.
     * @returns The most recent matching report, or null if none exist
     *   or on API failure. Schema-validation errors are advisory (logged
     *   and null-returned) per the same rationale as `findByFingerprint`.
     */
    latest(query?: {
        mode?: string;
        source?: string;
    }): Promise<null | Report>;
    /**
     * Read a report by its ID.
     *
     * @throws {ReportSchemaValidationError} if the stored document fails the
     *   W0191 runtime schema gate. Sanity API failures still return null.
     */
    read(id: ReportId): Promise<null | Report>;
    /**
     * Load a previously-published report's score summary as a baseline
     * for comparison. Returns a discriminated result so the caller can
     * distinguish a genuine 404 (skip compare with a clear reason) from
     * a transport failure (fail the step — the user pinned a baseline
     * and deserves to know it didn't actually compare).
     *
     * The report's `summary` field is a `ReportSummary` — a superset of
     * `ComparableSummary` — so the projection below carries everything
     * the `compare()` primitive needs (`overall`, `perModel`, `scores`)
     * without re-hydrating the slim prose/array fields.
     */
    loadBaselineFromReport(reportId: string): Promise<LoadBaselineResult>;
    /**
     * Write a report to the Sanity Content Lake.
     *
     * Creates an immutable `ailf.report` document. The document _id is
     * prefixed with `report-` for easy GROQ filtering.
     *
     * @returns The report ID on success, null on Sanity API failure (logged,
     *   not thrown — P5 local-first).
     * @throws {ReportSchemaValidationError} if the report fails the W0191
     *   runtime schema gate. Schema drift is a bug, not an outage.
     */
    write(report: Report): Promise<null | ReportId>;
    /**
     * Patch synthesis telemetry onto a published report (Phase 6 / DIAG-06).
     * Non-fatal on Sanity failure — the on-disk reportSnapshot artifact
     * remains the source of truth. Mirrors `write()` (L379–411) for
     * error handling.
     *
     * Document _id is `report-${reportId}` (see `toSanityReportDoc` L559).
     */
    patchSynthesis(reportId: ReportId, telemetry: SynthesisCostTelemetry): Promise<void>;
    /**
     * Patch a single artifact-manifest entry onto a published report.
     *
     * Used by deferred commands like `ailf interpret` whose post-hoc writer
     * produces a new ArtifactRef *after* the report doc was published. The
     * pipeline path lifts the full manifest into the doc at publish time
     * (publish-report-step.ts:187); this method is the post-hoc equivalent
     * for a single slot.
     *
     * Non-fatal on Sanity failure — mirrors `patchSynthesis` (L423).
     *
     * Document _id is `report-${reportId}` (see `toSanityReportDoc` L559).
     */
    patchArtifactManifest(reportId: ReportId, slot: ArtifactType, ref: ArtifactRef): Promise<void>;
    /**
     * Query error arrays from the last N reports for chronic failure detection.
     *
     * Returns a simplified shape with just the report ID and error details,
     * suitable for aggregation by the chronic-failures module.
     *
     * @param limit - Number of recent reports to query (default: 10)
     * @returns Array of { reportId, errors } or empty array on failure
     */
    queryRecentErrors(limit?: number): Promise<{
        reportId: string;
        errors: {
            task: string;
            model: string;
            error: string;
        }[];
    }[]>;
}
/**
 * Generate a UUID v7 (time-sortable) for report identification.
 *
 * UUID v7 encodes the current timestamp in the high bits, making reports
 * naturally sort by creation time in both GROQ and string comparisons.
 *
 * Uses crypto.randomUUID() as a base and overwrites the timestamp portion.
 */
export declare function generateReportId(): ReportId;
/**
 * Tagged error thrown by `toReport` and `ReportStore.write` when a Content
 * Lake document fails the W0191 runtime schema gate. Read paths
 * (`read`, `findByFingerprint`, `findComparableBaseline`) re-throw this
 * error rather than swallowing it via the P5 log-and-continue try/catch
 * — schema drift is a bug to be surfaced, not an outage to be tolerated.
 */
export declare class ReportSchemaValidationError extends Error {
    constructor(message: string);
}
/**
 * Build the Sanity `ailf.report` document shape for a domain `Report`.
 *
 * Inverse of `toReport`. Strips the baseline + experiment ScoreSummary
 * bulk from any nested comparison (they duplicate `report.summary` and the
 * `comparedAgainst` lineage), and lifts `artifactManifest` into the
 * `summary.artifactManifest` slot where the D0032 GROQ projection expects
 * it.
 *
 * Pure: takes a `Report`, returns a Sanity-shaped object literal. No I/O.
 * Used by `ReportStore.write` (production) and round-trip contract tests
 * (W0188) which need a deterministic forward-and-back mapping.
 */
export interface SanityReportDoc {
    _id: string;
    _type: string;
    comparison: null | Omit<ComparisonReport, "baseline" | "experiment">;
    completedAt: string;
    degraded?: Report["degraded"];
    durationMs: number;
    provenance: Report["provenance"];
    reportId: ReportId;
    summary: Report["summary"] & {
        artifactManifest?: Report["artifactManifest"];
    };
    tag: null | string;
    title: null | string;
}
export declare function toSanityReportDoc(report: Report): SanityReportDoc;
/**
 * Convert a raw Sanity document to a typed Report.
 *
 * The Sanity document shape mirrors the Report type but includes Sanity
 * metadata (_id, _type, _rev, etc.) that we strip.
 */
export declare function toReport(doc: Record<string, unknown>): Report;
/**
 * Remove the `baseline` and `experiment` ScoreSummary objects from a
 * ComparisonReport, producing a slim copy suitable for persistence.
 *
 * These fields are redundant in the stored document:
 * - `experiment` is byte-for-byte identical to `report.summary`
 * - `baseline` is fetchable via `provenance.lineage.comparedAgainst`
 *
 * Everything else (deltas, areas, classifications) is preserved.
 */
export declare function stripComparisonBulk(comparison: ComparisonReport): Omit<ComparisonReport, "baseline" | "experiment">;
