import type { DimensionResult, ExecutorFn, JudgeAgreement, JudgeConfig, ToolCallInfo, TurnInfo } from '../types/index.js'; export { buildJudgePrompt, getJudgePromptHash } from '../shared/llm-prompts/judge-prompts.js'; interface LlmJudgeOptions { output: string; rubric: string; prompt: string; executor: ExecutorFn; model: string; traceSummary?: string | null; /** * When true (default), the judge prompt includes an explicit * "length is not a quality signal" instruction. Pass false to drop it (the * debias-off prompt variant) — only useful for reproducing older no-length-debias * reports or running A/B comparisons with alternate length-debias settings. * (The presentation/tone neutrality instruction is always on, independent of this.) */ lengthDebias?: boolean; } export declare function buildTraceSummary(turns?: TurnInfo[], toolCalls?: ToolCallInfo[]): string | null; export declare function llmJudge({ output, rubric, prompt, executor, model, traceSummary, lengthDebias }: LlmJudgeOptions): Promise; /** * Judge a single (output, rubric) pair N times and aggregate. Returns mean score, * stddev across runs, raw score samples, and the first-call reasoning (we keep one * reasoning sample, not N — only the score distribution matters for stability). * * Calls run with bounded concurrency (JUDGE_REPEAT_CONCURRENCY) to amortize latency * without burning rate limit. N=3 finishes in ~1 round-trip; N=10 in ~4. Cost is * summed across all N calls. When N <= 1 this is equivalent to llmJudge() with * scoreSamples = [score], scoreStddev = 0. The repeat value is clamped to >= 1 * here as well as at the CLI layer — library callers shouldn't see surprises. * * Failures: any call returning score=0 (non-JSON / executor error / parse error) is * counted in `judgeFailureCount`. stddev is computed only over successful calls. If * stddev is 0 but judgeFailureCount > 0, that's NOT "judge agreed perfectly" — it * means most calls failed and one happened to succeed. Always inspect both fields. */ export declare function llmJudgeRepeat(options: LlmJudgeOptions, repeat: number): Promise; /** Format a JudgeConfig as "executor:model" identifier for reports / logs. */ export declare function judgeId(config: JudgeConfig): string; /** * Compute pairwise inter-judge agreement metrics across an ensemble. For N judges * we get N*(N-1)/2 pairs; metrics are pairwise-averaged. * * Each judge contributes ONE score per sample (its mean if judge-repeat > 1). We * then compute Pearson and mean-abs-diff over the N-judge × M-sample score matrix. * * NOTE: Within a single (sample × dimension) call, each judge gives ONE aggregated * score. So `pairwise` here means "two judges' scores on this one sample". With a * single sample point Pearson is undefined (need ≥ 2). For per-sample agreement we * fall back to mean-abs-diff alone; Pearson kicks in at the report-aggregate level * (across many samples). */ export declare function computeJudgeAgreement(judgeScores: number[][]): JudgeAgreement; /** * Judge a single (output, rubric) pair with N judge models in parallel. Each judge * may use a different executor (e.g. claude:opus + openai-api:gpt-4o + gemini:pro). Each * judge can also be repeated `judgeRepeat` times — final per-judge score is its mean. * * Returns: aggregate DimensionResult (score = mean across judges; this is the "consensus" * score), per-judge breakdown in `ensemble`, and agreement metrics in `agreement`. * * The aggregate score is the mean of per-judge scores. This is a defensible default * but not the only choice — one could argue median (robust to outlier judges) or * majority vote (if scores are categorical). Mean is what most papers report; we * provide the raw ensemble so downstream can recompute. */ export declare function llmJudgeEnsemble(options: LlmJudgeOptions, judges: JudgeConfig[], executorByName: (name: string) => ExecutorFn, judgeRepeat?: number): Promise;