/**
 * Validator-output verdict — substrate primitive for "did this output pass,
 * and how well?"
 *
 * Used by:
 *   - `@tangle-network/agent-eval/matrix` — verdict per cell in the cartesian.
 *   - `@tangle-network/agent-runtime` — Validator<Output, Verdict = DefaultVerdict>.
 *     Runtime keeps `Validator` because it's coupled to runtime-shaped
 *     `ValidationCtx` (iteration, signal, traceEmitter); the verdict TYPE
 *     itself is a substrate concept and lives here.
 *
 * Repo layering: agent-eval is the substrate (no upward deps). Both
 * agent-runtime and agent-knowledge consume this type FROM agent-eval —
 * never the other way around. See CLAUDE.md "Repo layering" for the rule.
 */
/**
 * Minimal verdict shape — `valid` + `score` are required; `scores` +
 * `notes` are optional surface. Validators that need richer shapes
 * parameterise `Validator<Output, MyVerdict>` with their own type.
 *
 * Need structured extras? Extend DefaultVerdict with typed fields — never
 * serialize extras into `notes`.
 */
interface DefaultVerdict {
    /** Whether the output meets the validator's pass criteria. */
    valid: boolean;
    /** Aggregate score in [0, 1]. Drivers use this for winner selection. */
    score: number;
    /** Per-dimension scores. Free-form; weighted into `score` by the validator. */
    scores?: Record<string, number>;
    /** Human-readable rationale; surfaces in trace + final-result `winner.verdict`. */
    notes?: string;
}

/**
 * N-axis cartesian matrix over substrate types — types module.
 *
 * The matrix is a runner + aggregator. It iterates the cartesian product of
 * caller-provided axes (any value type — `AgentProfile` from agent-interface,
 * `Driver` / `Validator` from agent-runtime, rubric records, thinking levels, anything)
 * and aggregates per-axis pass/score/cost summaries. Substrate types are
 * imported at the boundary by JSDoc only; the matrix never wraps them.
 */

/** One axis = one dimension to iterate. `V` is the value type — pass any
 *  substrate type (AgentProfile, Driver, Validator, rubric record). */
interface MatrixAxis<V> {
    /** Axis name. Becomes the key in `MatrixResult.byAxis`. */
    name: string;
    /** Stable id per value. Used as the bucket key in aggregation. */
    values: Array<{
        id: string;
        value: V;
    }>;
    /** Optional bucket label override. Receives the same `(value, id)` the
     *  runner stored on the cell; default label is `id`. */
    label?: (value: V, id: string) => string;
}
/** A cell carries one picked value from each axis, keyed by axis name. */
interface MatrixCell {
    axes: Record<string, {
        id: string;
        value: unknown;
    }>;
    /** 0-based replicate index within the same axis combination. */
    rep: number;
    /** Stable sort key — preserves cartesian order across concurrent execution. */
    ordinal: number;
}
interface CellResult<Output> {
    output: Output;
    verdict: DefaultVerdict;
    costUsd: number;
    durationMs: number;
    runId?: string;
    /** Populated when `runCell` threw. The cell contributes 0 to passRate AND
     *  meanScore regardless of `verdict`. */
    error?: {
        message: string;
        kind: string;
    };
}
interface AxisSummary {
    axisName: string;
    axisValue: string;
    cells: number;
    passRate: number;
    meanScore: number;
    p50Score: number;
    p90Score: number;
    totalCostUsd: number;
    meanDurationMs: number;
}
interface MatrixResult<Output> {
    cells: Array<{
        cell: MatrixCell;
        runs: CellResult<Output>[];
    }>;
    /** `byAxis[axisName][axisValueId] = summary`. Populated only for axes
     *  named in `aggregateBy` (default = every axis in `axes`). */
    byAxis: Record<string, Record<string, AxisSummary>>;
    summary: {
        totalCells: number;
        runsExecuted: number;
        /** Cells removed by `filter` plus cells unscheduled after the cost
         *  ceiling or abort signal tripped. */
        cellsSkipped: number;
        overallPassRate: number;
        overallMeanScore: number;
        totalCostUsd: number;
        durationMs: number;
    };
    /** Stable id-like string generated at the end of the run. */
    matrixId: string;
}
interface RunAgentMatrixOptions<Output> {
    axes: MatrixAxis<unknown>[];
    /** User-supplied cell executor. May throw; the matrix captures throws as
     *  `CellResult.error` and continues. */
    runCell: (cell: MatrixCell) => Promise<CellResult<Output>>;
    /** Replicates per cell. Default 1. */
    reps?: number;
    /** Prune cells from the cartesian BEFORE rep expansion. */
    filter?: (cell: Omit<MatrixCell, 'rep' | 'ordinal'>) => boolean;
    /** Axes to aggregate into `byAxis`. Default: every axis in `axes`. */
    aggregateBy?: string[];
    /** Max concurrent in-flight `runCell` invocations. Default 4. */
    maxConcurrency?: number;
    /** Cumulative-cost abort threshold (USD). When the running sum of
     *  `result.costUsd` crosses this value, no new cells are scheduled.
     *  In-flight cells finish. Default `Infinity`. */
    costCeiling?: number;
    /** Fires once per executed cell, after its promise settles. */
    onCellComplete?: (cell: MatrixCell, result: CellResult<Output>) => void;
    /** External cancellation. Aborts in-flight cells via a forwarded signal
     *  and suppresses scheduling of new ones. */
    signal?: AbortSignal;
}

/**
 * N-axis cartesian runner.
 *
 * Expansion order: cartesian over `axes` in declared order, then `reps` as the
 * inner-most dim → `ordinal = (cartIdx * reps) + rep`. The returned
 * `cells[]` is sorted by `ordinal` so concurrent execution does not reorder
 * the output.
 *
 * Scheduling is a sliding window of in-flight promises capped at
 * `maxConcurrency`. The window stops admitting new cells when the cost
 * ceiling trips or the abort signal fires; in-flight cells finish.
 */

declare function runAgentMatrix<Output>(opts: RunAgentMatrixOptions<Output>): Promise<MatrixResult<Output>>;

export { type AxisSummary, type CellResult, type DefaultVerdict, type MatrixAxis, type MatrixCell, type MatrixResult, type RunAgentMatrixOptions, runAgentMatrix };
