/**
 * ADR-121 Phase 11 — Reciprocal Rank Fusion (RRF).
 *
 * When you have N ranked result lists for the same query (or for N
 * variants of the same intent) — e.g. from a question-reformulation
 * pipeline, from a hybrid lexical+vector search, or from multiple
 * embedding models — RRF combines them into a single fused ranking
 * without needing the underlying scores to be comparable.
 *
 * Cormack, Clarke, Büttcher (SIGIR 2009):
 *
 *   RRF_score(item) = Σ over lists i where item appears:  1 / (k_rrf + rank_i)
 *
 * where rank_i is the item's 1-based position in list i and k_rrf is a
 * small constant (the original paper recommends 60 — small enough that
 * top results dominate, large enough that mid-list ranks still
 * contribute). The score is heuristic but practically excellent: RRF
 * consistently matches or beats supervised learning-to-rank in TREC
 * evaluations despite needing zero training data.
 *
 * This module ships the algorithm as a pure function so callers can
 * compose it with any source of ranked lists — AnnRouter results,
 * lexical search, MMR-reranked picks, etc. The CLI's
 * `embeddings_search_text_ensemble` tool composes
 * `search_text_batch` + `reciprocalRankFusion` for the common case of
 * "expand one user query into N variants, retrieve top-k for each,
 * fuse to a single ranking".
 */
export interface RrfListItem {
    /** Caller-supplied identifier. Items with the same id across lists are fused. */
    readonly id: string;
    /** Free-form payload — preserved from the FIRST list this item appears in. */
    readonly payload?: unknown;
}
export interface RrfOptions {
    /** Number of fused results to return. Clamped to total unique items. */
    readonly k: number;
    /**
     * RRF smoothing constant. Default 60 (the SIGIR 2009 recommendation).
     * Smaller k_rrf → top-ranked items dominate more sharply.
     * Larger k_rrf → flatter contribution from each list, more like simple
     * vote-counting.
     */
    readonly kRrf?: number;
    /** Optional per-list weights. Default = 1 for every list. */
    readonly listWeights?: ReadonlyArray<number>;
}
export interface RrfFusedHit {
    readonly id: string;
    readonly payload?: unknown;
    /** Final fused RRF score (higher = better). */
    readonly score: number;
    /**
     * Per-list contribution: the 1-based rank in each list the item
     * appeared in. Length === number of input lists. `null` means the
     * item didn't appear in that list.
     */
    readonly ranks: ReadonlyArray<number | null>;
    /** Number of lists the item appeared in. */
    readonly listOccurrences: number;
}
/**
 * Iterative RRF over N ranked lists. Time complexity:
 *   O(N · L) where N = number of lists, L = avg list length
 *
 * Lists are 1-indexed inside the formula (first item = rank 1).
 */
export declare function reciprocalRankFusion(lists: ReadonlyArray<ReadonlyArray<RrfListItem>>, options: RrfOptions): RrfFusedHit[];
/**
 * Convenience: same as reciprocalRankFusion but returns just the fused
 * ids in rank order.
 */
export declare function rrfIds(lists: ReadonlyArray<ReadonlyArray<RrfListItem>>, options: RrfOptions): string[];
//# sourceMappingURL=rrf.d.ts.map