Turning early warning into early action. Built for the IGAD Husika Hackathon 2026 · Smarter Early Warning, Stronger Communities · ICPAC
ICPAC already forecasts well. People still lose everything. The failure isn't the science — it's the last mile. This is the last mile.
I built this for the hackathon and then found out I can't enter it — entry is limited to the IGAD and EAC countries, and I'm based in the United States. That's a fair rule, and it doesn't make the work less useful to the people it was built for.
So this is published for ICPAC and the Husika team to take, fork, argue with, or ignore.
It's MIT-licensed. If one idea in here is worth lifting — the named-disaster catalogue, the
pledge-counted social proof, or the faithfulness gate — lift it; no attribution needed and
nothing owed. Corrections from people who actually live in these districts are worth more
than anything I can add from Atlanta, especially on the Kiswahili and on the
decision_points.json placeholders.
OND 2021 — SPI-6 −1.01 · rainfall 67% below the 1991–2020 normal ← real, and useless to a herder
↓
"Ndugu yangu, mvua ya mwaka huu inaonyesha dalili kama za Kitijake ya 2017. Familia 340
kule Lodwar zimeahidi kuuza mifugo dhaifu mapema. Fanya jambo moja: uza wanyama wako
wawili dhaifu kwenye soko la mifugo la Lodwar siku ya Alhamisi... Jibu NDIYO kuahidi.
-- Pastor James, pamoja na timu ya tahadhari ya kaunti" ← same forecast, actionable
Husika is ICPAC's own last-mile early-warning service (app + SMS + web, built with Bunifu Technologies and GIZ). Husika solved delivery. Husika Alert adds the layer that makes the message land:
| Husika already does | Husika Alert adds |
|---|---|
| Reaches the household (app, SMS, web) | The community's own named disaster as the hook |
| Sends the forecast | Behavioural design — social proof, a deadline, one easy step |
| Institutional voice | The trusted faith/community messenger |
| — | Human-in-the-loop approval before anything is sent |
| — | An automated faithfulness gate so the AI cannot invent a word |
python src/husika/demo.py # the whole pipeline in your terminal — no install needed
pip install flask && python app/server.py # the officer console → http://127.0.0.1:5000Optional — let Claude write the alerts (falls back to the grounded template without a key):
export ANTHROPIC_API_KEY=sk-... # PowerShell: $env:ANTHROPIC_API_KEY="sk-..."
PYTHONPATH=src python -m husika.faithful --polish # the audit, against live model outputRe-pull the real data yourself:
PYTHONPATH=src python -m husika.chirps KE-TUR 2021-12-31 # ingest real CHIRPS
PYTHONPATH=src python -m husika.chirps scan KE-TUR 2021-01 2023-06 # see the real SPI record CHIRPS v2.0 (real) ──ClimateSERV/SERVIR JSON API, no auth──┐
▼
chirps.py daily → dekads/months · 1991–2020 climatology · gamma-fit SPI-3/6/12
▼
detector.py standard SPI classes → hazard + severity + a rationale you can check
▼
analog.py "what does THIS community call the last one?" → Kitijake (32-event catalogue)
▼
nudge.py 7 behavioural levers → a grounded draft + a FACT SHEET
▼
llm.py Claude Opus 4.8 rewrites it — using only the fact sheet
▼
faithful.py ⛔ GATE: no invented numbers · keyword/name/count intact · no drift · SMS length
(fails → the grounded template ships instead. The floor is never worse.)
▼
app/ officer reviews → Approve → broadcast (SIMULATED)
▼
pledges.py "Reply YES" → counted → the NEXT message's neighbour figure truthfully rises
Each one is doing a job, and each is grounded in the data — never asserted.
| Lever | Principle | Source of truth |
|---|---|---|
| "…like Kitijake" | availability heuristic + loss aversion | data/event_catalogue.json (sourced) |
| "340 families have pledged" | social proof (a counted number) | data/pledges.json ledger |
| "— Pastor James" | messenger effect (76% trust faith leaders vs 44% government) | data/messengers.json |
| "Do one thing" | EAST — make it Easy | data/audience_actions.json |
| "at Lodwar market, Thursday" | implementation intention (Gollwitzer) | data/decision_points.json |
| "prices hold until Thursday" | EAST — Timely | data/decision_points.json |
| "Reply YES to pledge" | commitment device → feeds the count above | pledges.py |
We'd rather tell you than have you find out.
| Real | Simulated / configured |
|---|---|
| CHIRPS v2.0 rainfall via ClimateSERV (1991→present) | The SMS/WhatsApp broadcast — no gateway is connected |
| The 1991–2020 climatology and gamma-fit SPI-3/6/12 | Seed pledge counts (live pledges during a session are real) |
| The named-disaster catalogue — every entry sourced | Market days / water points — county-configured placeholders, not derived |
| The Kiswahili, written by Claude and gated |
python -m husika.faithful --polish # 6 alerts: 3 audiences × Kiswahili/English
→ 6/6 fully grounded — 0 invented facts, 0 dropped keywords/names/counts, 0 hazard drift
The gate caught two real bugs before release: a Kiswahili reply keyword that wouldn't have matched the gateway (every Swahili pledge would have vanished), and English alerts running over the 3-segment SMS budget.
Scanning the real record, Turkana's worst honest signal in the 2020–23 drought was SPI-6 −1.01 — moderate, not extreme. We anchored there deliberately. That is the point of anticipatory action: you act while selling two goats is still a choice, not a loss. A tool that only shouts at SPI −2.0 is a historian, not an early-warning system.
src/husika/ chirps.py · detector.py · analog.py · nudge.py · llm.py · faithful.py · pledges.py
data/ districts/ · event_catalogue.json · messengers.json · decision_points.json
app/ server.py + static/index.html (officer console)
docs/ DESIGN.md · SUBMISSION.md · DEMO_SCRIPT.md
- CHIRPS v2.0 — Climate Hazards Center, UC Santa Barbara / USGS. ICPAC's preferred rainfall dataset.
- ClimateSERV — SERVIR (NASA / USAID),
climateserv.servirglobal.net— the public, no-auth API we pull CHIRPS through. - ICPAC — East Africa Hazards Watch, Drought Watch, and the
icpac-igadopen-source work that framed this. - Bunifu Technologies + GIZ — who built Husika, the service this extends.
- Claude Opus 4.8 (Anthropic) — writes the alerts, from a fact sheet, under the gate.
- scipy — gamma fitting for SPI. Flask — the console.
- The named-disaster catalogue is compiled from published sources; every entry carries its URL
in
data/event_catalogue.json.
Regionally led. Nationally owned. Locally implemented.