Data audit
Every number on Wisdom traces to a public source. Here are our methods, our coverage gaps, our known weaknesses, and our formulas — published the same way the World Bank and IMF publish theirs.
- World Bank Open Data API
- WHO Global Health Observatory
- Mo Ibrahim IIAG
- UN World Population Prospects
- UNESCO UIS · FAO · IPCC · UNCTAD
- ISS African Futures (forecasts)
- AU / AUDA-NEPAD (comparison only)
- scripts/ingest/world-bank.ts — pulls API
- scripts/ingest/mo-ibrahim-iiag.ts — CSV
- scripts/ingest/indicators-registry.ts — maps 20 AU goals → source codes
- scripts/ingest/african-countries.ts — 55 ISO codes
- scripts/ingest/african-population.ts — UN WPP weights
- data/ingested/world-bank.json (21 indicators)
- data/ingested/mo-ibrahim-iiag.json (1 indicator)
- data/ingested/manifest.json (timestamps)
- pan-african-literature-database.json (561 works)
- lib/agenda-2063-live.ts — continentalAggregate() · calculateProgress() · getCoverageStats()
- lib/futures-data.ts — three-scenario forecasts (Failure / Current / Possible)
- lib/literature-data.ts — search · filter · get-by-id
- /africa-2050 — Our reality + Our goals (live Agenda 2063 scoring)
- /futures — Three paths to 2043
- /audit — This page (methodology disclosure)
- /browse · /work/[id] · /themes — Literature archive
- /ask — AI assistant (calls MCP literature tools)
Sources are external and authoritative. We deliberately don't trust AU self-reported numbers — they're widely seen as politically optimistic (Goal 8 "United Africa" jumped 12% → 98% in two years per their 2022 report). Instead we pull from the World Bank, WHO GHO, Mo Ibrahim IIAG, UN WPP, UNESCO UIS, FAO, and ISS African Futures. AU's published scores appear only as comparison benchmarks.
The indicator registry is the contract. scripts/ingest/indicators-registry.ts declares each indicator with its goal, aspiration, source URL, baseline, target, and direction. Ingestion scripts know how to fetch each sourceCode from each source. Aggregation scripts know how to compute progress from baseline → current → target. One file, one source of truth.
Storage is plain JSON committed to git. The GitHub Action runs npx tsx scripts/ingest/world-bank.ts every Sunday at 03:00 UTC, fetches every indicator × every country, computes continental aggregates, writes JSON, commits to the branch, Vercel rebuilds. No live API calls at request time — pages render fast and survive when source APIs are slow.
Methodology lives in the read layer. lib/agenda-2063-live.ts exposes continentalAggregate() (both simple-mean and population-weighted), calculateProgress() (refuses to invent confidence when target===baseline or current is null), and getCoverageStats() (surfaces missingness so the composite score isn't misread).
Forecasts are a separate layer. lib/futures-data.ts holds the three-scenario data (Failure / Current Path / Possible Africa). Forecasting is fundamentally different from measurement — you need a simulation model (we use ISS's IFs platform via Pardee Institute), not linear extrapolation.
| Aspiration | Goals total | Goals with data | Missing goals | Our score | AU 2021 |
|---|---|---|---|---|---|
| #1Prosperous Africa | 7 | 6 | Goals 6 | 23% | 37% |
| #2Integrated Africa | 3 | 1 | Goals 8, 9 | 32% | 84% |
| #3Good Governance | 2 | 1 | Goals 12 | 1% | 42% |
| #4Peaceful Africa | 3 | 0 | Goals 13, 14, 15 | no data | 63% |
| #5Cultural Identity | 1 | 0 | Goals 16 | no data | 45% |
| #6People-driven | 2 | 1 | Goals 18 | 10% | 67% |
| #7Global Partner | 2 | 0 | Goals 19, 20 | no data | 58% |
Indicators where the two methods diverge by more than 5% — i.e. where the choice matters:
| Indicator | Simple mean | Pop-weighted | Δ % |
|---|---|---|---|
| GDP per capita (current US$) | 2824.1 USD | 2019.3 USD | +39.9% |
| Under-5 mortality rate | 55.9 per 1,000 | 61.4 per 1,000 | -9.0% |
| Individuals using the internet | 42.1 % | 39.5 % | +6.6% |
Population weights from UN World Population Prospects 2024, 2023 medium-variant estimates. Total African population covered: 1.46B.
lib/agenda-2063-live.ts.Worked example: maternal mortality. Baseline 480/100k (2013) → target 70/100k (2063). Current: 394/100k. Progress = (480−394) / (480−70) = 86 / 410 = 21%.
Caveat: goals with zero indicators are skipped, not zeroed. So Aspiration 1 (6 of 7 goals covered) is comparable to other aspirations, but Aspirations 4, 5, 7 (zero coverage) return null, not zero.
Caveat: currently averaged across 4 of 7 aspirations. AU's published methodology uses all 7 with their own indicator weights — not directly comparable, intentionally.
Aspirations 4 (Peaceful Africa), 5 (Cultural Identity), and 7 (Global Partner) currently have zero indicators wired into the live data layer. Goals 6, 8, 9, 12, 13, 14, 15, 16, 18, 19, 20 are empty. Most are intentionally hard to quantify (cultural renaissance, federal unification) or politically contested (continental peace metrics).
Mitigation: Disclosed in the dashboard's coverage banner. Ingestion roadmap targets ACLED (peace), AfCFTA Secretariat (integration), Afrobarometer (governance perception).
The data file ships with hand-curated values from publicly known World Bank and IIAG figures rather than fetched live from APIs. The GitHub Action runs ingestion but the dev sandbox blocked outbound HTTPS during initial setup.
Mitigation: GitHub Actions workflow at .github/workflows/ingest-data.yml runs on Sundays 03:00 UTC and on-demand. First production run will replace seed values with API-fetched data.
The 'projected completion year' calculation in Our Goals uses simple linear extrapolation from the 2013 baseline. Real forecasting (capturing inter-sector dynamics, demographic transitions, capital accumulation) requires a simulation model.
Mitigation: Our Paths page uses ISS African Futures values, which are computed from the Pardee Institute's IFs simulation platform. Linear extrapolation is clearly labeled in the methodology footer of Our Goals.
World Bank, WHO, UNESCO, and national statistical offices may publish different values for the same conceptual indicator (different reference years, survey vs administrative, different aggregation rules). For example, World Bank life expectancy and WHO life expectancy can differ by 1-2 years for the same country-year.
Mitigation: Each indicator clearly cites its specific source. We don't blend across providers within a single indicator.
A 1.3-point gap between our hand-curated continental mean and the published IIAG 2024 figure. Likely explained by 1-2 country values being slightly off from the underlying scoreboard, plus the IIAG report including a richer set of category-weighted aggregations.
Mitigation: Once IIAG ingestion runs against an official CSV download (data/external/iiag-2024.csv), this gap closes. CSV parser stub is in place at scripts/ingest/mo-ibrahim-iiag.ts.
The Failure scenario on the Our Paths page is not from ISS African Futures. We assembled it from documented historical worst-case patterns: 1980s-1995 lost decade (SAP era), Zimbabwe 2000-2008 collapse, Sahel 2020-2024 coup contagion, +3°C climate trajectory.
Mitigation: Each Failure value cites its specific historical anchor in the indicator card's expandable methodology section.
The /api/ask route forwards user prompts to OpenRouter using a Wisdom-owned API key. It does not require authentication and has no per-IP or per-session rate limiting. A malicious or buggy client can hit this endpoint indefinitely and drain credits. Discovered in audit pass XII (2026-05-15).
Mitigation: Two reasonable fixes: (1) require Supabase auth on the route (re-use the same getCurrentUser pattern as the rest of the app), or (2) add an in-memory token bucket per IP and a daily cap per key. We've intentionally NOT shipped either fix without explicit product direction — both change runtime behaviour and may break dev. Documented openly so anyone deploying this can see the gap before going public.
Twelfth pass found and fixed: (1) /app/(app)/africa-2050/page.tsx imported ScoreDashboard but never rendered it (dead import). Removed. The component file itself stays until the deprecated lib/agenda-2063-data.ts is fully migrated to live data. (2) System prompt for /api/ask said '370+ works' but database is now 561. Updated to '500+' as a forward-looking floor. (3) 56/561 works (10%) had no accessLinks, dead-ending the user. Added a fallback card on /work/[id] with 3 search links (Internet Archive, Open Library, WorldCat) so every work has a way to look further. (4) 3 browse-filter pages (/browse/era/[era], /browse/genre/[genre], /browse/region/[region]) have no pagination — render up to 170 cards at once for popular categories. Flagged but not fixed; not critical at 170 items. (5) Two orphan exports: WisdomIcon in wisdom-logo.tsx and ScoreDashboard. Left in place for future use; the WisdomIcon may be needed once the marketing site refactors.
Mitigation: All fixes in commit applied today.
Eleventh pass: (1) verified tile map geography — 0 of 55 country positions mismatch their expected latitude band; north coast west-to-east ordering correct. (2) verified DB field completeness — language/region/country/genre/era/description/significance all 100% present across 561 works; only accessLinks is 90% (gap fixed via fallback). (3) removed 3 confirmed duplicate works: 'We Need New Names' (id 310), 'Homegoing' (id 256), 'Facing Mount Kenya' (id 260). 'Paradise' (×2) retained — Toni Morrison's 1997 and Abdulrazak Gurnah's 1994 are legitimately different works that share a title. (4) verified all 9 futures categories have ≥1 indicator. (5) verified AU framework mapping in ASPIRATION_GOALS still matches 7+3+2+3+1+2+2=20.
Mitigation: 3 duplicates removed, work count 564 → 561.
Pass IX-X: (1) calculateProgress in lib/agenda-2063-live returned 100 or 0 at range==0, inconsistent with the static layer's null. Made live match static — both now return null when baseline === target (progress is mathematically undefined). (2) AfricaTileMap rendered all tiles muted when only one country had data (range==0); now mid-scale amber so the data point is visible. (3) MCP server exposes 7 literature tools but no Agenda 2063 tools — feature gap, not bug. (4) /api/ask provides no Agenda 2063 context to the LLM — feature gap.
Mitigation: Live/static formula consistency restored; MCP+ask Agenda 2063 integration logged for future iteration.
Pass VIII verified clean (no issues found): (1) ScenarioHero indicator references all exist in FUTURE_INDICATORS. (2) ScenarioHero displayed numbers (2.0/3.3/6.0 GDP share, 38/18/6 poverty, 320/188/80 ag imports) match ISS exactly. (3) scenario-chart 2043 endpoints match futures-data gdp-per-capita card. (4) forecast-summary requiredPace 2063 = exactly 100 (algebraic). (5) trendIcon logic correct for negative deltas (governance-effectiveness). (6) 1458M population sum matches UN WPP 1460M within rounding. (7) /audit dynamic StatBlocks use live coverage stats. (8) Tile-map ESH position row 0 col 2 — geographically correct for north-western Africa.
Mitigation: No fixes needed; documented as verified-clean.
Pass VII: AspirationRadar was doing ours: d.ours ?? 0 to feed recharts. When an aspiration had no live indicators (4, 5, 7 currently), the polygon collapsed to that vertex at 0% AND the tooltip showed '0%' — visually claiming Africa scored zero when truth was 'we don't measure this'. Now: passes undefined (not 0) so recharts breaks the polygon at the null vertex; tooltip formatter displays 'no data' for null values.
Mitigation: Radar now honestly shows missing data instead of misleading zero.
Sixth deep audit pass: (1) /futures ImaginedFuture cards linked to /work/lagoon, /rosewater, /who-fears-death — but the route is /work/[id] (numeric), not [slug]. Three dead links. Fixed by switching to numeric workIds (495, 454, 73 — looked up in the literature database). (2) Wellbeing radar in charts.tsx drifted from live data: 'Women Parl. 27%' was the simple country mean; pop-weighted continental is 24%. 'Governance 48.8' was stale IIAG; updated to 49 (IIAG 2023 published). 'Education 52%' had unclear definition; relabeled 'Secondary Completion' so the value is defined. (3) Happiness data in charts.tsx had no methodology — the World Happiness Report ranks individual countries, not regions. Added explicit comment that 'rank' is the unweighted mean of African countries' WHR global ranks, and the forward values are linear extrapolations only. (4) charts.tsx employmentData.laborForce 2013 = 330M doesn't cleanly match ILO whole-Africa (~470M) or SSA-only (~370M); scope ambiguous — flagged in code for migration to ILO modelled estimates when ingestion expands.
Mitigation: Three dead links fixed. Wellbeing radar values reconciled with live data layer. Happiness methodology now documented in code comment.
External audit (Codex 2026-05-15) found bugs the previous internal passes missed. All real findings fixed: (1) getStatus() hardcoded the 2026 expected-progress threshold (26%) regardless of each indicator's currentYear. An indicator measured in 2023 should be benchmarked against 2023's expected progress (20%), not 2026's. Function now accepts currentYear and computes year-specific threshold; all callers updated to pass indicator.currentYear. (2) calculateProgress_static returned 100 whenever target===baseline (range=0), even if current differed materially; and silently coerced null/NaN current to 0 or 100. Now returns null in both cases; callers must handle explicitly. Score aggregation functions filter nulls instead of treating them as zero. (3) ProgressBar component hardcoded the expected marker at 26%; now accepts markerYear and computes proportionally. (4) charts.tsx had 'pressFreeedom' typo (5 places). Renamed to pressFreedom. (5) charts.tsx energyData electricityAccess trajectory was too slow — 47% by 2025 vs WB's actual ~58% by 2022. Series rebuilt with 2022=58 (WB actual) waypoint and accelerated forward projection. The external auditor also flagged simple-mean vs population-weighted discrepancy (our 58% whole-Africa vs their 53% SSA-only weighted) — different scopes, not an error; disclosure improved. Stale-extraction findings (missing files, IIAG 47.5) were already fixed in earlier passes; auditor was looking at older branch state.
Mitigation: All fixes pushed in commit applied today. The original audit report is preserved for traceability.
Fourth deep audit pass found and fixed: (1) GDP per capita baseline2013 was $1,880 — that's sub-Saharan Africa only; whole continent was $2,210. Skewed all progress math. Corrected. (2) Population 2043 Current Path was 2.14B citing UN WPP, but ISS African Futures Current Path uses 2.3B. We're a Current-Path-driven page, so we should match ISS for internal coherence. Switched to 2.3B; failure and possible scenarios rescaled. (3) Cereal yield was citing FAOSTAT cereal-only baseline (1.6 t/ha) while scenario forecast was ISS all-crops (5.9 t/ha) — unit mismatch. Renamed to 'Crop yield (all crops)' with consistent baseline 4.3 → currentPath 5.9 per ISS Agriculture theme. (4) IIAG Cabo Verde was 67.6 (off by 4pts); Kenya was 56.6 (off by 3.4pts). Both corrected to published 71.6 and 60.0. (5) Three duplicate MWI keys in IIAG 2014 baseline — only one canonical 56.2 retained. (6) Population indicator was marked higherIsBetter=true but Possible Africa scenario has LOWER population (demographic transition). Reversed: more population in failure path, lower in possible path. (7) AU report URL fabricated path /20220207/ replaced with the documents index https://au.int/en/documents.
Mitigation: All Current Path 2043 values now align with ISS African Futures to ≤5% error. Scenario ordering passes monotonicity check for all 16 indicators.
Third deep audit pass found and fixed: (1) charts.tsx healthData infantMortality showed 92/1000 — that's the under-5 rate, not infant. Corrected to ~60/1000 per WHO/UN IGME. (2) charts.tsx digitalData mobile field was 280 in 2013 — wrong by 3x; GSMA reports ~750M SIM connections. Corrected. (3) Dual composite-score rendering removed: page.tsx no longer renders ScoreDashboard alongside LiveDataSection. (4) Function name collisions resolved: the deprecated lib/agenda-2063-data.ts now exports calculateProgress_static, calculateGoalScore_static, calculateAspirationScore_static, calculateOverallScore_static to prevent silent wrong-import bugs. (5) AU Continental Report URL changed from a fabricated /20220207/ path to https://au.int/en/documents (the documents index) where users can search reliably. (6) formatValue() in both live-data-section.tsx and futures/page.tsx expanded to handle all 13 declared units.
Mitigation: All fixes shipped in commit applied today. Verifiable in git history.
For academic and journalistic use, please cite the original primary sources (the URLs above) for any specific numerical claim. Wisdom is an aggregator and visualiser, not an originator of statistical estimates.
For dashboard methodology and the Failure scenario construction, cite: Wisdom Pan-African Library, Agenda 2063 dashboard methodology,with a link to wisdom.example/audit.
For the IFs-based Current Path and Possible Africa forecasts, cite Cilliers, J. (2026). Africa Current Path. ISS African Futures and Innovation Programme.