/**
 * notifications/service.ts
 *
 * NotificationService — composes the read source (subscribed teams), the pure
 * matcher (report → channels), and the deliver adapters (one per channel type)
 * into a fire-and-forget dispatcher behind the `NotificationServicePort`. The
 * composition root wires it into `AppContext.notifications` only when
 * `SLACK_BOT_TOKEN` is set, exactly as `loadSinks` is gated.
 *
 * Fire-and-forget (P6): neither method throws. The publish step has already
 * written the report to the system of record by the time it dispatches, so a
 * notification failure must never propagate back into the pipeline. A rejecting
 * source yields an empty result; a rejecting adapter is caught by the retry
 * helper and recorded as a `failed` outcome. Deliveries run concurrently via
 * `Promise.allSettled` so one failing channel never blocks the rest.
 *
 * @see packages/core/src/ports/notification.ts — the port this implements
 * @see packages/core/src/notifications/match.ts — the pure matcher
 * @see packages/eval/src/orchestration/steps/publish-report-step.ts — runSinks,
 *   the fire-and-forget precedent this mirrors
 */
import { type ChannelDelivery, type ChannelDispatchResult, type DigestSummary, type NotificationChannelAdapter, type NotificationDelivery, type NotificationServicePort, type Report, type Team, type TeamSubscriptionSource } from "../_vendor/ailf-core/index.d.ts";
import type { SanityClient } from "@sanity/client";
/** Retry tuning for the delivery path. Defaults to the sink policy (3, 1000ms). */
export interface NotificationRetryOptions {
    baseDelayMs?: number;
    maxRetries?: number;
}
export interface NotificationServiceOptions {
    adapters: NotificationChannelAdapter[];
    retry?: NotificationRetryOptions;
    source: TeamSubscriptionSource;
}
export declare class NotificationService implements NotificationServicePort {
    private readonly adapters;
    private readonly retry;
    private readonly source;
    constructor(options: NotificationServiceOptions);
    dispatchReport(report: Report): Promise<ChannelDispatchResult[]>;
    dispatchDigest(digest: DigestSummary, cadence: NotificationDelivery, teams: Team[]): Promise<ChannelDispatchResult[]>;
    /**
     * Deliver a per-channel scoped digest: each item pairs a resolved channel
     * target with the digest built from *that channel's* windowed reports. Unlike
     * `dispatchDigest` (one shared roll-up to every cadence channel), each
     * delivery carries its own digest, so a `repos`-scoped channel receives a
     * roll-up of only its repos' reports.
     *
     * This is the M6 notify-sweep delivery path: the sweep does the windowing and
     * per-channel scope/event matching (via the pure `matchReportToChannels`) and
     * hands the resolved per-channel digests here. Never throws (P6). Not on the
     * core `NotificationServicePort` — that contract covers the pipeline's inline
     * dispatch and the cadence-broadcast primitive; the sweep uses the concrete
     * service it builds via `createNotificationService`.
     */
    dispatchScopedDigests(items: {
        digest: DigestSummary;
        target: ChannelDelivery;
    }[], cadence: NotificationDelivery): Promise<ChannelDispatchResult[]>;
    private deliverAll;
    /**
     * Deliver each (target, digest) pair concurrently — one digest per channel.
     * Shared core for `dispatchDigest` (same digest to every cadence channel) and
     * `dispatchScopedDigests` (per-channel scoped digests). Mirrors `deliverAll`,
     * but pairs each delivery with its own digest content.
     */
    private deliverScoped;
    private deliverOne;
}
/**
 * Build the production NotificationService: a Content Lake team source plus the
 * channel adapters whose credentials are present. The Slack adapter is added
 * when `token` (SLACK_BOT_TOKEN) is set; the webhook adapter when
 * `webhookSigningSecret` (AILF_WEBHOOK_SIGNING_SECRET) is set. At least one is
 * required by the composition-root gate before this is called.
 */
export declare function createNotificationService(opts: {
    client: SanityClient;
    dashboardBaseUrl: string;
    token?: string;
    webhookSigningSecret?: string;
    webhookEnv?: NodeJS.ProcessEnv;
}): NotificationService;
