/**
 * Port: Where documentation context comes from.
 *
 * Adapters:
 * - SanityDocFetcher — GROQ queries against Sanity Content Lake
 *   (perspective diffing, document overlays, URL fetching)
 * - InMemoryDocFetcher (testing) — returns pre-loaded content
 *
 * The pipeline orchestrator and all downstream steps work with
 * FetchResult regardless of where the documentation came from.
 */
import type { SourceLocator } from "../../ailf-shared/index.d.ts";
import type { GeneralizedTaskDefinition } from "../types/generalized-task.js";
/**
 * A fetched documentation context ready for injection into prompts.
 *
 * Each DocContext corresponds to one task's documentation — the combined
 * markdown of all canonical docs for that task plus any overlays/URLs.
 */
export interface DocContext {
    /** The task ID this context belongs to */
    taskId: string;
    /** Combined markdown content of the fetched documentation */
    content: string;
    /** Document slugs included in this context */
    slugs: string[];
    /** Approximate token count (length / 4) */
    tokenCount?: number;
}
/**
 * Configuration for a documentation source.
 *
 * Maps to the resolved source config from config/sources.yaml, but
 * expressed as a domain type independent of the YAML structure.
 *
 * The `kind` discriminator is optional in v1 for backward compat — the
 * eval-side registry defaults untagged entries to `"sanity-content-lake"`.
 * Adapter-specific source types narrow `kind` to a literal
 * (e.g. `kind: "google-drive"`).
 */
export interface DocSourceConfig {
    /** Discriminator for source kind. Optional; eval-side registry defaults to
     *  "sanity-content-lake" when omitted. */
    readonly kind?: string;
    /** Source name; selectable via --source CLI flag. */
    readonly name?: string;
    /** Whether this entry is the default source when `--source` is omitted. */
    default?: boolean;
    /** Base URL (e.g., "https://www.sanity.io/docs") */
    baseUrl?: string;
    /** Sanity dataset (e.g., "production") */
    dataset?: string;
    /** Sanity project ID */
    projectId?: string;
    /** Custom headers for authenticated requests */
    headers?: Record<string, string>;
    /** Content release perspective (e.g., bundle name) */
    perspective?: string;
    /** Direct URLs to fetch and include in context */
    urls?: string[];
    /** Sanity document IDs for overlay (replace/append to canonical docs) */
    documentIds?: string[];
}
/**
 * Generic typed error: a fetcher received a ref whose `kind` it does not
 * accept. Each adapter throws this when given a foreign or untagged ref.
 */
export declare class RefKindMismatchError extends Error {
    constructor(message: string);
}
/** Metadata about a fetched document, for traceability */
export interface DocumentManifestEntry {
    /**
     * Source-tagged retrieval contract (D0062) stamped by the producer at
     * fetch time, when the resolved source coordinates are in hand. The
     * locator's `documentId`/`revision` are the `sanity-content-lake` mapping
     * of this entry's native `_id`/`_rev`. Carried through to the
     * `DocumentRef` built at the gap-analysis boundary so new reports become
     * self-describing. Optional: absent on legacy manifests written before
     * the locator landed (consumers fall back to {@link resolveLocator}).
     */
    locator?: SourceLocator;
    _id: string;
    _rev: string;
    slug: string;
    /** Parent section slug (`primarySection->slug.current`), when resolvable. */
    sectionSlug?: string;
    /**
     * Full URL path under `/docs/` (e.g. `content-lake/groq-introduction`)
     * composed via `buildContextDocPath` from `sectionSlug + "/" + slug`.
     * Optional — historical manifests written before W0287 only carry
     * `slug`; downstream `DocumentRef` builders fall back to slug-only
     * display when this is absent.
     */
    path?: string;
    title: string;
}
/** Impact of a content release on canonical documents */
export interface ReleaseImpact {
    added: string[];
    modified: string[];
    removed: string[];
    unchanged: string[];
    /**
     * Slugs versioned in the release but NOT canonical docs of any in-scope
     * task — release edits that fall outside the evaluated set, so their
     * effect is never measured. The `added`/`modified`/`unchanged`/`removed`
     * fields are scoped to the in-scope canonical set by construction (the
     * perspective diff only sees those slugs); this field is the complementary
     * view computed over the full `sanity::partOfRelease` footprint, so an
     * applied fix to a doc no task references is reported rather than silently
     * dropped.
     *
     * Optional and three-valued by presence: absent when no source-level
     * release perspective was active (or the footprint query could not run);
     * an empty array means "checked — every release-modified doc is covered";
     * a non-empty array names the unmeasured docs.
     */
    uncovered?: string[];
}
/** Summary of document overlay operations */
export interface DocumentOverlaySummary {
    appendedCount: number;
    documentIds: string[];
    replacedSlugs: string[];
}
/** Metadata for a single URL fetch result */
export interface UrlFetchEntry {
    contentLength?: number;
    error?: string;
    method: string;
    status?: number;
    url: string;
}
/** Summary of URL fetch operations */
export interface UrlFetchSummary {
    failures: {
        error?: string;
        url: string;
    }[];
    fetchedUrls: UrlFetchEntry[];
    totalFailed: number;
    totalFetched: number;
}
/**
 * Expansion of task-level perspective doc refs, resolved during fetch.
 *
 * `PerspectiveDocRef`s expand one-to-many ("all articles versioned in
 * release X") only at fetch time, so the orchestration step cannot know
 * the expanded slugs up front. The fetcher returns the expansion here so
 * release auto-scope attribution can map perspective-expanded slugs back
 * to their owning tasks instead of silently skipping a task whose
 * canonical docs come only from a perspective ref.
 *
 * Plain `Record`s (not `Map`s) so the metadata stays JSON-serializable
 * alongside the other `FetchMetadata` fields.
 */
