Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | // lib/reflection/evaluator.ts import { isVerbose } from './flags'; import { SIGNALS, type Signal, type SignalEvaluator, type EvaluationResult } from './types'; // ======================================== // Configuration (SLOs) // ======================================== const EVALUATORS: Record<string, SignalEvaluator & { direction?: 'higher' | 'lower' }> = { [SIGNALS.WINDOW_CHURN]: { signal: SIGNALS.WINDOW_CHURN, // higher churn is worse direction: 'higher', slos: [ { threshold: 4, status: 'CRITICAL' }, // > 4 events/sec { threshold: 3, status: 'WARNING' }, // > 3 events/sec ], }, [SIGNALS.FOCUS_STABILITY]: { signal: SIGNALS.FOCUS_STABILITY, // lower stability is worse (0..1 range) direction: 'lower', slos: [ { threshold: 0.4, status: 'CRITICAL' }, // < 0.4 is critical { threshold: 0.6, status: 'WARNING' }, // < 0.6 is warning ], }, [SIGNALS.LATENCY_SUMMARY]: { signal: SIGNALS.LATENCY_SUMMARY, slos: [], }, [SIGNALS.IDLE_RATIO]: { signal: SIGNALS.IDLE_RATIO, slos: [], }, [SIGNALS.WINDOW_LIFETIME]: { signal: SIGNALS.WINDOW_LIFETIME, slos: [], }, }; // ======================================== // Public API // ======================================== /** * Evaluates a given signal against its configured SLOs. * @param signal The signal to evaluate. * @returns An EvaluationResult object. */ export function evaluateSignal(signal: Signal): EvaluationResult { const evaluator = EVALUATORS[signal.type as string]; if (!evaluator || evaluator.slos.length === 0) { return { signal, status: 'NORMAL', slo: null, timestamp: performance.now(), }; } // Iterate through SLOs (ordered most to least critical). Honor direction. const direction = (evaluator as any).direction ?? 'higher'; for (const slo of evaluator.slos) { const breached = direction === 'higher' ? signal.value > slo.threshold : signal.value < slo.threshold; if (breached) { const result: EvaluationResult = { signal, status: slo.status, slo, timestamp: performance.now(), }; if (isVerbose()) { console.log( `[Reflection/Evaluator] Signal evaluated: ${signal.type} is ${slo.status}`, result ); } return result; } } // If no threshold was breached, the status is normal const result: EvaluationResult = { signal, status: 'NORMAL', slo: null, timestamp: performance.now(), }; if (isVerbose()) { console.log(`[Reflection/Evaluator] Signal evaluated: ${signal.type} is NORMAL`, result); } return result; } /** * Convenience: evaluate an array or object of signals and return EvaluationResult[] */ export function evaluateSignals(signals: any): EvaluationResult[] { const list: Signal[] = []; if (Array.isArray(signals)) { for (const s of signals) list.push(s); } else if (signals && typeof signals === 'object') { for (const key of Object.keys(signals)) { const val = (signals as any)[key]; if (val && typeof val === 'object' && 'type' in val) list.push(val as Signal); } } return list.map((s) => evaluateSignal(s)); } /** * Test helper (no-op for now) to reset evaluator-internal state. */ export function _resetEvaluatorForTests(): void { // reserved for future internal caches } |