v17: Conflict-Realism Calibration — War Zones Now Score Accurately

The geo scoring engine was built for breaking news but miscalibrated for ongoing conflicts. A missile strike from 18 hours ago was nearly dead in the recency window. Countries at war were averaged down by their own routine diplomatic and economic coverage. v17 fixes all of that: longer half-life, tighter scoring thresholds, a smaller article pool, and a heatmap that colors by peak signal rather than diluted average.

The original geo scoring system was designed around a simple assumption: news is breaking news. Something happens, it gets reported, the signal spikes, and then it decays as the story is replaced by the next one. That assumption works for isolated incidents — a surprise election result, a natural disaster, a single cyber attack. It fails badly for sustained conflicts, where the "news" is not a single event but an ongoing situation generating dozens of articles per day, none of which individually looks alarming compared to an actual breaking story.

Russia and Ukraine are at war. Iran, Israel, Gaza, and Lebanon are in active conflict. Yet the geo scores for those countries were sitting in the 4–6 range — "elevated" at best. The problem was not bad data. The problem was that the scoring system was systematically discounting exactly the kind of sustained, high-intensity coverage that active war zones produce.

Four compounding problems

What changed

ParameterBefore (v16)After (v17)Rationale
Geo recency half-life6 hours24 hoursWars last months. A strike from yesterday is still a live signal.
Urgency thresholdkeywords / 8keywords / 64-keyword war headlines now score 6.7+ instead of 5.0
Sentiment thresholdwords / 6words / 44 negative words now maxes out sentiment instead of requiring 6
Geo article poolTop 100Top 30Concentrates score on highest-urgency articles; prevents routine coverage from diluting conflict signal
Geo blend weight27%40%Geopolitical news is the primary driver of world-threat perception
Heatmap color basisAll-article average per countryTop-10 scoring articles per countryColors reflect peak signal intensity, not diluted average across all mentions
Heatmap critical threshold≥ 8.0≥ 7.0Recalibrated for the new scoring range

Geo half-life: 6h → 24h

The exponential recency decay function is the same: recency = 10 × e^(−ageHours / halfLife). Only the halfLife parameter changes for geo articles. At 6 hours, an article 24 hours old scored 0.25/10 on recency — essentially zero. At 24 hours, that same article scores 3.7/10, still decaying but still contributing meaningfully to the signal. By 48 hours it scores 1.4/10; by 72 hours (the cutoff) it scores 0.5/10. This means sustained daily coverage of an active war zone accumulates properly rather than resetting every morning.

recency(t) = 10 × e^(−t / 24)   where t = article age in hours

Tighter thresholds

The urgency and sentiment thresholds were originally set for maximum caution — only truly overwhelming article content would score near 10. The problem is that war reporting is not "overwhelming" in keyword density; it is consistently severe. A headline matching 5 urgency keywords (war, attack, missile, killed, crisis) is an extremely serious article. With the old threshold it scored 6.25/10 on urgency. With the new threshold it scores 8.3/10 — which is accurate. Matching 4 negative sentiment words (dead, attack, critical, terror) now maxes out sentiment instead of requiring 6.

Geo pool: 100 → 30 articles

The geo score is the mean of the top-N scored geo articles. Averaging 100 articles means that 60–70 routine articles about the same country — economic policy, sports, cultural events — pull the mean down even when 30 of those articles are about active armed conflict. Reducing the pool to 30 means the score reflects the 30 most alarming geo stories in the last 72 hours. Routine coverage does not disappear from the system — it is still in Firestore, still displayed in the feed — it just no longer dilutes the scoring signal.

Heatmap: coloring by peak signal

The geo heatmap previously colored each country by the average score across all articles mentioning that country in the last 24 hours. Russia might appear in 40 articles — 5 about missile strikes scoring 8–9, and 35 about sanctions, energy prices, diplomatic statements, and sports scoring 2–4. The average was around 4.5, producing an "elevated" yellow color. v17 changes the basis to the mean of the top-10 highest-scoring articles per country. The same Russia example now produces a mean of 8.2 from its five highest-scoring conflict articles — correctly rendering as critical red. Countries not in active conflict still render at their true level, because their top-10 articles are not war reports.

Rollout note

The new urgency and sentiment thresholds only apply to articles scored after the v17 deployment. Existing articles in Firestore have their scores cached and will not be automatically re-scored. As the 72-hour article window turns over — roughly by Saturday — all articles in the scoring pool will carry v17-calibrated scores. The recency half-life change, pool-size change, and blend weight change take effect on every poll cycle immediately, regardless of when individual articles were scored.