/**
 * Adversarial scenario search.
 *
 * Capability evaluation on a fixed scenario set measures performance on
 * the distribution someone curated. Production failure modes live in the
 * tail — inputs the curator didn't think of, or actively avoided. The
 * adversarial-search primitive actively looks for them: starting from a
 * pool of scenarios where the policy already passes, it mutates them
 * (paraphrase, edge-case substitution, compositional combination) and
 * keeps the mutations that *break* the policy.
 *
 * This is not magic. It's the simplest version of the loop that AdA
 * (Open-Ended Adaptation, DeepMind 2023), POET, and Anthropic's
 * auto-jailbreak rigs all run: hill-climb against a failure indicator,
 * keep the survivors, repeat. We ship the harness; consumers supply the
 * mutation strategies and the failure detector.
 *
 * Why ship this in agent-eval and not as a separate red-team tool: every
 * piece of the standard adversarial loop is already in this package
 * (`runEvalCampaign` for the matrix run, `RawProviderSink` for capture,
 * `assertRunCaptured` for integrity, `pairedEvalueSequence` for stop
 * criteria). The adversarial primitive is just the *scenario-mutation
 * meta-loop* on top of that machinery.
 */
interface AdversarialScenario<S> {
    /** Stable id — used for deduplication and lineage tracking. */
    id: string;
    /** Generation index — 0 for seeds, 1 for first round of mutations, etc. */
    generation: number;
    /** Lineage — id of the parent scenario this was mutated from, if any. */
    parentId: string | null;
    scenario: S;
    /** Score on the policy under test. Lower = adversarial signal. */
    score: number | null;
    /** Strategy that produced this mutation, for diagnostics. */
    mutationStrategy: string | null;
}
interface AdversarialMutation<S> {
    id: string;
    /**
     * Mutate one scenario. Return null to skip; return one or more new
     * scenarios. The harness deduplicates by `mutateScenarioId(scenario)`.
     */
    mutate(parent: S, rng: () => number): Promise<S[]> | S[];
}
interface AdversarialSearchOptions<S> {
    /** Initial scenarios — typically those the policy currently passes. */
    seeds: S[];
    /** Stable identifier extraction. */
    mutateScenarioId: (s: S) => string;
    /** Mutation strategies. */
    mutations: AdversarialMutation<S>[];
    /**
     * Run the policy under test against one scenario, return a scalar score
     * in [0, 1]. Lower = adversarial signal.
     */
    scoreFn: (s: S) => Promise<number>;
    /**
     * Threshold below which a scenario counts as a "failure" worth keeping.
     * Default 0.5.
     */
    failureThreshold?: number;
    /** Number of mutation rounds. Default 3. */
    rounds?: number;
    /** Children per parent per round. Default 4. */
    childrenPerParent?: number;
    /** Maximum total scenarios examined. Default Infinity. */
    budget?: number;
    /** Seed for the deterministic RNG. Default 1. */
    seed?: number;
}
interface AdversarialSearchReport<S> {
    scenarios: AdversarialScenario<S>[];
    /** Discovered failures sorted by score ascending. */
    failures: AdversarialScenario<S>[];
    /** Round-by-round counts. */
    byGeneration: Array<{
        generation: number;
        total: number;
        failures: number;
        meanScore: number;
    }>;
    /** Total scoreFn invocations consumed. */
    scoreCalls: number;
}
declare function adversarialScenarioSearch<S>(opts: AdversarialSearchOptions<S>): Promise<AdversarialSearchReport<S>>;

export { type AdversarialMutation as A, type AdversarialScenario as a, type AdversarialSearchOptions as b, type AdversarialSearchReport as c, adversarialScenarioSearch as d };
