Skip to main content

Documentation Index

Fetch the complete documentation index at: https://worldmonitor.app/docs/llms.txt

Use this file to discover all available pages before exploring further.

Known drift, tracked in #3789. The server-side BASELINE_RISK and EVENT_MULTIPLIER tables disagree with the frontend CURATED_COUNTRIES table for 7 countries (AF, EG, IQ, JP, KR, LB, QA). The values published below reflect what the server actually applies today; the frontend may display different values for those 7 countries until reconciliation lands. API consumers should treat the server values as authoritative.
Published methodology note for the Composite Instability Index (CII) and the Strategic Risk roll-up surfaced by GET /api/intelligence/risk-scores (proto worldmonitor.intelligence.v1.GetRiskScoresResponse). These weights are editorial — authored by the WorldMonitor intelligence team based on internal review of historical incidents and current geopolitical posture. They are not derived from a published academic index, a peer-reviewed paper, or a third-party risk product. Treat the scores as opinionated, not empirical. The point of this note is to make the opinions inspectable so downstream consumers can decide whether they agree. The on-the-wire methodology_version field on every CiiScore reflects which revision of this document was active when the score was computed. The current version is v1.
Heads up — coefficient changes. Any edit to the per-country baselines, event multipliers, or the strategic-risk roll-up coefficients MUST come with a bump of CII_FORMULA_VERSION in server/worldmonitor/intelligence/v1/_risk-config.ts, an update to this document in the same commit, and a public CHANGELOG entry. Tests in tests/cii-scoring.test.mts enforce that this document lists every country code in CURATED_COUNTRIES.

1. The four CII components

Each Tier-1 country gets four sub-scores in the 0–100 range. These are exposed on the wire as CiiComponents:
Wire fieldEditorial meaning
cii_contribution (Unrest)Civil disorder pressure: ACLED protests + riots, fatalities from those events, and confirmed internet/power outages. Reflects pre-violent friction.
geo_convergence (Conflict)Kinetic activity: ACLED battles, explosions/remote violence, and violence-against-civilians events, plus Iran-region strike intensity. Square-root fatality scaling prevents single-event saturation.
military_activity (Security)Hard-security tempo near the country: GPS-jamming hex density (high vs medium severity) over the country bounding box.
news_activity (Information)Information-environment pressure: weighted count of classified critical/high/medium news headlines geo-attributed to the country.
The four components are weighted into the headline combinedScore:
eventScore = U * 0.25 + C * 0.30 + S * 0.20 + I * 0.25

composite = baseline * 0.4
          + eventScore * 0.6
          + climateBoost     (≤ 15)
          + cyberBoost       (≤ 10)
          + fireBoost        (≤  8)
          + advisoryBoost    (≤ 15)
          + orefBlendBoost   (IL only, ≤ 25)
          + displacementBoost (≤ 20)
composite is then clamped to [floor, 100] where floor is the larger of:
  • UCDP floor: 70 if a UCDP war-level event is active, 50 if a minor conflict-level event is active, else 0.
  • State Department advisory floor: 60 for “do not travel”, 50 for “reconsider travel”, else 0.
The dynamicScore exposed on the wire is composite − staticBaseline — i.e. the live-event contribution above the per-country baseline.

2. Per-country baselineRisk and eventMultiplier

