Skip to content

feat: universal country detection — CII scoring for all countries#344

Merged
koala73 merged 1 commit into
mainfrom
feat/universal-country-detection
Feb 24, 2026
Merged

feat: universal country detection — CII scoring for all countries#344
koala73 merged 1 commit into
mainfrom
feat/universal-country-detection

Conversation

@koala73

@koala73 koala73 commented Feb 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Removes all TIER1 gates from 9 ingest functions so any country with data gets a CII score (previously silently discarded for non-TIER1 countries)
  • Creates single source of truth for country metadata in src/config/countries.ts — replaces 13+ hardcoded maps across 8 files with centralized CURATED_COUNTRIES (30 entries with expert-tuned params) and GeoJSON-backed universal registry (~240 countries)
  • Fixes 5 bugs in HOTSPOT_COUNTRY_MAP: brussels→BE (was FR), baghdad→IQ (was IR), beirut→LB (was IR), doha→QA (was SA), abudhabi→AE (was SA), adds nuuk→GL

Key changes

File Change
src/config/countries.ts CURATED_COUNTRIES with separate scoringKeywords/searchAliases, canonical HOTSPOT_COUNTRY_MAP, getHotspotCountries() helper
src/services/country-geometry.ts ISO3→ISO2, name→ISO2 indexes, Taiwan CN-TWTW override, word-boundary country name matchers
src/services/country-instability.ts Removed 9 TIER1 gates, deleted 7 hardcoded maps, ensureISO2() normalizer, observability counters
src/App.ts Removed COUNTRY_BOUNDS + COUNTRY_ALIASES, migrated all consumers to centralized config
5 other consumer files Replaced local hardcoded maps with centralized imports

Design decisions

  • TIER1 (23 countries) unchanged — keeps exact same hand-tuned baseline risk and event multipliers
  • CURATED_COUNTRIES (30 entries) is a superset including non-TIER1 countries from old COUNTRY_ALIASES (KR, IQ, AF, LB, EG, JP, QA)
  • Non-curated countries get DEFAULT_BASELINE_RISK=15 and DEFAULT_EVENT_MULTIPLIER=1.0
  • HAPI fetch scope kept conservative — don't expand to 240 countries to avoid API spam
  • Longest-first word-boundary regex prevents "Guinea" matching inside "Papua New Guinea"

Test plan

  • tsc --noEmit passes (verified)
  • build:full passes (verified)
  • Click Egypt/Colombia on map → country brief opens with CII score
  • Click Taiwan → resolves as TW (not CN-TW)
  • Search "Egypt" → appears in search results
  • All 23 TIER1 countries retain exact same scores
  • Hotspot escalation scores still compute (no broken hotspot→country mappings)

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Feb 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Feb 24, 2026 11:01pm
worldmonitor-finance Ready Ready Preview, Comment Feb 24, 2026 11:01pm
worldmonitor-happy Ready Ready Preview, Comment Feb 24, 2026 11:01pm
worldmonitor-startup Ready Ready Preview, Comment Feb 24, 2026 11:01pm

Request Review

Remove TIER1 gates from all 9 ingest functions so any country with data
gets a CII score. TIER1 keeps expert-tuned baselines/multipliers via
CURATED_COUNTRIES; non-curated countries use sensible defaults (baseline=15,
multiplier=1.0).

Key changes:
- country-geometry.ts: ISO3→ISO2, name→ISO2 indexes from GeoJSON (258
  features), Taiwan CN-TW override, word-boundary country name matchers
- config/countries.ts: 30-entry CURATED_COUNTRIES with separate scoring
  keywords vs search aliases, canonical HOTSPOT_COUNTRY_MAP with bug fixes
  (brussels→BE, baghdad→IQ, beirut→LB, doha→QA, abudhabi→AE, +nuuk→GL)
- country-instability.ts: delete 7 hardcoded maps, use centralized config,
  ensureISO2() normalizer, unmapped-rate observability counters
- App.ts: remove COUNTRY_BOUNDS + COUNTRY_ALIASES, use GeoJSON + curated
  config, expand search to all scored countries
- signal-aggregator.ts: GeoJSON-based coordsToCountry replacing hardcoded
  bounding boxes
- Remaining consumers (story-data, hotspot-escalation, cross-module-
  integration, conflict/index) updated to centralized sources
