/**
 * SanityDocFetcher — full adapter for the DocFetcher port.
 *
 * Fetches documentation from the Sanity Content Lake with support for:
 * - Basic slug-based fetching (GROQ → Portable Text → Markdown)
 * - Perspective-aware fetching (content release diffing)
 * - Document overlays (replace/append canonical docs by document ID)
 * - Direct URL fetching (markdown endpoints + content negotiation)
 * - Custom HTTP headers
 * - Document manifest (traceability: _id, _rev, slug, title)
 * - Release impact metadata (added/modified/removed/unchanged)
 *
 * The pipeline step (FetchDocsStep) calls ctx.docFetcher.fetch() and
 * writes the returned metadata to disk for downstream consumption.
 */
import { type DocFetcher, type DocSourceConfig, type FetchResult, type GeneralizedTaskDefinition, type IdDocRef, type PathDocRef, type PerspectiveDocRef, type PerspectiveExpansion, type ProductFeature, type SlugDocRef } from "../../_vendor/ailf-core/index.d.ts";
/** Sanity Content Lake source — narrows `DocSourceConfig.kind` to its literal. */
export interface SanityContentLakeSource extends DocSourceConfig {
    kind: "sanity-content-lake";
}
/** Sanity-tagged variants of core's four ref interfaces. */
export type TaggedSlugDocRef = SlugDocRef & {
    kind?: "sanity-slug";
};
export type TaggedPathDocRef = PathDocRef & {
    kind?: "sanity-path";
};
export type TaggedIdDocRef = IdDocRef & {
    kind?: "sanity-id";
};
export type TaggedPerspectiveDocRef = PerspectiveDocRef & {
    kind?: "sanity-release-perspective";
};
/**
 * The ref union the Sanity adapter accepts. Untagged refs (legacy form) still
 * satisfy each variant because `kind` is optional at core.
 */
export type SanityDocRef = TaggedSlugDocRef | TaggedPathDocRef | TaggedIdDocRef | TaggedPerspectiveDocRef;
/**
 * Build the `FetchMetadata.perspectiveExpansion` envelope from the
 * collected perspective refs and their fetch-time slug expansion.
 *
 * Perspective doc refs expand one-to-many only during fetch, so this is
 * the single point where the expansion (release → slugs) and the
 * attribution (task → releases) are both known. Returning them together
 * lets the orchestration step attribute perspective-expanded slugs back
 * to their owning tasks during release auto-scope computation.
 *
 * Exported for unit testing.
 */
