import type { RunnerEvent } from "./sync-runner.js"; export interface RunnerEventStreams { stdout: { write: (chunk: string) => boolean | void; }; stderr: { write: (chunk: string) => boolean | void; }; } export declare function setRunnerEmitObserver(observer: (() => void) | null): void; /** * Fire the installed observer once, swallowing any fault. Call this at * work-driven seams that do NOT route a protocol event — notably the engine's * raw heartbeat, which is called far more often than the rate-limited heartbeat * EVENT — so the governor keeps observing during an async-heavy pass that emits * few events. The observer (the heap checkpoint) is itself gated, so calling it * often is cheap. */ export declare function notifyRunnerEmitObserver(): void; export declare function routeEvents(event: RunnerEvent, streams: RunnerEventStreams): void; export declare function createRunnerEmitter(streams: RunnerEventStreams): (event: RunnerEvent) => void; /** * Emit a CLASSIFIED `error` event for a top-level uncaught runner rejection, * BEFORE the process exits non-zero. * * The menubar (hq-sync) treats a non-zero runner exit with NO error event seen * at all as an "unexplained crash" and ALWAYS alerts on it. That is correct for * a real panic/OOM, but the historical top-level catch wrote only a plain * stderr line (not a protocol event) for EVERY uncaught rejection — so even a * benign cause that bubbled to the top (transient network blip, a * not-yet-provisioned 404, an expected ACL-scope skip) drove a false alert * (HQ-SYNC-WEB-6). Emitting a structured `{type:"error"}` event here routes the * failure through the menubar's `is_alertable_error` classifier, so the benign * cases are suppressed while genuine defects still surface. * * Best-effort: if routing itself throws, fall back to a plain stderr line so the * failure is never fully silent in the logs. */ export declare function emitUncaughtRunnerError(err: unknown, streams: RunnerEventStreams): void; //# sourceMappingURL=sync-runner-events.d.ts.map