/** * Acute-spike correlation engine for log10x_investigate. * * Given an anchor pattern with a detected inflection, query the * Prometheus metric universe for co-movers (patterns whose rate changed * sharply in the same window), run lag analysis across a handful of * offsets, and build a causal chain ordered by lead time. * * The engine returns a structured result the renderer turns into markdown. * Confidence is mechanically derived from stat strength, lag tightness, * and chain coherence — never the model's self-assessment. */ import type { EnvConfig } from './environments.js'; import type { InvestigateThresholds } from './thresholds.js'; import { type PrimitiveError } from './primitive-errors.js'; export interface CoMover { pattern: string; service: string; severity: string; currentRate: number; baselineRate: number; rateChange: number; direction: 'up' | 'down'; /** Lag in seconds relative to anchor inflection — negative = leads. */ lagSeconds?: number; /** Per-offset rate change: used for lag-tightness scoring. */ lagProfile?: Array<{ offsetSeconds: number; rateChange: number; }>; } export interface ChainLink { mover: CoMover; /** Stat sub-score (0-1) — magnitude above noise floor. */ stat: number; /** Lag tightness (0-1) — sharpness of the peak across offsets. */ lag: number; /** Chain coherence (0-1) — how well this link fits the chain vs star pattern. */ chain: number; /** Final per-link confidence = stat * lag * chain. */ confidence: number; } /** * Outcome of the correlation engine. The agent-facing branches: * * - `success` — usable chain and/or co-movers. * - `no_signal` — query ran cleanly but nothing crossed the * rate-change / lag thresholds. * - `anchor_no_signal` — Phase B (anchor rate-change reference) returned * empty or a non-success Prometheus response, so * the direction reference is unusable. The agent * should re-anchor or widen the window. * - `error` — structural failure (Phase A topk query failed, * backend down, etc.). Read `error` for the typed * envelope; do NOT trust `chain`/`coMovers`. */ export type CorrelationStatus = 'success' | 'no_signal' | 'anchor_no_signal' | 'error'; export interface CorrelationResult { status: CorrelationStatus; /** Plain-English summary the agent or the report renderer can surface. */ human_summary: string; anchor: string; anchorRateChange: number; /** Sorted by lead time (most-leading first). The final entry is the anchor. */ chain: ChainLink[]; /** Co-movers that didn't make the chain but have above-floor signal. */ coMovers: CoMover[]; metadata: { patternsAnalyzed: number; queriesExecuted: number; wallTimeMs: number; softTimeoutHit: boolean; hardTimeoutHit: boolean; }; /** * Populated when `status === 'error'`. Structural failure the agent can * branch on (retryable, backoff hint, etc.). */ error?: PrimitiveError; /** * Sub-query failures that did NOT abort the correlation (Phase B anchor * rate non-fatal swallow, Phase C per-(mover, offset) lag queries). * Surfaced so the caller can see what got skipped instead of guessing * from a degraded chain. */ partialFailures?: PrimitiveError[]; } export interface CorrelationOptions { env: EnvConfig; metricsEnv: string; anchor: string; inflectionTimestamp: number; baselineOffsetSeconds: number; window: string; depth: 'shallow' | 'normal' | 'deep'; thresholds: InvestigateThresholds; /** Service label to scope the universe when depth != "deep". */ scopeService?: string; /** Event-count metric to use for correlation. */ metricName?: string; } export declare function runAcuteSpikeCorrelation(opts: CorrelationOptions): Promise;