/**
 * Typed event bus for index lifecycle events. Forwarded into the WS
 * broadcast pipeline by `server.ts` (T11) and consumed by the in-process
 * `SearchService` state machine.
 *
 * Payloads match `src/server/ws/protocol.ts` additions (design §9) exactly
 * so forwarding is a no-op cast — the WS layer just stamps a `type` prefix
 * and ships it.
 */
export interface IndexProgressEvent {
    projectId: string;
    phase: "rebuild" | "incremental";
    total: number;
    completed: number;
    backlog: number;
}
export interface IndexCompleteEvent {
    projectId: string;
    phase: "rebuild" | "incremental";
    durationMs: number;
    rowsWritten: number;
}
export interface IndexErrorEvent {
    projectId: string;
    message: string;
    recoverable: boolean;
}
export interface ProgressBusEvents {
    "index:progress": [IndexProgressEvent];
    "index:complete": [IndexCompleteEvent];
    "index:error": [IndexErrorEvent];
}
/**
 * Thin typed wrapper over `EventEmitter`. We use a hand-rolled generic
 * rather than TS 5's built-in typed emitter so downstream code doesn't
 * need `@types/node` >= 22 semantics leaking.
 */
export declare class ProgressBus {
    private readonly emitter;
    on<K extends keyof ProgressBusEvents>(event: K, listener: (...args: ProgressBusEvents[K]) => void): this;
    off<K extends keyof ProgressBusEvents>(event: K, listener: (...args: ProgressBusEvents[K]) => void): this;
    once<K extends keyof ProgressBusEvents>(event: K, listener: (...args: ProgressBusEvents[K]) => void): this;
    emit<K extends keyof ProgressBusEvents>(event: K, ...args: ProgressBusEvents[K]): boolean;
    removeAllListeners<K extends keyof ProgressBusEvents>(event?: K): this;
}
/**
 * Shared singleton — there is one bus per server process. Per-project
 * scoping is carried in each event's `projectId` field; the WS layer
 * filters subscribers.
 */
export declare const progressBus: ProgressBus;
//# sourceMappingURL=progress-bus.d.ts.map