import type { ListmonkClient } from "@listmonk-ops/openapi"; export interface SegmentSnapshotEntry { capturedAt: string; listId: number; listName: string; subscriberCount: number; /** Caller-scoped sampling period; same-key entries replace their predecessor. */ sampleKey?: string; } /** * A committed keyed sample's original result, persisted so an identical * retry replays the exact measurement (including alerts) instead of * re-observing live counts. */ export interface StoredSegmentDriftSettings { threshold: number; minAbsoluteChange: number; lookbackDays: number; baselineMode: "previous" | "lookback-mean" | "lookback-median"; } export interface StoredSegmentDriftResult { scope: "all" | "lists"; listIds: number[]; capturedAt: string; settings: StoredSegmentDriftSettings; comparisons: SegmentDriftComparison[]; alerts: SegmentDriftComparison[]; } export interface SegmentDriftStore { version: 1; snapshots: SegmentSnapshotEntry[]; keyedResults?: Record; } export interface SegmentDriftOptions { listIds?: number[]; threshold?: number; minAbsoluteChange?: number; lookbackDays?: number; /** How to compute the baseline for alert decisions. */ baselineMode?: "previous" | "lookback-mean" | "lookback-median"; /** * Caller-scoped sampling period key. Snapshots sharing a listId and * sampleKey replace their predecessor instead of appending, so an * ambiguous retry never double-weights the same period. */ sampleKey?: string; } export interface SegmentDriftComparison { listId: number; listName: string; previousCount?: number; currentCount: number; baselineCount?: number; delta?: number; deltaRate?: number; alert: boolean; } export interface SegmentDriftResult { capturedAt: string; storePath: string; threshold: number; minAbsoluteChange: number; /** Snapshots replaced by this run because they shared its sample key. */ replaced: number; comparisons: SegmentDriftComparison[]; alerts: SegmentDriftComparison[]; } export declare function runSegmentDriftSnapshot(client: ListmonkClient, options?: SegmentDriftOptions): Promise;