/**
 * SentinelNotifier — the single delivery policy for the silently-stopped
 * sentinels (ActiveWorkSilenceSentinel + SocketDisconnectSentinel).
 *
 * Built in response to the 2026-05-22 topic-spam flood. Three problems were
 * stacked together; this module owns two of them (the detector fix lives in
 * sentinelWiring.ts):
 *
 *   1. Severity — sentinel monitoring is housekeeping. Every lifecycle
 *      transition (detected / nudged / recovered / escalated) is written to
 *      the logs (console + a JSONL audit trail) and, by default, NOTHING is
 *      sent to Telegram. Per the user: "anything that just needs to be logged
 *      for the system should not by default be sent to Telegram." This is
 *      stronger than throttling — routine noise is never GENERATED, not merely
 *      rate-limited.
 *
 *   2. Routing — when Telegram escalation is explicitly enabled, genuine
 *      recovery-failed escalations are COALESCED into ONE message and sent to
 *      ONE reused system topic. They never each spawn a brand-new forum topic
 *      (the old path went through /attention → createAttentionItem →
 *      createForumTopic, one topic per event, which produced the wall of
 *      "X went quiet" topics).
 *
 * Signal-vs-authority: this is a delivery sink, not a gate. It introduces no
 * blocking authority. The escalation message is a fixed plain-English template
 * with a yes/no CTA; the system-topic sender it is wired to may still apply the
 * outbound tone gate.
 *
 * Spec: docs/specs/silently-stopped-trio.md
 */
export type SentinelEventKind = 'detected' | 'nudged' | 'recovered' | 'escalated' | 'escalation-sent' | 'escalation-suppressed' | 'nudge-error' | 'recovery-error' | 'notify-error' | 'recovering' | 'dry-run' | 'false-alarm';
export interface SentinelLogEntry {
    ts: string;
    kind: SentinelEventKind;
    sentinel: string;
    sessionName: string;
    detail?: string;
}
export interface SentinelNotifierDeps {
    /**
     * Append a structured audit entry. Always invoked for every transition.
     * server.ts wires this to console + a JSONL file; tests pass a capture array.
     */
    log: (entry: SentinelLogEntry) => void;
    /**
     * Send ONE consolidated escalation message to the single reused system topic.
     * Only invoked when telegramEscalation is enabled. Returns true on delivery.
     * When omitted, escalation is log-only regardless of the enabled flag.
     */
    sendConsolidated?: (text: string) => Promise<boolean>;
    now?: () => number;
    setTimer?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
    clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
}
export interface SentinelNotifierConfig {
    /**
     * Master gate for Telegram escalation. Default false → all sentinel notices
     * are log-only. When true, genuine recovery-failed escalations are coalesced
     * and sent to the system topic.
     */
    telegramEscalation?: boolean;
    /**
     * Coalescing window (ms). Escalations that arrive within this window of each
     * other are flushed together as a single message. Default 5000ms — long
     * enough to absorb a restart-time burst, short enough to feel timely.
     */
    coalesceWindowMs?: number;
}
export declare class SentinelNotifier {
    private readonly deps;
    private readonly cfg;
    private readonly pending;
    private flushHandle;
    constructor(deps: SentinelNotifierDeps, cfg?: SentinelNotifierConfig);
    /** True if Telegram escalation is wired AND enabled. */
    get telegramEnabled(): boolean;
    /**
     * Record a routine lifecycle transition. Always log-only — never reaches
     * Telegram. This is the "housekeeping goes to the logs" path.
     */
    record(kind: SentinelEventKind, sentinel: string, sessionName: string, detail?: string): void;
    /**
     * A sentinel could not recover a genuinely-stuck session. Always logged. Sent
     * to Telegram (coalesced, single system topic) ONLY when escalation is
     * enabled; otherwise log-only.
     */
    escalate(sentinel: string, sessionName: string, text: string): void;
    /** Flush immediately (test seam + graceful shutdown). */
    flushNow(): Promise<void>;
    /** Cancel any pending flush (graceful shutdown). */
    stop(): void;
    private scheduleFlush;
    private clearFlush;
    private flush;
    /** Build ONE plain-English, CTA-bearing message for all coalesced sessions. */
    private composeMessage;
    private write;
}
//# sourceMappingURL=SentinelNotifier.d.ts.map