/**
 * ADR-121 Phase 20 — Lazy/short-circuit adaptive router (BEYOND SOTA).
 *
 * Phase 16's adaptive router demands all three signal inputs upfront:
 * top-N candidates (needs question embed + dense search), variant
 * vectors (needs N variant embeds), hypothetical vectors (needs N
 * hypothetical embeds). The router was correct but expensive — the
 * Phase 19 ablation showed a 23% cost overhead vs running compound
 * directly, because feature extraction is unconditional.
 *
 * This module ships the missing optimization: **incremental feature
 * extraction with short-circuit decisions**. Signals are extracted
 * in a deliberate order, and the router stops embedding as soon as
 * a routing decision is reachable.
 *
 * Order of evaluation (cheapest signal first):
 *
 *   1. Always embed the question (1 embed). Run plain top-k for
 *      candidate-density. Cost so far: 1 embed + 1 search.
 *      - If duplicateDensity > dupT → fire MMR. Done.
 *
 *   2. Else embed the variants (N variant embeds).
 *      - If queryIntentCohesion < intentT → fire RRF. Done.
 *
 *   3. Else embed the hypotheticals (M hypothetical embeds).
 *      - If qaSpaceGap > gapT → fire HyDE. Done.
 *
 *   4. Else → fire plain (no signals fired).
 *
 *   5. Compound: if at any step >=2 signals have already fired AND
 *      `preferCompound` is true → upgrade to compound. This requires
 *      ALL embeds (same cost as Phase 16), but compound was always
 *      expensive — that's expected.
 *
 * Quality equivalence: lazy and eager routers produce the SAME
 * decision when run on the same inputs. The lazy router just pays
 * less to compute features it doesn't end up needing. (Verified by
 * a per-query equivalence test.)
 *
 * Cost reduction: dominated by the workload's "easy" fraction —
 * queries where the first cheap signal already fires never pay for
 * variant/hypothetical embeds. On a workload split 50/50 easy/hard,
 * lazy saves ~40% of variant+hypothetical embeds.
 */
import { type AdaptiveRouterOptions, type AdaptiveDecision } from './adaptive-router.js';
export interface LazyEmbedAdapter {
    /** Embed a single text. Returns the L2-normalized vector. */
    readonly embed: (text: string) => Promise<Float32Array | number[]>;
}
export interface LazyCandidateSource {
    /**
     * Return top-k nearest neighbors to the supplied query vector.
     * Hits must include `vector` so the router can compute the
     * duplicate-density signal.
     */
    readonly topK: (queryVec: Float32Array | number[], k: number) => Promise<ReadonlyArray<{
        id: string;
        vector: Float32Array | number[];
        score?: number;
    }>>;
}
export interface LazyRouterInputs {
    /** The user's question text. */
    readonly queryText: string;
    /** Query reformulation variants (without the original question). */
    readonly variantTexts: ReadonlyArray<string>;
    /** Hypothetical-answer texts for HyDE-style features. */
    readonly hypotheticalTexts: ReadonlyArray<string>;
}
export interface LazyRouterCostReport {
    /** Number of embed calls actually made. */
    readonly embedsUsed: number;
    /** Number of embeds that would have been made by the eager router. */
    readonly embedsEager: number;
    /** Number of embeds saved by short-circuiting (>= 0). */
    readonly embedsSaved: number;
    /** Which signal-extraction steps were skipped. */
    readonly skippedSteps: ReadonlyArray<'variants' | 'hypotheticals'>;
}
export interface LazyRouterResult {
    /** The routing decision (same shape as Phase 16's adaptiveRoute). */
    readonly decision: AdaptiveDecision;
    /** Cost accounting for the lazy run. */
    readonly cost: LazyRouterCostReport;
    /**
     * Already-computed embeddings the caller can reuse for the
     * downstream primitive call. Avoids re-embedding when the lazy
     * pass already paid for these.
     */
    readonly cached: {
        readonly queryVector: Float32Array | number[];
        readonly topCandidates: ReadonlyArray<{
            id: string;
            vector: Float32Array | number[];
            score?: number;
        }>;
        readonly variantVectors: ReadonlyArray<Float32Array | number[]>;
        readonly hypotheticalVectors: ReadonlyArray<Float32Array | number[]>;
    };
}
/**
 * Run the lazy/short-circuit adaptive router.
 *
 * Returns the same decision the eager router would produce, plus a
 * cost report showing which embeds were skipped, plus the cached
 * intermediate vectors the caller can reuse for the downstream
 * primitive call.
 */
export declare function lazyAdaptiveRoute(embedder: LazyEmbedAdapter, candidates: LazyCandidateSource, inputs: LazyRouterInputs, options?: AdaptiveRouterOptions & {
    readonly topKForFeatures?: number;
}): Promise<LazyRouterResult>;
//# sourceMappingURL=lazy-adaptive-router.d.ts.map