export interface PerspectiveExpansion {
    /** Release/perspective ID → article slugs expanded from that release */
    slugsByPerspective: Record<string, string[]>;
    /** Task ID → perspective IDs the task referenced via `PerspectiveDocRef` */
    perspectivesByTask: Record<string, string[]>;
}
/**
 * A failed fetch of a single resource — source-agnostic. Adapters that
 * support partial-failure mode populate this on `FetchMetadata.fetchFailures`
 * so the run completes with the successes and records the failures.
 */
export interface FetchFailure {
    /** Stable identifier for the failed resource (URL, Drive web URL, future-adapter id). */
    resource: string;
    /** Error message. */
    error: string;
    /** HTTP/API status code, when applicable. */
    status?: number;
    /**
     * Task this failure attributes to, when the adapter knows the binding.
     * Lets downstream consumers (grading, run-summary) distinguish "the
     * model ignored its docs" from "the fetcher couldn't read this task's
     * docs" without re-deriving the mapping. Optional — some failures
     * (e.g. folder-list errors before per-task expansion) aren't
     * attributable to a single task.
     */
    taskId?: string;
}
/**
 * Per-task entry in the symbol-reference index manifest (W0197).
 *
 * One entry is emitted per task that the fetcher processed, regardless of
 * whether extraction yielded any symbols. The grader-context consumer
 * uses `symbolCount > 0` to decide between symbol-index and full-doc
 * injection — distinguishing "extraction ran and produced nothing"
 * (entry present, count zero — observable fallback) from "fetcher hadn't
 * run with W0197" (no entry — silent fallback).
 */
export interface SymbolIndexManifestEntry {
    taskId: string;
    /** Repo-relative path to the per-task index artifact. */
    path: string;
    /** Total deduped symbols in the index (post-merge). */
    symbolCount: number;
    /** Per-tier breakdown for observability. */
    tierBreakdown: {
        typeDef: number;
        heading: number;
        inlineCode: number;
        codeBlock: number;
    };
}
/** Metadata about the fetch operation, for downstream pipeline consumption */
export interface FetchMetadata {
    /** Document manifest for traceability (slug, _id, _rev, title) */
    manifest?: DocumentManifestEntry[];
    /** Release impact from perspective diffing */
    releaseImpact?: ReleaseImpact;
    /** Document overlay operations summary */
    documentOverlay?: DocumentOverlaySummary;
    /** URL fetch operations summary */
    urlFetch?: UrlFetchSummary;
    /**
     * Per-task symbol-index manifest (W0197). Always populated when the
     * fetcher emits per-task index artifacts; the in-memory copy mirrors
     * the on-disk `contexts/canonical-symbols/manifest.json`.
     */
    symbolIndexes?: SymbolIndexManifestEntry[];
    /**
     * Expansion of task-level perspective doc refs (one-to-many, resolved
     * during fetch). Optional: only present when the fetched task set
     * contained at least one `PerspectiveDocRef`; adapters that do not
     * support perspective refs simply omit it.
     */
    perspectiveExpansion?: PerspectiveExpansion;
    /**
     * Per-resource fetch failures, source-agnostic. Populated by any adapter
     * that supports partial-failure mode. Serialized to
     * `contexts/fetch-failures.json` by `fetch-docs-step.ts` when non-empty.
     */
    fetchFailures?: FetchFailure[];
}
/** Complete result of a doc fetch operation */
export interface FetchResult {
    /** Per-task documentation contexts */
    contexts: DocContext[];
    /** Optional metadata about the fetch (manifests, impact, overlays, URLs) */
    metadata?: FetchMetadata;
}
/**
 * Port: Where documentation context comes from.
 *
 * The pipeline never knows HOW docs are fetched — it only sees
 * FetchResult. The adapter handles GROQ queries, Portable Text
 * conversion, URL fetching, perspective diffing, document overlays, etc.
 */
export interface DocFetcher {
    /**
     * Fetch documentation context for a set of tasks.
     *
     * The adapter:
     * 1. Collects unique slugs from tasks' canonicalDocs
     * 2. Fetches documents from the source (with perspective/overlay support)
     * 3. Converts to markdown
     * 4. Assembles per-task context (combining all canonical docs + overlays)
     * 5. Writes context files to disk (for Promptfoo consumption)
     * 6. Returns structured metadata (manifest, release impact, etc.)
     *
     * @param tasks — Task definitions with canonical doc references
     * @param source — Where to fetch documentation from
     * @returns Fetched doc contexts + optional metadata
     */
    fetch(tasks: GeneralizedTaskDefinition[], source?: DocSourceConfig): Promise<FetchResult>;
}
