/**
 * Process-level crash policy for `serve`.
 *
 * `uncaughtException` keeps fail-fast shutdown: a synchronous throw can leave
 * shared state mid-mutation, and Node documents resuming after one as unsafe.
 *
 * Unhandled REJECTIONS are a different population in practice: they are
 * overwhelmingly request-scoped async failures that escaped a reply lifecycle.
 * The motivating outage (1.3.48-next.224): a non-ASCII asset filename in an
 * ETag made Node throw ERR_INVALID_CHAR at header-send time, which surfaced as
 * an unhandledRejection — and ONE share-page font request took the whole
 * workspace down for every user until the platform restarted it. Exiting
 * trades one request's bug for a tenant-wide outage; a request-scoped failure
 * should cost that request a failed response, not the tenant its server.
 *
 * Policy: log loudly and keep serving — UNLESS rejections arrive in a storm
 * (≥ stormMax within stormWindowMs), which indicates systemic breakage (a
 * poisoned event loop, corrupted shared state, a tight failing retry loop)
 * rather than an isolated bad request. A storm fails fast exactly like the
 * old policy; every crash path stays recoverable on next boot (sessions
 * persist on markDirty, recoverOnBoot replays).
 */
export declare const REJECTION_STORM_MAX = 5;
export declare const REJECTION_STORM_WINDOW_MS = 30000;
export interface UnhandledRejectionPolicyOptions {
    /** Invoked when the storm threshold trips — shut the process down. */
    onFatal: (err: unknown) => void;
    log?: (message: string, err: unknown) => void;
    /** Injectable clock for tests. */
    now?: () => number;
    stormMax?: number;
    stormWindowMs?: number;
}
/** Build the `process.on('unhandledRejection')` listener implementing the
 *  log-and-continue-with-storm-breaker policy above. Pure factory (no process
 *  wiring) so the policy is unit-testable without spawning a server. */
export declare function createUnhandledRejectionHandler(options: UnhandledRejectionPolicyOptions): (err: unknown) => void;
