/**
 * work — an admitted operation's charge, and the work under it until that work
 * has settled.
 *
 * Pattern: one object per unit of work that is at once the request guard
 *          (`mcp/requestGuard.ts`) and the count of what is still running.
 * Role:    The pool's third budget (`docs/design/2026-10-mcp-client-pool.md`
 *          § 5.3). The accounting unit is the admitted LOGICAL operation: a
 *          `tools/call`, a listing (one `list(ctx)` for one conversation), an
 *          `acquire` and an ending each take one slot at admission. Setup an
 *          operation performs for itself — the open of its key's client, the
 *          revalidating `tools/list` of a replacement — runs inside that slot.
 *
 * AN ABORT IS NOT SETTLEMENT. A slot is released only when the operation's
 * logical request has its answer AND every piece of work under it has settled:
 * the `send()` it made, a credential vend, an attempt's `fetch`, an AWS `send`,
 * the open it owns. A caller's timeout answers the caller; it frees nothing.
 * Work that never settles keeps its charge — `stats().unsettled` reports it,
 * and the budget refuses new work rather than admit it against room that does
 * not exist. There is no release that returns capacity sooner.
 */
import type { RequestGuard } from '../requestGuard.js';
/** What a unit of work is doing now — what `stats().unsettled` counts it under. */
export type WorkKind = 'open' | 'listing' | 'call' | 'ending';
/** What an operation is, as the budget admits it. */
export type OperationKind = 'listing' | 'call' | 'acquire' | 'ending';
/** What a request's answer proved, as the pool's fetch read it (`pool.ts`). */
export type WorkEvidence = 'server-404' | 'handle-lost';
/**
 * One unit of pooled work: its requests are checked against it at every
 * boundary (`check`), and every promise started for it is counted until it
 * settles (`track`). It is SETTLED once its logical part has finished and the
 * count is zero.
 */
export declare class Work implements RequestGuard {
    /** What it is doing now. */
    phase: WorkKind;
    private readonly link;
    private pending;
    private finished;
    private done;
    /** Still running underneath when the caller was answered: it lingered. */
    private lingered;
    private readonly listeners;
    /** What `check` asks besides the abort — a call's binding. */
    private extra;
    /** What the latest answered request proved, if anything. */
    evidence: WorkEvidence | undefined;
    constructor(
    /** What it is doing now. */
    phase: WorkKind, sources: readonly (AbortSignal | undefined)[]);
    /** What aborts its own work: its sources, its deadline, its caller detaching. */
    get signal(): AbortSignal;
    /** True once its logical part finished and everything under it settled. */
    get settled(): boolean;
    /** Its caller was answered while work under it still ran. */
    get unsettledPastAnswer(): boolean;
    /** Abort its work with `reason` (a deadline, a detached caller). Idempotent. */
    abort(reason: unknown): void;
    /** Ask `gate` too, each time a request is checked. */
    guardWith(gate: () => void): void;
    /**
     * The send gate: refused once its caller was answered (nothing more is sent
     * for an answered operation), once aborted, or when the extra gate refuses.
     */
    check(): void;
    /** Count `work` until it settles. Never throws; never surfaces its rejection. */
    track(work: PromiseLike<unknown>): void;
    /** Record what a request's answer proved. */
    note(evidence: WorkEvidence): void;
    /**
     * Its logical part is over: the caller has its answer. It settles now, or —
     * when work under it still runs — when that work does.
     */
    finish(): void;
    /** Did it linger — answered while work under it ran? Read once it settled. */
    get settledLate(): boolean;
    /** Call `listener` once it has settled (at once when it already has). */
    onSettled(listener: () => void): void;
    /** A promise that resolves once it has settled. */
    whenSettled(): Promise<void>;
    private settleIfDone;
}
/** An admitted operation: a unit of work that holds one slot of the budget. */
export declare class Operation extends Work {
    readonly kind: OperationKind;
    /** When it was admitted, on the pool's clock. */
    readonly admittedAt: number;
    constructor(kind: OperationKind, phase: WorkKind, sources: readonly (AbortSignal | undefined)[], 
    /** When it was admitted, on the pool's clock. */
    admittedAt: number);
}
/**
 * The pool-wide operation budget: at most `max` operations charged, each from
 * its admission until it has SETTLED (see the module note). Admission is the
 * only way in; settlement the only way out.
 */
export declare class OperationBudget {
    readonly max: number;
    private readonly charged;
    private readonly onRelease;
    constructor(max: number);
    /** Operations charged now. */
    get count(): number;
    /** Is there a free slot? */
    get hasRoom(): boolean;
    /**
     * Admit one operation, or `undefined` when the budget is full. The slot is
     * charged from here until the operation settles.
     */
    admit(kind: OperationKind, phase: WorkKind, sources: readonly (AbortSignal | undefined)[], now: number): Operation | undefined;
    /** Call `listener` each time an operation settles and frees its slot. Returns the unsubscribe. */
    whenReleased(listener: (operation: Operation) => void): () => void;
    /** Charged work whose caller was already answered and which has not settled, by what it is doing. */
    unsettled(): Record<WorkKind, number>;
}
