import { type ModBusSide, type ModEventName, type ModSeat } from "./events.js";
import { type ModAdmissionRecord, type ModDollarBase, type ModOrigin, type ModSeats } from "./registration.js";
import { type ModAnswerCheck, type ModEventPayload, type ModFailureCause, type ModMatcher, type ModSkip, type ProxyProbe } from "./site-rules.js";
/** A frame on the dispatch stack: a registration's own `$` call, or one of its handlers running. */
export type ModFrame = {
    readonly kind: "dollar";
    readonly plugin: string;
} | {
    readonly kind: "handler";
    readonly plugin: string;
    readonly handler: number;
};
/** What a chain bottom (the core of an event) receives besides `e`. */
export interface ModBottomContext {
    readonly frames: readonly ModFrame[];
    readonly signal: AbortSignal;
    readonly origin: ModOrigin;
}
/** A `$` method's chain bottom: the host's seat behind it. Its throw is the caller's throw. */
export type ModMethodBottom = (args: ModEventPayload, ctx: ModBottomContext) => unknown;
/**
 * A `$` method on a bus: `run` is its chain bottom; `enter`, when the method has one, shapes the caller's (received)
 * arguments into the event payload the chain sees — the one place a method's argument form is normalised before any
 * handler reads it. Either one's throw is the caller's throw.
 */
export interface ModMethodSeat {
    readonly run: ModMethodBottom;
    readonly enter?: (args: ModEventPayload) => ModEventPayload;
}
export type ModMethodBottoms = Partial<Record<ModEventName, ModMethodSeat>>;
export type ModDispatchOutcome = {
    readonly kind: "answered";
    readonly answer: unknown;
    readonly answeredBy?: string;
    readonly skipped: readonly ModSkip[];
} | {
    readonly kind: "failed";
    readonly registration: string;
    readonly cause: ModFailureCause;
    readonly reason: string;
    readonly skipped: readonly ModSkip[];
} | {
    readonly kind: "aborted";
};
/** What a participant filter sees of one mounted handler: its registration, that registration's seat, and whether it only observes. */
export interface ModParticipant {
    readonly plugin: string;
    readonly seat: ModSeat;
    readonly observe: boolean;
}
export interface ModDispatchOptions {
    /** The core of the event: what the engine (or shell) does when the chain reaches the bottom. */
    readonly bottom: (e: ModEventPayload, ctx: ModBottomContext) => unknown;
    readonly signal?: AbortSignal;
    /** The frames the event is raised under (a chain bottom hands its own `ctx.frames` on). */
    readonly frames?: readonly ModFrame[];
    readonly origin?: ModOrigin;
    /** The raiser's reading of an answer; an answer it refuses is a violation of the site. */
    readonly checkAnswer?: ModAnswerCheck;
    /** Which mounted handlers take part (absent ⇒ every handler on the event). A handler it leaves out neither runs nor observes. */
    readonly participant?: (p: ModParticipant) => boolean;
}
/** One handler as admission hung it — what a registration's `register` mounted, never its code. */
export interface ModMountedHandler {
    readonly plugin: string;
    readonly seat: ModSeat;
    readonly pattern: string;
    readonly matcher?: ModMatcher;
    readonly observe: boolean;
    /** Whether it was hung with a `.catch`. */
    readonly caught: boolean;
}
export interface ModBus {
    readonly records: readonly ModAdmissionRecord[];
    /** Every mounted handler, in mount order (registrations in run order, each in the order its `register` hung them). */
    mounted(): readonly ModMountedHandler[];
    /** Whether any mounted handler hangs on `event` (among those `participant` admits) — no handler, no dispatch (the station skips the call). */
    hasHandlers(event: ModEventName, participant?: (p: ModParticipant) => boolean): boolean;
    dispatch(event: ModEventName, e: ModEventPayload, options: ModDispatchOptions): Promise<ModDispatchOutcome>;
}
export interface ModBusInput<D extends ModDollarBase = ModDollarBase> {
    readonly side: ModBusSide;
    readonly seats: ModSeats<D>;
    readonly bottoms: ModMethodBottoms;
    /** Where handler failures go (the host's error channel). Never throws back into the bus. */
    readonly report: (err: Error, classification?: "observational-hook-verdict-ignored") => void;
    /** The host's one rule for turning a THROWN value into text (a handler, a `.catch` or a `register` may throw
     *  anything). The bus has no rendering of its own: every failure reason it writes names the value this way. */
    readonly describeThrown: (err: unknown) => string;
    /** The host's Proxy probe: a Proxy a handler answers or hands on is refused before any of its traps runs (a violation
     *  of the site). Absent ⇒ a Proxy is read like any object, its traps run by the copy. */
    readonly isProxy?: ProxyProbe;
    readonly signal?: AbortSignal;
}
/**
 * Screen both seats, then admit registrations one by one in run order: each is put to the
 * `plugin.register` handlers of the registrations already admitted; a refused one is never registered
 * (its code never runs). Throws `config.mods_invalid` for a registration the kernel cannot take.
 */
export declare function admitMods<D extends ModDollarBase = ModDollarBase>(input: ModBusInput<D>): Promise<ModBus>;
