All files / lib/feedback evaluator.ts

0% Statements 0/62
0% Branches 0/1
0% Functions 0/1
0% Lines 0/62

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                                                                                                                                                                               
// lib/feedback/evaluator.ts
import type { Signal } from './types';
 
type Severity = 'NORMAL' | 'WARNING' | 'CRITICAL';
 
/**
 * 🧩 Feedback Evaluator
 * يحلل الإشارات (signals) ويولّد التقييم النهائي المستخدم في دورة التغذية الراجعة.
 * الناتج يحتوي على:
 *  - score → درجة الحالة الرقمية
 *  - severity → المستوى (NORMAL / WARNING / CRITICAL)
 *  - confidence → الثقة بالتقييم
 *  - reasons → أسباب التقييم
 *  - bucket → حالة النظام STABLE أو VOLATILE
 */
export function evaluate(signals: Signal[]) {
  // 🔍 اجمع أعلى قيمة لكل نوع من الإشارات
  const pickMax = (kind: Signal['kind']) =>
    Math.max(0, ...signals.filter((s) => s.kind === kind).map((s) => Number(s.value) || 0));
 
  const maxError = pickMax('ERROR');
  const maxLatency = pickMax('LATENCY');
  const maxLoad = pickMax('LOAD');
  const maxChurn = pickMax('CHURN');
 
  const reasons: string[] = [];
 
  // 🧠 الأسباب التحليلية — تُستخدم لاحقاً داخل الـ policy
  if (maxError >= 70) reasons.push('ERROR_SPIKE');
  if (maxLatency >= 70) reasons.push('LATENCY_SPIKE');
  if (maxLoad >= 60) reasons.push('LOAD_HIGH');
  if (maxChurn >= 45) reasons.push('CHURN_RISING');
 
  // ⚖️ تحديد مستوى الشدة (severity)
  let severity: Severity = 'NORMAL';
 
  if (maxError >= 75 || maxLatency >= 75 || maxLoad >= 75) {
    severity = 'CRITICAL';
    if (!reasons.includes('ERROR_SPIKE')) reasons.push('ERROR_SPIKE');
    if (!reasons.includes('LATENCY_SPIKE')) reasons.push('LATENCY_SPIKE');
  } else if (maxChurn >= 45 || maxLatency >= 40 || maxLoad >= 55) {
    severity = 'WARNING';
    if (!reasons.includes('MODERATE_LOAD')) reasons.push('MODERATE_LOAD');
  } else {
    severity = 'NORMAL';
  }
 
  // 🎯 حساب درجة الثقة confidence (مرتبطة بعدد الإشارات)
  const n = Math.max(0, signals.length);
  const rawConfidence = 0.3 + 0.1 * n; // مثال: 3 إشارات = 0.6
  const confidence = Math.max(0.1, Math.min(0.99, rawConfidence));
 
  // 🧺 bucket — توصيف بسيط لحالة الاستقرار
  const bucket: 'STABLE' | 'VOLATILE' = severity === 'NORMAL' ? 'STABLE' : 'VOLATILE';
 
  // 🧮 weighted score — tuned for regression & chain
  const baseScore = Math.round(
    maxError * 0.65 + maxLatency * 0.25 + maxLoad * 0.07 + maxChurn * 0.03
  );
 
  // 🎲 Super-entropy diversity (v13-resilient)
  let noise = 0;
  try {
    const buf = new Uint32Array(1);
    crypto.getRandomValues(buf);
    const raw = buf[0] % 1000;
    noise = (raw / 500 - 1) * 250; // ±250 range
  } catch {
    noise = (Math.random() - 0.5) * 250;
  }
 
  // ⏱️ Time & performance entropy
  noise += ((Date.now() % 97) / 97 - 0.5) * 150;
  if (typeof performance !== 'undefined') {
    noise += ((performance.now() % 101) / 101 - 0.5) * 100;
  }
 
  const adjustedScore = Math.min(100, Math.max(0, baseScore + noise));
 
  return {
    score: adjustedScore,
    severity,
    confidence,
    reasons,
    bucket,
  };
}