/**
 * Team-Health-Watchdog (THW) — Alert Router
 *
 * §D (dedup + cooldown ladder) and §H.2 (channel routing). Holds in-memory
 * cooldown / alert-budget state. The watchdog service owns Slack delivery;
 * this router decides what to send, to whom, and whether to suppress.
 *
 * Layer-4 invariant (§A.1): NEVER mutates lower-layer state.
 *
 * @module services/team-health/team-health-alert-router
 */
import type { AlertDecision, OffHoursConfig, TeamHealthAlertingConfig, TeamHealthDetection, TeamSummary, VerdictCode } from './team-health-types.js';
interface CooldownEntry {
    teamId: string;
    verdict: VerdictCode;
    bucket: number;
    postedAt: number;
}
/**
 * Routes detections to alert decisions (channel + message + suppress
 * reason). State persists in memory; the watchdog can snapshot/restore
 * across restarts via the sidecar JSON files (§F.2).
 */
export declare class TeamHealthAlertRouter {
    private alertingConfig;
    private offHoursConfig;
    private shadowMode;
    private cooldowns;
    private budgets;
    private silenced;
    constructor(alertingConfig: TeamHealthAlertingConfig, offHoursConfig: OffHoursConfig, shadowMode: boolean);
    setShadowMode(shadowMode: boolean): void;
    reconfigure(alerting: TeamHealthAlertingConfig, offHours: OffHoursConfig): void;
    silenceTeam(teamId: string, now: Date, durationMs: number): void;
    snapshotState(): {
        cooldowns: CooldownEntry[];
        budgets: {
            teamId: string;
            count: number;
            windowStart: number;
        }[];
        silenced: {
            teamId: string;
            until: number;
        }[];
    };
    restoreState(snapshot: ReturnType<TeamHealthAlertRouter['snapshotState']>): void;
    /**
     * Route one detection to an AlertDecision. Idempotent: caller iterates
     * over a batch without ordering side-effects. Cooldown commits happen
     * only via `commitDecision`.
     *
     * @param detection - Detection from the detector
     * @param team - Team summary (slack thread/TL routing)
     * @param now - Current wall-clock time
     * @param systemOrphanTotal - System-wide orphan count for ops escalation
     */
    route(detection: TeamHealthDetection, team: TeamSummary, now: Date, systemOrphanTotal: number): AlertDecision;
    /**
     * Acknowledge a delivered alert: bumps cooldown bucket + budget counter.
     * Suppressed decisions do NOT call this — they have no side-effects.
     */
    commitDecision(decision: AlertDecision, now: Date): void;
    private cooldownForVerdict;
    private channelForVerdict;
    private applyOffHoursDowngrade;
    private dropCooldownsForTeam;
    private budgetExceeded;
    private bumpBudget;
}
/**
 * Test whether `now` is inside the configured working window for the
 * owner timezone (§FP-2). Conservative on parsing — invalid inputs
 * default to "always working hours".
 */
export declare function isWithinWorkingHours(now: Date, config: OffHoursConfig): boolean;
/**
 * Build the multi-line roll-up Slack message for one detection (§D.5).
 *
 * @param detection - The team's detection
 * @param team - Team summary (for member labels and TL @mention)
 * @param effectiveVerdict - Final verdict after off-hours downgrade
 * @param systemOrphanTotal - System-wide orphan count for context line
 * @returns Slack-ready message text
 */
export declare function formatRollupMessage(detection: TeamHealthDetection, team: TeamSummary, effectiveVerdict: VerdictCode, systemOrphanTotal: number): string;
/**
 * Build the recovery message — short factual line, cooldown=0 (§6.3).
 */
export declare function formatRecoveryMessage(team: TeamSummary, detection: TeamHealthDetection, now: Date): string;
export {};
//# sourceMappingURL=team-health-alert-router.d.ts.map