/**
 * Judge-ensemble reducer — folds N independent judge verdicts on the same
 * artifact into one aggregate score.
 *
 * The pattern every multi-model judge re-implements: run K uncorrelated judges
 * (different model families remove within-family bias), then reduce their
 * per-dimension verdicts to a single composite + an inter-rater disagreement
 * signal. This is the pure reduction — no LLM, no I/O — so a lift it produces
 * is attributable to the scores, not to where they came from.
 *
 * Fail-loud: a judge that errored or returned malformed output is recorded in
 * `failedJudges` with `perDimension: null`, never folded into a zero. If EVERY
 * judge failed the reducer throws — a silent zero here would corrupt the gate's
 * number. A failed judge still burned tokens, so its `costUsd` is still summed.
 */
/** One judge's verdict. `perDimension: null` ⇒ that judge call failed (threw or
 *  returned malformed output) — recorded, never folded into a zero. */
export interface JudgeVerdict<D extends string = string> {
    /** Judge identity (typically the model id) — the `perJudge` / `failedJudges` key. */
    model: string;
    /** Per-dimension scores, or `null` when the judge failed. */
    perDimension: Record<D, number> | null;
    /** Optional one-line rationale; the first non-empty one becomes the aggregate's. */
    rationale?: string;
    /** Optional reported cost — summed across ALL verdicts (failed included). */
    costUsd?: number;
    /** Optional per-dimension reasoning/evidence. Carried through to
     *  `EnsembleAggregate.verdicts` verbatim — never folded into the math. */
    detail?: Partial<Record<D, {
        reasoning?: string;
        evidence?: string;
    }>>;
}
/** The aggregated ensemble result. */
export interface EnsembleAggregate<D extends string = string> {
    /** Mean over SURVIVING judges, per dimension (absent-everywhere ⇒ 0). */
    perDimension: Record<D, number>;
    /** Weighted mean of `perDimension` (uniform unless `weights` given). */
    composite: number;
    /** Each surviving judge's clamped per-dimension scores, for trace drill-down. */
    perJudge: Record<string, Record<D, number>>;
    /** Max over dimensions of (max − min) across survivors — the inter-rater signal. */
    maxDisagreement: number;
    /** Models whose verdict was null (failed). */
    failedJudges: string[];
    /** Sum of `costUsd` over ALL verdicts, failed included. */
    costUsd: number;
    /** First non-empty survivor rationale, or `'llm-judge'`. */
    rationale: string;
    /** The input verdicts, verbatim — drill-down to raw scores, `detail`
     *  reasoning/evidence, and per-verdict cost without re-running judges. */
    verdicts: JudgeVerdict<D>[];
}
/**
 * Reduce per-judge verdicts to one aggregate. Generic over the rubric: pass the
 * stable-ordered `dimensionKeys` the judges scored.
 *
 * - Per-dimension score = mean over surviving judges (out-of-range clamped to [0,1]).
 * - `composite` = `weightedComposite` of `perDimension`. No `weights` ⇒ uniform
 *   over every dimension. A partial `weights` map selects AND weights exactly the
 *   named dimensions (others excluded from the composite) — the substrate's
 *   sum-normalized weighting, not re-implemented here.
 * - Throws if `verdicts` or `dimensionKeys` is empty, or if every judge failed.
 */
export declare function aggregateJudgeVerdicts<D extends string>(verdicts: readonly JudgeVerdict<D>[], dimensionKeys: readonly D[], weights?: Partial<Record<D, number>>): EnsembleAggregate<D>;
//# sourceMappingURL=judge-ensemble.d.ts.map