/**
 * Adaptive curriculum / active scenario selection.
 *
 * Fixed scenario sets waste sample budget on cells the policy already
 * passes (no information left) and cells the policy never passes (no
 * gradient available either). Active learning over scenarios fixes this
 * by allocating the next sample budget to cells where the policy's
 * outcome is *uncertain* — those carry the most decision-relevant signal.
 *
 * This module ships two complementary strategies:
 *
 *   1. **Variance-based** — score each (variant, scenario) cell by the
 *      empirical variance of past observations. Allocate next-round budget
 *      proportional to variance. Standard active-learning-by-uncertainty
 *      heuristic; works well when the policy is non-deterministic and
 *      cells differ in observation noise.
 *
 *   2. **Bandit-based (Thompson sampling)** — model each (variant,
 *      scenario) cell as a Beta-Bernoulli arm; sample a posterior; pick
 *      cells whose posterior mean is closest to the per-scenario decision
 *      threshold. The right primitive when scenarios are
 *      "pass/fail" rather than continuous, and when promotion gates fire
 *      at a known threshold (e.g., 0.5).
 *
 * The output is a *next-round budget allocation* — a list of (variant,
 * scenario, count) triples. The consumer's matrix runner consumes the
 * allocation, runs those cells, feeds the new observations back. Loop.
 *
 * Out of scope (deliberate): scenario *generation* — that's the
 * adversarial primitive's job. This module allocates over an existing
 * scenario pool.
 */
import type { RunRecord } from '../run-record';
export interface CellObservation {
    variantId: string;
    scenarioId: string;
    /** Observed score in [0, 1]. */
    score: number;
    /** For Bernoulli arms — derive from the score with a threshold if needed. */
    pass?: boolean;
}
export interface CurriculumAllocation {
    variantId: string;
    scenarioId: string;
    /** How many additional reps to run on this cell. */
    count: number;
    /** Strategy-specific reason for the allocation. */
    reason: string;
}
export interface VarianceCurriculumOptions {
    /** Total reps to allocate across all cells. */
    budget: number;
    /**
     * Smoothing prior on variance — keeps the allocator from concentrating
     * on a cell with one observation just because its 1-sample variance is
     * 0. Default 0.05.
     */
    variancePrior?: number;
    /**
     * Minimum reps per cell — even when the variance estimate is low, give
     * every cell at least this many. Default 1.
     */
    floorPerCell?: number;
}
/**
 * Variance-proportional allocation. For each cell, estimate variance from
 * past observations + a prior, then allocate the budget proportional to
 * (sqrt(variance) + 1/sqrt(n)) — a classical optimal-allocation rule
 * (Neyman 1934) that balances "explore noisy cells" with "explore
 * under-sampled cells."
 */
export declare function varianceBasedCurriculum(observations: CellObservation[], candidateCells: Array<{
    variantId: string;
    scenarioId: string;
}>, opts: VarianceCurriculumOptions): CurriculumAllocation[];
export interface ThompsonCurriculumOptions {
    budget: number;
    /**
     * The per-scenario decision threshold. Cells whose posterior mean is
     * closest to this get the most budget — that's where the next observation
     * has the highest information value for the gate decision. Default 0.5.
     */
    decisionThreshold?: number;
    /** Beta prior parameters. Default α=β=1 (uniform). */
    priorAlpha?: number;
    priorBeta?: number;
    /** Seed the Thompson sampler. Default unset (Math.random). */
    seed?: number;
}
/**
 * Thompson-sampling-style allocation for pass/fail cells. For each cell:
 *
 *   - Maintain Beta(α + passes, β + failures) posterior on pass-rate
 *   - Allocation weight ∝ exp(-((sampledMean - threshold) / σ)^2):
 *     cells whose sampled posterior straddles the decision boundary get
 *     the most weight; cells already clearly above or below get less.
 *
 * This is the right primitive when promotion gates fire at a known
 * threshold and you want to sharpen the posterior near the boundary.
 */
export declare function thompsonCurriculum(observations: CellObservation[], candidateCells: Array<{
    variantId: string;
    scenarioId: string;
}>, opts: ThompsonCurriculumOptions): CurriculumAllocation[];
/** Convenience: extract `CellObservation[]` directly from `RunRecord[]`. */
export declare function observationsFromRunRecords(runs: RunRecord[], opts?: {
    passThreshold?: number;
    useHoldout?: boolean;
}): CellObservation[];
//# sourceMappingURL=active-curriculum.d.ts.map