/** * HangBuster filter pipeline — pure functions, no I/O. * * Stages: parse → normalise → threshold → bucket → cluster → aggregate → rank → format. * * Each function is independently testable. Pure module: only 'crypto' (deterministic hash). * No fs, no child_process. */ export declare const FINGERPRINT_VERSION = 2; export declare const DEFAULT_HANG_PREDICATE = "(subsystem == \"com.apple.runningboard\") OR (eventMessage CONTAINS \"Hang detected\") OR ((eventMessage CONTAINS[c] \"main thread\") AND (eventMessage CONTAINS[c] \"hang\"))"; export type Severity = 'minor' | 'warn' | 'critical' | 'frozen'; export interface NormalisedEvent { atMs: number; durationMs: number; severity: Severity; process: string; symbol?: string; normalisedMessage: string; fingerprint: string; } export interface Cluster { fingerprint: string; count: number; maxDurationMs: number; totalDurationMs: number; firstDeltaMs: number; severity: Severity; sampleEvent: NormalisedEvent; } export interface SessionSummary { sessionId: string; durationMs: number; totalEvents: number; droppedEvents: number; clusters: Cluster[]; bursts: Array<{ startsAtMs: number; endsAtMs: number; count: number; }>; quietPeriods: number; processDistribution: Record; fingerprintVersion: number; } export declare const SEVERITY_WEIGHT: Record; /** True if msg (lowercased) describes a hang/stall/watchdog event. */ export declare function isHangMessage(msg: string): boolean; /** * Parse one `xcrun simctl spawn log stream` line. * * @param line Raw log line. * @param baseMs Optional base timestamp in ms for computing atMs from a relative offset. * If omitted and the timestamp is unparseable, atMs = 0. * @returns NormalisedEvent or null if not a hang line / no duration. */ export declare function parseLogLine(line: string, baseMs?: number): NormalisedEvent | null; /** Strip boilerplate prefixes, redact volatile tokens, truncate to 40 chars. */ export declare function normaliseMessage(msg: string, maxLen?: number): string; /** Return the first ObjC or Swift symbol found in message, or undefined. */ export declare function extractSymbol(msg: string): string | undefined; /** True if the event's duration is at or above minHangMs (default 250). */ export declare function aboveThreshold(ev: NormalisedEvent, minHangMs?: number): boolean; /** Map milliseconds to a severity band. */ export declare function bucketSeverity(durationMs: number): Severity; /** * Stable identity hash for clustering. * Key = symbol if present, else normalisedMessage. * Returns 'fp:' + sha256(key).slice(0,16). */ export declare function computeFingerprint(ev: Pick): string; /** Group events by fingerprint, aggregating count + duration stats. */ export declare function clusterEvents(events: NormalisedEvent[]): Cluster[]; /** Find windows containing minCount or more events within windowMs. */ export declare function detectTemporalBursts(events: NormalisedEvent[], windowMs?: number, minCount?: number): Array<{ startsAtMs: number; endsAtMs: number; count: number; }>; /** Find gaps between adjacent events that exceed gapMs. Returns count of such gaps. */ export declare function detectQuietPeriods(events: NormalisedEvent[], gapMs?: number): number; /** Count events per process name. */ export declare function processDistribution(events: NormalisedEvent[]): Record; /** Score = SEVERITY_WEIGHT[severity] * maxDurationMs * log(count + 1), descending. */ export declare function rankClusters(clusters: Cluster[], topN?: number): Cluster[]; /** Single-line status (~20 tokens). Cache-friendly for agent context. */ export declare function formatL0(summary: SessionSummary): string; /** Default ~80-120 token output: header + top-N clusters + drill hint. */ export declare function formatL1(summary: SessionSummary, topN?: number): string; /** Expanded ~300 token output: all clusters + aggregates. */ export declare function formatL2(summary: SessionSummary): string; /** L3: per-cluster detail. */ export declare function formatClusterDetail(cluster: Cluster): string; /** Documented char/4 heuristic. */ export declare function estimateTokens(text: string): number; /** * Pick the densest level that fits maxTokens. * null → L1 unconditionally; ≥200 try L2; ≥60 try L1; else L0. */ export declare function compressToBudget(summary: SessionSummary, maxTokens?: number): string; /** Convenience function to cluster, rank, and aggregate events into a SessionSummary. */ export declare function buildSummary(sessionId: string, events: NormalisedEvent[], droppedEvents: number, topN?: number): SessionSummary; //# sourceMappingURL=pipeline.d.ts.map