@koala73
koala73 force-pushed the feat/universal-country-detection branch from 2f58049 to ca18411 Compare February 24, 2026 23:00
@koala73
koala73 merged commit 32a53f3 into main Feb 24, 2026
1 of 5 checks passed
koala73 added a commit that referenced this pull request Feb 24, 2026
## What's Changed

### Performance
- perf: defer YouTube/map init and stagger data loads to reduce blocking time (#287)

### Features
- feat: universal country detection — CII scoring for all countries (#344)
- feat: add Mexico as CII hotspot for cartel/security monitoring (#327)
- feat: add Mexico and LatAm security feeds for instability coverage (#325)
- feat: add category pills and search filter to Panels tab (#322)
- feat: consolidate settings into unified tabbed modal (#319)
- feat: add Island Times (Palau) RSS feed (#317)
- feat: add AI Flow settings popup for web-only AI provider control (#314)
- feat: optional channels with tab-based region browse UI (#295)
- feat: custom channel management (#282)
- feat: add Bild RSS feed scoped to German locale (#312)

### Bug Fixes
- fix: suppress notification sound when popup alerts are disabled
- fix: prevent entity conflation in pane summarization (#341)
- fix: add Mexico to COUNTRY_BOUNDS and COUNTRY_ALIASES (#338)
- fix: make OpenSky cache TTLs env-configurable (#333)
- fix: serialize OpenSky requests with global 429 cooldown (#332)
- fix: replace RSSHub feeds with native/Google News alternatives (#331)
- fix: OpenSky auth resilience — retry, IPv4, no negative cache on auth fail (#329)
- fix: add CARTO and OpenStreetMap attribution to map (#323)
- fix: add drag cleanup handlers and suppress click after drag-drop (#315)
- fix: replace HTML5 drag API with mouse events for WKWebView (#313)
- fix: open channel settings as inline modal instead of separate window (#311)
- fix: sync YouTube live panel mute state with native player controls (#285)
- fix: strip Ollama reasoning tokens from summaries (#299)
- fix: open external links in system browser on Tauri desktop (#297)
- fix: add User-Agent and Cloudflare 403 detection to secret validation (#296)
- fix: infra cost optimizations round 2 (#275)
- fix: enforce military bbox filtering (#284)
- fix: infrastructure cost optimizations across caching, polling, batching (#283)
- fix: circuit breaker persistent cache with safety fixes (#281)
- fix: immediately refresh stale services when tab regains focus (#277)

### Security
- Security hardening: SSRF protection, auth gating, and token generation (#343)
- Harden Railway relay auth, caching, and proxy routing (#320)
- Build/runtime hardening and dependency security updates (#286)
- fix: harden embed postMessage origin check (#302)
koala73 added a commit that referenced this pull request Feb 25, 2026
## What's Changed

### Performance
- perf: defer YouTube/map init and stagger data loads (#287)

### Features
- feat: universal country detection — CII scoring for all countries (#344)
- feat: add Mexico as CII hotspot (#327)
- feat: add Mexico and LatAm security feeds (#325)
- feat: add category pills and search filter to Panels tab (#322)
- feat: consolidate settings into unified tabbed modal (#319)
- feat: optional channels with tab-based region browse UI (#295)
- feat: custom channel management (#282)

### Bug Fixes
- fix: suppress notification sound when popup alerts are disabled
- fix: prevent entity conflation in pane summarization (#341)
- fix: add Mexico to COUNTRY_BOUNDS and COUNTRY_ALIASES (#338)
- fix: OpenSky cache TTLs, serialization, and auth resilience (#329-#333)
- fix: replace RSSHub feeds with native/Google News alternatives (#331)
- fix: replace HTML5 drag API with mouse events for WKWebView (#313)
- fix: sync YouTube mute state with native player controls (#285)
- fix: strip Ollama reasoning tokens from summaries (#299)
- fix: infra cost optimizations (#275, #283)
- fix: circuit breaker persistent cache (#281)
- fix: immediately refresh stale services on tab focus (#277)

### Security
- Security hardening: SSRF protection, auth gating, token generation (#343)
- Harden Railway relay auth, caching, and proxy routing (#320)
- Build/runtime hardening and dependency security updates (#286)
koala73 added a commit that referenced this pull request Feb 25, 2026
…346)

* fix: suppress notification sound when popup alerts are disabled

Badge playSound() was firing on new findings regardless of the
"Pop up new alerts" toggle. Gate sound on popupEnabled so both
the modal and audio respect the user preference.

* chore: bump version to 2.5.7 with changelog

## What's Changed

### Performance
- perf: defer YouTube/map init and stagger data loads (#287)

### Features
- feat: universal country detection — CII scoring for all countries (#344)
- feat: add Mexico as CII hotspot (#327)
- feat: add Mexico and LatAm security feeds (#325)
- feat: add category pills and search filter to Panels tab (#322)
- feat: consolidate settings into unified tabbed modal (#319)
- feat: optional channels with tab-based region browse UI (#295)
- feat: custom channel management (#282)

### Bug Fixes
- fix: suppress notification sound when popup alerts are disabled
- fix: prevent entity conflation in pane summarization (#341)
- fix: add Mexico to COUNTRY_BOUNDS and COUNTRY_ALIASES (#338)
- fix: OpenSky cache TTLs, serialization, and auth resilience (#329-#333)
- fix: replace RSSHub feeds with native/Google News alternatives (#331)
- fix: replace HTML5 drag API with mouse events for WKWebView (#313)
- fix: sync YouTube mute state with native player controls (#285)
- fix: strip Ollama reasoning tokens from summaries (#299)
- fix: infra cost optimizations (#275, #283)
- fix: circuit breaker persistent cache (#281)
- fix: immediately refresh stale services on tab focus (#277)

### Security
- Security hardening: SSRF protection, auth gating, token generation (#343)
- Harden Railway relay auth, caching, and proxy routing (#320)
- Build/runtime hardening and dependency security updates (#286)
@koala73
koala73 deleted the feat/universal-country-detection branch February 25, 2026 08:01
andreteow pushed a commit to andreteow/worldmonitor-a47 that referenced this pull request Feb 25, 2026
…ala73#344)

Remove TIER1 gates from all 9 ingest functions so any country with data
gets a CII score. TIER1 keeps expert-tuned baselines/multipliers via
CURATED_COUNTRIES; non-curated countries use sensible defaults (baseline=15,
multiplier=1.0).

Key changes:
- country-geometry.ts: ISO3→ISO2, name→ISO2 indexes from GeoJSON (258
  features), Taiwan CN-TW override, word-boundary country name matchers
- config/countries.ts: 30-entry CURATED_COUNTRIES with separate scoring
  keywords vs search aliases, canonical HOTSPOT_COUNTRY_MAP with bug fixes
  (brussels→BE, baghdad→IQ, beirut→LB, doha→QA, abudhabi→AE, +nuuk→GL)
- country-instability.ts: delete 7 hardcoded maps, use centralized config,
  ensureISO2() normalizer, unmapped-rate observability counters
- App.ts: remove COUNTRY_BOUNDS + COUNTRY_ALIASES, use GeoJSON + curated
  config, expand search to all scored countries
- signal-aggregator.ts: GeoJSON-based coordsToCountry replacing hardcoded
  bounding boxes
- Remaining consumers (story-data, hotspot-escalation, cross-module-
  integration, conflict/index) updated to centralized sources
andreteow pushed a commit to andreteow/worldmonitor-a47 that referenced this pull request Feb 25, 2026
…oala73#346)

* fix: suppress notification sound when popup alerts are disabled

Badge playSound() was firing on new findings regardless of the
"Pop up new alerts" toggle. Gate sound on popupEnabled so both
the modal and audio respect the user preference.

* chore: bump version to 2.5.7 with changelog

## What's Changed

### Performance
- perf: defer YouTube/map init and stagger data loads (koala73#287)

### Features
- feat: universal country detection — CII scoring for all countries (koala73#344)
- feat: add Mexico as CII hotspot (koala73#327)
- feat: add Mexico and LatAm security feeds (koala73#325)
- feat: add category pills and search filter to Panels tab (koala73#322)
- feat: consolidate settings into unified tabbed modal (koala73#319)
- feat: optional channels with tab-based region browse UI (koala73#295)
- feat: custom channel management (koala73#282)

### Bug Fixes
- fix: suppress notification sound when popup alerts are disabled
- fix: prevent entity conflation in pane summarization (koala73#341)
- fix: add Mexico to COUNTRY_BOUNDS and COUNTRY_ALIASES (koala73#338)
- fix: OpenSky cache TTLs, serialization, and auth resilience (koala73#329-koala73#333)
- fix: replace RSSHub feeds with native/Google News alternatives (koala73#331)
- fix: replace HTML5 drag API with mouse events for WKWebView (koala73#313)
- fix: sync YouTube mute state with native player controls (koala73#285)
- fix: strip Ollama reasoning tokens from summaries (koala73#299)
- fix: infra cost optimizations (koala73#275, koala73#283)
- fix: circuit breaker persistent cache (koala73#281)
- fix: immediately refresh stale services on tab focus (koala73#277)

### Security
- Security hardening: SSRF protection, auth gating, token generation (koala73#343)
- Harden Railway relay auth, caching, and proxy routing (koala73#320)
- Build/runtime hardening and dependency security updates (koala73#286)
facusturla pushed a commit to facusturla/worldmonitor that referenced this pull request Feb 27, 2026
…ala73#344)

Remove TIER1 gates from all 9 ingest functions so any country with data
gets a CII score. TIER1 keeps expert-tuned baselines/multipliers via
CURATED_COUNTRIES; non-curated countries use sensible defaults (baseline=15,
multiplier=1.0).

Key changes:
- country-geometry.ts: ISO3→ISO2, name→ISO2 indexes from GeoJSON (258
  features), Taiwan CN-TW override, word-boundary country name matchers
- config/countries.ts: 30-entry CURATED_COUNTRIES with separate scoring
  keywords vs search aliases, canonical HOTSPOT_COUNTRY_MAP with bug fixes
  (brussels→BE, baghdad→IQ, beirut→LB, doha→QA, abudhabi→AE, +nuuk→GL)
- country-instability.ts: delete 7 hardcoded maps, use centralized config,
  ensureISO2() normalizer, unmapped-rate observability counters
- App.ts: remove COUNTRY_BOUNDS + COUNTRY_ALIASES, use GeoJSON + curated
  config, expand search to all scored countries
- signal-aggregator.ts: GeoJSON-based coordsToCountry replacing hardcoded
  bounding boxes
- Remaining consumers (story-data, hotspot-escalation, cross-module-
  integration, conflict/index) updated to centralized sources
facusturla pushed a commit to facusturla/worldmonitor that referenced this pull request Feb 27, 2026
…oala73#346)

* fix: suppress notification sound when popup alerts are disabled

Badge playSound() was firing on new findings regardless of the
"Pop up new alerts" toggle. Gate sound on popupEnabled so both
the modal and audio respect the user preference.

* chore: bump version to 2.5.7 with changelog

## What's Changed

### Performance
- perf: defer YouTube/map init and stagger data loads (koala73#287)

### Features
- feat: universal country detection — CII scoring for all countries (koala73#344)
- feat: add Mexico as CII hotspot (koala73#327)
- feat: add Mexico and LatAm security feeds (koala73#325)
- feat: add category pills and search filter to Panels tab (koala73#322)
- feat: consolidate settings into unified tabbed modal (koala73#319)
- feat: optional channels with tab-based region browse UI (koala73#295)
- feat: custom channel management (koala73#282)

### Bug Fixes
- fix: suppress notification sound when popup alerts are disabled
- fix: prevent entity conflation in pane summarization (koala73#341)
- fix: add Mexico to COUNTRY_BOUNDS and COUNTRY_ALIASES (koala73#338)
- fix: OpenSky cache TTLs, serialization, and auth resilience (koala73#329-koala73#333)
- fix: replace RSSHub feeds with native/Google News alternatives (koala73#331)
- fix: replace HTML5 drag API with mouse events for WKWebView (koala73#313)
- fix: sync YouTube mute state with native player controls (koala73#285)
- fix: strip Ollama reasoning tokens from summaries (koala73#299)
- fix: infra cost optimizations (koala73#275, koala73#283)
- fix: circuit breaker persistent cache (koala73#281)
- fix: immediately refresh stale services on tab focus (koala73#277)

### Security
- Security hardening: SSRF protection, auth gating, token generation (koala73#343)
- Harden Railway relay auth, caching, and proxy routing (koala73#320)
- Build/runtime hardening and dependency security updates (koala73#286)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant