/**
 * seriesEvidence — one MCP request's retry series, written down for its run.
 *
 * Pattern: a collector over footprintjs's attempt records, filed once.
 * Role:    The series (`throttleRetry.ts` · `Series`) is the one retry owner and
 *          the attempt runner makes one record per try; this turns each record
 *          into an allow-listed row and files the request's whole story — its
 *          rows, how many were not listed, and how it ended — to the call's sink
 *          (`tools/requestEvidence.ts`) exactly ONCE.
 *
 * WHAT A ROW MAY SAY. Numbers and the library's own words; never the server's
 * answer, the call's arguments or an error's text. A failure is a fixed sentence
 * and its category — a network or SDK error message can carry a URL with a token
 * in it, a host's internal name or a server's reply.
 *
 * A RESPONSE IS NOT A SUCCESS. The runner records an attempt that returned a
 * response as `ok` with the reason `succeeded`; here it is `answered`, with the
 * status the server sent — a 503 delivered is `answered` + `503`, never success.
 *
 * EVERY REQUEST SENT IS COUNTED. Each attempt the series started is a row — or,
 * past the cap, one more in `omitted` — so `rows + omitted` is the number of
 * requests the series sent. An attempt a cancellation cuts in flight is a row
 * too (`cut`), exactly as an attempt the deadline cuts is (`timed-out`). A
 * request the series never sent — the next one after a cancelled wait — has no
 * row.
 *
 * A CUT IS NOT A "NOT RUN". An attempt that ended without an answer — cut,
 * timed out, or failed — was sent, and the server may have received it and run
 * it. Its row says so (`remote: 'unknown'`); nothing here records it as not run.
 *
 * THREE FACTS PER ATTEMPT, NONE READ FROM ANOTHER (`replay.ts`): the failure
 * (footprintjs's category), what is known of its effect (`unknown` for every
 * attempt sent that did not complete — a refusal included; `applied` when the
 * call completed, never proof of a write; `none` only for what was never
 * sent), and — on an attempt the series asked again after — what permitted it.
 * Each row also says how long it took. The end says how many requests were
 * sent and what is known of the whole series' effect; uncertainty survives
 * (`SeriesKnowledge`).
 *
 * WHEN IT FILES. When the call settles — the series has ended by then, and the
 * call's verdict is what says whether an answered attempt completed (a 200 can
 * carry a tool error) — and, for a cancellation, at the moment the signal
 * fires: a cancelled run stops waiting for its stage at once, so a record filed
 * when the series later unwinds would land after the run was saved. The runner
 * makes no record for an attempt it abandons at that moment or for a wait it
 * was cut out of, so those are written here: the cut attempt's row and
 * `during: 'request'`, or `during: 'wait'`. A series ended and waiting for its
 * call files at once if the call is cancelled first, with what it knows.
 * Anything the series reports after it has filed is not part of the request's
 * story any more and is ignored.
 */
import type { AttemptRecord } from 'footprintjs';
import type { ToolRequestAttempt, ToolRequestEffect, ToolRequestPermission, ToolRequestReason } from '../events/payloads.js';
import { type RequestEvidence, type RequestEvidenceSink } from '../tools/requestEvidence.js';
import { type RequestReplay } from './replay.js';
/** Where the request went, as a row may say it: the app's label for it, or its origin. */
export type RequestWhere = Pick<RequestEvidence, 'endpoint' | 'origin'>;
/** What the series saw of one attempt that its record does not hold. */
export interface AttemptSeen {
    /** The response's status, when a response arrived. */
    readonly status?: number;
    /** The refusal a rule recognised in that response, when one did. */
    readonly refusal?: {
        readonly kind: 'throttle' | 'session-busy';
        readonly retryAfterMs?: number;
    };
}
/** Why the series' `retryOn` said no — the reasons the runner calls `declined`. */
export type DeclineReason = Extract<ToolRequestReason, 'exhausted' | 'wait-limit' | 'no-time-left' | 'not-replayable' | 'not-retryable' | 'not-permitted' | 'changes-without-key'>;
/**
 * What the series knows of one attempt beyond the runner's record (`replay.ts`):
 * its effect — absent for an answered attempt, which the call's verdict decides
 * when the record is filed — what permitted the next attempt, and how long it
 * took.
 */
export interface AttemptFacts {
    readonly effect?: ToolRequestEffect;
    readonly permission?: ToolRequestPermission;
    readonly durationMs: number;
}
/**
 * Where the record waits for its call: the call's signal (it fires when the
 * call settles or is cancelled), and the facts the call leaves there.
 */
export interface Settlement {
    readonly signal: AbortSignal;
    readonly replay: RequestReplay;
}
/** One request's evidence, collected as its series runs and filed once. */
export declare class SeriesEvidence {
    private readonly sink;
    private readonly where;
    private readonly settlement?;
    private readonly rows;
    private omitted;
    private last;
    private filed;
    private waiting;
    /** What is known of the series' effect, attempt by attempt — the answer's excepted. */
    private readonly knowledge;
    /** The answered attempt, while its effect waits for the call's verdict. */
    private answer;
    constructor(sink: RequestEvidenceSink, where: RequestWhere, settlement?: Settlement | undefined);
    /** One attempt as the runner recorded it, with what the series knows of it. */
    attempt(record: AttemptRecord, seen: AttemptSeen | undefined, declined?: DeclineReason, facts?: AttemptFacts): void;
    /**
     * The caller's cancellation cut attempt `n` in flight. It was sent — the
     * server may have it, and may have run it — so it is a row, `cut`, with the
     * remote outcome `unknown`; then the request's end says the same.
     */
    cutInFlight(n: number, durationMs?: number): void;
    /**
     * The caller's cancellation landed with NO request in flight: between two —
     * `during: 'wait'`, the next request never sent — or before the first, when
     * nothing was sent and there is no `during`. No row is added: there is no
     * request to account for. A request that had already ended keeps its end.
     */
    cancelled(): void;
    /**
     * The series delivered a response. It is the last attempt's — an answer, or a
     * refusal it will not ask again after. A refusal it MEANT to ask again after
     * is delivered when the series stopped inside the wait: the deadline landed
     * there (`no-time-left`), or a pooled call's send gate refused the next
     * attempt before it was sent (`stoppedBy`, `not-permitted`). The end says
     * which, during the `wait`; the attempt that was never sent has no row.
     * Filed when the call has read it.
     */
    delivered(stoppedBy?: DeclineReason): void;
    /**
     * The series threw. The end is the last attempt's when that attempt ended it
     * (a failure, a timed-out request). The rest is defensive — footprintjs 10.6's
     * runner never throws without a record but for a cancellation, which is filed
     * as one: a deadline that had passed before the first request (`timed-out`,
     * no `during`, nothing sent) or one a future runner reports from inside a wait
     * (`during: 'wait'`); anything else is filed as a failure the record cannot
     * account for, so a request is never left unfiled. A pooled call's send gate
     * that refused the next attempt before it was sent ends it as `stoppedBy`,
     * during the `wait`. Filed when the call settles.
     */
    threw(outOfTime: boolean, stoppedBy?: DeclineReason): void;
    private add;
    /**
     * File `end` once the call has settled — its verdict is what says whether an
     * answered attempt completed — or at once, when the call is already settled
     * or cancelled, or there is no call to wait for.
     */
    private fileWhenSettled;
    private file;
    /**
     * The rows, the answered one given its effect: `applied` when the call
     * completed — the server answered it, and not with an error — else `unknown`
     * (a 5xx, a JSON-RPC error, a tool error, a call cancelled before it read the
     * answer). The answer's effect joins the series' knowledge here.
     */
    private settleAnswer;
}
/** One record as a row — see the module note for what a row may say. */
export declare function rowOf(record: AttemptRecord, seen: AttemptSeen | undefined, declined?: DeclineReason): ToolRequestAttempt;
/**
 * `row` with what the series knows of its attempt beyond the record — its
 * effect, what permitted the next attempt, how long it took. Without `facts`,
 * the row as the record alone says it.
 */
export declare function withFacts(row: ToolRequestAttempt, facts: AttemptFacts | undefined): ToolRequestAttempt;
