/** A latency distribution: how many samples, and their nearest-rank median and 95th percentile. */
export interface Latency {
    samples: number;
    /** `null` when there are no samples. */
    p50Ms: number | null;
    /** `null` when there are no samples. */
    p95Ms: number | null;
}
/** Nearest-rank percentile of an ascending-sorted list; `null` when it is empty. */
export declare function percentile(sorted: readonly number[], p: number): number | null;
/** {@link Latency} of a list of durations, in any order. */
export declare function summarizeLatency(values: readonly number[]): Latency;
/** What {@link summarizeRunMetrics} reads off one run row, whichever store it came from. */
export interface RunMetricsSample {
    status: string;
    parentRunId: string | null;
    /** Epoch ms. */
    startedAt: number;
    /** Epoch ms; `null` while running. */
    finishedAt: number | null;
    ttftMs: number | null;
    errorCode: string | null;
}
/** How many failed runs ended under one stream error code. */
export interface RunFailureCodeRow {
    /** The run's `error_code`; `'unknown'` for a failure recorded before codes were. */
    code: string;
    count: number;
}
/** The latency and failure-code part of a run reliability rollup. */
export interface RunMetrics {
    latency: {
        ttft: Latency;
        duration: Latency;
    };
    failuresByCode: RunFailureCodeRow[];
}
/**
 * Turn latency and failures by code over a set of runs. Latency counts completed turns only, and
 * only a person's turn: a delegation's child run is part of its parent's turn, and counting it again
 * would skew both the median and the tail toward short sub-tasks. Every failed run counts toward its
 * code, the same runs {@link import('./spi/governance-queries.js').RunReliability.failed} counts.
 */
export declare function summarizeRunMetrics(runs: Iterable<RunMetricsSample>): RunMetrics;
//# sourceMappingURL=run-metrics.d.ts.map