/**
 * Scoring Pipeline: Stage 1 (Semantic + Frequency), Grammar Filter, Stage 2 (LM Re-ranking).
 *
 * Operates synchronously on pre-loaded data. Each stage gracefully degrades
 * when its required data isn't available (cold → warm → full warm).
 */
export interface ScoringCandidate {
    authorFreq: number;
    docFreq: number;
    sessionFreq: number;
    tenantFreq: number;
    word: string;
}
export interface ScoredCandidate {
    finalScore: number;
    freqScore: number;
    lmScore: number;
    semanticScore: number;
    word: string;
}
/** Metadata returned by the grammar filter for debug logging in the caller. */
export interface GrammarFilterMeta {
    after: number;
    before: number;
    dropped: string[];
    prevTags: string[];
    prevWord: string;
}
export declare const STAGE1_WEIGHT = 0.35;
export declare const STAGE2_WEIGHT = 0.65;
export declare const MIN_STAGE1_SCORE = 0.35;
export interface PipelineDebug {
    final: number;
    grammarRejected: string[];
    initial: number;
    stage1Rejected: string[];
}
export interface RankCandidatesResult {
    candidates: ScoredCandidate[];
    grammarMeta: GrammarFilterMeta | null;
    pipelineDebug: PipelineDebug;
}
export declare function rankCandidates(candidates: ScoringCandidate[], contextVector: Float32Array | null, getWordVector: (word: string) => Float32Array | null, lmLogits: Record<string, number> | null, maxTenantFreq: number, previousWord: string): RankCandidatesResult;
