/**
 * The deferral CENSUS: what a leg discloses about which of its tools ship as name-only placeholders, and the
 * seat that carries it to the stream. Split out of the disclosure mount because it is a different concern —
 * the mount decides the request FACE, this decides what is SAID about it.
 */
import type { ToolSearchPolicy, ResolvedToolSearch } from "../tool-search-setting.js";
/**
 * The HOST-facing census of this leg's deferral: which tool names ship as name-only placeholders, which the model has activated, and the policy that decided it.
 * @contract tool_disclosure.snapshot — the `tool_disclosure` frame is minted ONLY here ({@link ToolDisclosureSeat.publish}), exists ONLY on a leg that defers
 * at least one tool, and carries the WHOLE census each time (a consumer replaces its copy; the "what just happened" delta is this snapshot's `activated` minus
 * the previous one's). `deferred` is frozen at prepare (a name never leaves it, it only appears in `activated`); both lists are sorted, so two snapshots
 * compare by value. A leg that defers nothing emits no frame at all — absence is "nothing was deferred", never "the disclosure is off".
 */
export interface ToolDisclosureSnapshot {
    /** Which arm of `RunnerDeps.toolSearch` decided rule ② on this leg. */
    policy: ToolSearchPolicy;
    /** Present iff `policy === "auto"`: the percent of the window the candidate set had to reach. */
    thresholdPercent?: number;
    /** Every deferred name on this leg, sorted. Non-empty (the frame does not exist otherwise). */
    deferred: readonly string[];
    /** The deferred names ACTIVE on this leg right now, sorted — the engine's state, not a record of commits. Empty on the leg-start census only when nothing
     *  seeded it; a RESUMED leg carries whatever the engine reseeded (transcript replay, compaction snapshot, checkpoint) before anything executed. */
    activated: readonly string[];
}
/**
 * The run-time seat the frame rides: prepare publishes the leg-start census, every activation that changes it publishes the next, and the run's event wiring
 * subscribes once. Snapshots published before the sink is installed are buffered (bounded) and flushed in order, so the leg-start census can be minted at
 * prepare and still arrive after the manifest frame it belongs beside. Deliberately the same shape as `ToolRosterDeltaSeat` — the two are one problem.
 */
export declare class ToolDisclosureSeat {
    #private;
    /** Publish a census. A snapshot equal to the last published one is DROPPED: `rematerialize` also runs on an MCP refresh, and a frame that says nothing
     *  changed reads as an activation that did not happen. */
    publish(snapshot: ToolDisclosureSnapshot): void;
    /** Install the stream sink; anything published before is flushed in order. */
    subscribe(sink: (snapshot: ToolDisclosureSnapshot) => void): void;
    /** The leg ended: drop the sink so a late publish never reaches a closed stream (it buffers, unread). */
    unsubscribe(): void;
}
/**
 * Mint a leg's census producer: the frozen deferred list, the policy it was classified under, and a seat.
 * One place holds both halves, so a census can never name a policy the classification did not run under.
 *
 * `deferred` is frozen because every census shares the one array — a host that mutated the list it was handed
 * would be editing every later frame of the leg. `activated` is filtered to the DEFERRED names: the live
 * activation set is seeded from the transcript and a resume checkpoint, both of which can name an undeferred
 * tool.
 */
export declare function createDeferralCensus(deferred: ReadonlySet<string>, policy: ResolvedToolSearch): {
    seat: ToolDisclosureSeat;
    publish: (active: ReadonlySet<string>) => void;
};
