* feat(resilience): refresh benchmark sources — INFORM 2026 API + UNDP HDI + WRI via HDX
Replaces stale/broken external sources with fresh, authoritative ones.
Before: 4 sources hardcoded to year-stamped CSV URLs that all drift annually. By today: INFORM_Composite_2024.csv was 404 (JRC reorganized to XLSX+API), FSI's latest downloadable bulk data is 2023 XLSX (no 2024/2025 CSV published), WRI's weltrisikobericht.de/download/2944 URL 404'd, and ND-GAIN's nd_gain_countryindex_2023data.csv URL now serves the 2023 report PDF (silently parsed to 0 rows while logging '2.4 MB fetched live').
After: 3 sources, all live, all authoritative, all fresh. INFORM Risk 2026 via JRC's JSON API (WorkflowId=505, 191 countries, plain UA bypasses the Chrome-UA bot-check). UNDP HDI from the 2025 HDR composite-indices time-series CSV (191 countries, 2023 data). WorldRiskIndex 2024 via the HDX CDN multi-year 'trend' CSV (192 countries, stable, not geo-blocked).
FSI dropped entirely (no fresh bulk data). ND-GAIN deferred until the seeder can unzip the 2026 archive (ships only as ZIP now). Hypothesis count 4 → 3, WM-resilience↔HDI is positive (higher HDI → higher resilience), keeping the negative correlations for INFORM (risk) and WorldRiskIndex (risk).
Smoke-tested against production: all three URLs return valid data in 0.2-3.4s with 191-192 countries each. 25/25 unit tests pass, biome clean, typecheck clean.
* fix(resilience): guard INFORM rows.length + drop unused NDGAIN_ZIP_URL constant
Two reviewer P2s on PR #3068.
1. fetchInformGlobal logged rows.length BEFORE the Array.isArray guard. A null/object response body would throw 'Cannot read properties of null', the surrounding catch would swallow it, and the user-facing log would say 'Live fetch failed for INFORM' as if it were a network error. Now type-checks before logging — payload-shape regressions surface as 'expected JSON array, got object' instead of a misleading network error string.
2. NDGAIN_ZIP_URL was a doc-only constant never referenced anywhere — risked a noUnusedVariables lint failure. Demoted to a regular comment with the same content + an explicit DO-NOT-RESTORE warning about the silent PDF-served-as-CSV trap on the legacy URL.