* feat(forecasts): add EMA-based threat velocity spike detection
- New pure-math module _ema-threat-engine.mjs: updateWindow, computeWindowStats,
computeEmaWindows, computeRisk24h with ALPHA=0.3, 24-entry sliding window
- Add ACLED (conflict:acled:v1:all:0:0) and EMA windows (conflict:ema-windows:v1)
to readInputKeys() Redis pipeline batch
- updateEmaWindows() merges ACLED + UCDP event counts, computes z-scores, persists
updated windows with 26h TTL before domain detectors run
- detectConflictScenarios and detectUcdpConflictZones inject velocity_spike signals
(weight 0.35, +0.08 prob boost) when risk24h >= 75
* fix(ema): delta counts + EMA-based z-score in threat engine
- computeEmaWindows: track lastRawCount per country, append delta
(currentRaw - priorRaw) instead of absolute snapshot totals
- Union prior + current keys so countries absent from current snapshot
get delta=0 (not silently dropped)
- First run: priorRaw = currentRaw so initial delta is 0, not a spike
- Clamp delta >= 0 to handle snapshot window shrinkage
- computeRisk24h: z-score now uses window.ema instead of raw last entry,
so ALPHA=0.3 smoothing actually dampens single-run spikes before alerting
* fix(ema): timestamp-based 24h event counting replaces unreliable snapshot delta
- Remove lastRawCount delta logic that suppressed real acceleration in rolling source windows
- computeEmaWindows now counts events with event_date/date_start >= now-24h directly from snapshot objects
- Add private normalizeCountry() helper; add nowMs param for testability
- Remove lastRawCount from WindowState typedef (no longer stored or persisted)
* fix(ema): seed-meta write + dead code cleanup
- P1: write seed-meta:conflict:ema-windows:v1 after EMA persist so health monitoring detects silent failures
- P2: remove dead `last` variable from computeWindowStats
- P2: remove redundant full O(n) EMA sweep in computeWindowStats (incremental EMA in updateWindow is authoritative)
- P2: remove dead `?? 0` guard on `prob` in detectConflictScenarios (already a number at that point)