export declare function buildPerspectiveExpansion(perspectiveRefs: {
    perspective: string;
    taskId: string;
}[], perspectiveToSlugs: Map<string, string[]>): PerspectiveExpansion;
/** Optional construction-time collaborators for SanityDocFetcher. */
export interface SanityDocFetcherOptions {
    /**
     * Product feature registry powering the perspective-pin relatedness
     * guard (section→area mapping). When omitted, the guard still warns on
     * empty expansions but skips the area-relatedness assessment.
     */
    features?: ProductFeature[];
}
export declare class SanityDocFetcher implements DocFetcher {
    private readonly rootDir;
    private readonly features;
    /**
     * Per-URL cache of attachment-body fetches. A single `typesReference` doc is
     * now fetched once for the grader symbol index and again for each task that
     * renders it (relevance-scoped per D0069 §5), so without this a 658 KB
     * typedoc would be downloaded N+1 times per run. Sanity file-asset URLs are
     * content-addressed (the asset id is in the path), so a cached body never
     * goes stale. The promise is cached so concurrent callers dedupe too. A
     * failed fetch resolves to `null` (never rejects) and is also memoized, so a
     * transient failure fails fast for the whole run rather than re-downloading.
     */
    private readonly attachmentBodyCache;
    constructor(rootDir: string, options?: SanityDocFetcherOptions);
    fetch(tasks: GeneralizedTaskDefinition[], source?: DocSourceConfig): Promise<FetchResult>;
    private fetchInternal;
    private fetchManifest;
    /**
     * Warn when a bare `slug` ref resolves to more than one published article.
     *
     * The by-slug content fetch (`ARTICLE_BY_SLUG_QUERY`, `...[0]`) can only
     * return the first match, so a colliding legacy slug ref silently injects an
     * arbitrary winner. Naming the candidate `_id`s surfaces the ambiguity so the
     * ref can be pinned to an id — the collision-safe path id refs already take.
     * Id-resolved slugs are excluded: those refs already name a specific
     * document, so their slug appearing on multiple articles is expected and not
     * a warning.
     */
    private warnOnAmbiguousSlugRefs;
    /**
     * Batch-resolve document ID refs without filtering on `_type`.
     *
     * Articles are routed back into the slug-flow (so manifest, perspective
     * diffing, and overlay handling continue to work unchanged). Non-articles
     * are rendered eagerly via the renderer registry — `typesReference` gets
     * a high-fidelity formatter; anything else falls through to the default
     * walker so authors can pin marketing pages, glossary entries, etc.
     * without an AILF code change.
     *
     * Three log shapes:
     *   - `info` — doc rendered with the default formatter (suggests a
     *     dedicated renderer would improve fidelity)
     *   - `warn` — registered renderer produced empty content (W0195 AC#3)
     *   - `warn` — id had no matching document (existed/wrong tenant/typo)
     */
    private resolveIdRefs;
    /**
     * Fetch the raw body of a Sanity file asset URL, used by the
     * `typesReference` renderer to inline typedoc JSON. Returns `null`
     * on any HTTP/network failure rather than throwing — the renderer
     * surfaces a placeholder so the rest of the context still renders.
     *
     * Wrapped in a 30s `AbortSignal.timeout` so a slow CDN can't hang the
     * eval pipeline indefinitely. Timeouts surface as a single `null`
     * return like any other fetch failure. Results are memoized per URL (see
     * `attachmentBodyCache`).
     */
    private fetchAttachmentBody;
    private fetchAttachmentBodyUncached;
    /**
     * Resolve path-based canonical doc references to their article slugs.
     *
     * Handles two path formats:
     * - Simple path: "webhooks" → resolves as slug lookup
     * - Section-qualified path: "content-lake/webhooks" → matches section + slug
     *
     * @see docs/design-docs/canonical-doc-resolution.md
     */
    private resolvePathRefsToSlugs;
    /**
     * Expand perspective canonical doc refs to the article slugs within
     * each content release.
     *
     * Each perspective ref resolves to ALL article documents versioned in
     * that release. This is the one-to-many expansion described in the
     * canonical-doc-resolution design doc.
     *
     * The perspective value from the ref is used as both the release ID
     * for the versioned document query AND the client perspective for
     * fetching content. If a source-level perspective is also set, the
     * ref-level perspective takes precedence for its own resolution.
     *
     * Expansion is intentionally unconditional; a stale or unrelated pin is
     * surfaced through the non-fatal {@link warnOnSuspectPerspectivePin}
     * guard rather than gating the fetch.
     *
     * @see docs/design-docs/canonical-doc-resolution.md
     */
    private resolvePerspectiveRefsToSlugs;
    /**
     * Non-fatal stale-pin guard for one perspective ref expansion.
     *
     * Warns when the pinned release expanded to no articles (release gone,
     * published, or empty) or when the expanded articles' sections are
     * unrelated to the pinning task's area per the feature-registry
     * section→area mapping (see {@link buildPerspectivePinWarnings}).
     * Warning only — expansion remains unconditional and the fetch never
     * fails because of a suspect pin.
     */
    private warnOnSuspectPerspectivePin;
    private identifyAffectedDocs;
    /**
     * Compute the slugs versioned in the release that are NOT canonical docs of
     * any in-scope task, via the full `sanity::partOfRelease` footprint.
     *
     * Returns `undefined` (not `[]`) when the footprint query fails, preserving
     * the three-valued `ReleaseImpact.uncovered` contract: absent = not computed,
     * `[]` = checked and fully covered, non-empty = unmeasured docs named.
     */
    private identifyUncoveredReleaseDocs;
    private resolveDocumentOverlay;
    private fetchArticleById;
    private fetchArticleBySlug;
    private fetchArticleBySlugWithPerspective;
    private fetchCanonicalDocs;
    /**
     * Generate feature-area context files (one per GROQ feature area query).
     *
     * This is NOT part of the DocFetcher port — it's an opt-in CLI feature
     * used by `ailf fetch-docs --include-feature-areas`.
     */
    fetchFeatureAreaContexts(source?: DocSourceConfig): Promise<void>;
    /**
     * Generate a full corpus context file (all articles in one markdown file).
     *
     * This is NOT part of the DocFetcher port — it's an opt-in CLI feature
     * used by `ailf fetch-docs --include-corpus`.
     */
    fetchFullCorpus(source?: DocSourceConfig): Promise<void>;
}