These are the editorial values applied server-side. They are mirrored from the CURATED_COUNTRIES table in src/config/countries.ts, which the frontend uses for client-side CII rendering. Where the two have drifted, the server values below are authoritative for the API response (issue #3725 calls out the drift and is the source of this published note). Reconciliation tracked in #3789 — the 7 drift cells called out in the rightmost column below are a deliberate known-issue, not an oversight. That issue weighs server-authoritative vs frontend-authoritative vs a single-source-of-truth refactor and will land the reconciliation in a follow-up PR.
CodeCountrybaselineRisk (server)eventMultiplier (server)Drift vs CURATED_COUNTRIES
AEUnited Arab Emirates101.5
AFAfghanistan450.8frontend uses baseline 15, multiplier 1
BRBrazil150.6
CNChina252.5
CUCuba452.0
DEGermany50.5
EGEgypt201.0frontend uses baseline 15
FRFrance100.6
GBUnited Kingdom50.5
ILIsrael450.7
INIndia200.8
IQIraq401.2frontend uses baseline 35, multiplier 1
IRIran402.0
JPJapan50.5frontend uses baseline 15, multiplier 1
KPNorth Korea453.0
KRSouth Korea150.8frontend uses multiplier 1
LBLebanon401.5frontend uses baseline 15, multiplier 1
MMMyanmar451.8
MXMexico351.0
PKPakistan351.5
PLPoland100.8
QAQatar100.8frontend uses baseline 15, multiplier 1
RURussia352.0
SASaudi Arabia202.0
SYSyria500.7
TRTurkey251.2
TWTaiwan301.5
UAUkraine500.8
USUnited States50.3
VEVenezuela401.8
YEYemen500.7
What baselineRisk does. It is the country’s “always-on” instability floor. Independent of any live event, the country starts each scoring cycle at baselineRisk * 0.4 and accumulates event-driven score on top. A country with baselineRisk = 5 (US, DE, GB, JP) needs much louder event signals to register a high combinedScore than a country with baselineRisk = 50 (UA, SY, YE). What eventMultiplier does. It scales the contribution of live ACLED events into the Unrest and Conflict components. The rationale is editorial: in information-rich, low-noise geographies (US, DE, GB, JP, FR with multipliers 0.3–0.6) we down-weight live events because the reporting density makes each individual event look bigger than it is in context. In signal-poor, high-relevance geographies (KP, CN, IR, RU with multipliers 2.0–3.0) we up-weight because every confirmed event there is disproportionately newsworthy. For countries where eventMultiplier < 0.7, unrest counts use log2(n+1) * multiplier * 5 instead of linear scaling, specifically to dampen US-style high-volume-low-intensity protest signals.

3. Strategic Risk roll-up

The global Strategic Risk score in StrategicRisk[0] is a weighted average of the top-5 highest-scoring countries’ combinedScore values:
top5         = ciiScores.slice(0, STRATEGIC_RISK_TOP_N)            # N = 5
weights      = [1.00, 0.85, 0.70, 0.55, 0.40]                       # 1 - i * 0.15
weightedAvg  = Σ(score_i * weight_i) / Σ(weight_i)
overallScore = min(100, round(weightedAvg * 0.70 + 15))             # banded to [15, 85]
The decay step, top-N window, scale-floor (15), and scale-factor (0.70) are all defined in server/worldmonitor/intelligence/v1/_risk-config.ts. Their rationale:
  • STRATEGIC_RISK_POSITIONAL_DECAY = 0.15 — the most-affected country gets full weight; weight reaches zero at position 6. Chosen so the slice size of 5 falls out naturally.
  • STRATEGIC_RISK_TOP_N = 5 — large enough to dilute single-country spikes, small enough that the score reflects the “very top” of the dashboard rather than a long tail.
  • STRATEGIC_RISK_SCALE_FLOOR = 15 — the global picture is never “all clear”. A baseline of 15 keeps the dial visually meaningful when every Tier-1 country is calm.
  • STRATEGIC_RISK_SCALE_FACTOR = 0.70 — combined with the floor, this compresses the weighted top-5 average from [0, 100] into [15, 85] before the final min(100). Prevents a single very-high country from saturating the global score.
The resulting severity band exposed on StrategicRisk.level is:
  • SEVERITY_LEVEL_HIGH if overallScore ≥ 70
  • SEVERITY_LEVEL_MEDIUM if 40 ≤ overallScore < 70
  • SEVERITY_LEVEL_LOW if overallScore < 40

4. What this score is and is not

It is a single number to help operators triage where to look first on a news-velocity dashboard. It is not a forecast, an insurance pricing input, or a substitute for travel-advisory guidance from a sovereign government. The published values in section 2 are editorial; reasonable analysts will disagree with individual entries. If you depend on these scores for any consequential decision, pin against the methodology_version field on each CiiScore, watch for version bumps in the public CHANGELOG, and consider the per-country weight you see in event_multiplier against your own ground truth before relying on the composite.