feat: domestic flights, road traffic, CCTV webcams, AI situation brief

Four new intelligence domains for the dashboard:

1. Domestic flights (OpenSky) — global airborne aircraft count by
   region with commercial/general breakdown. No API key needed.

2. Road traffic (TomTom) — real-time congestion % for 20 major world
   cities + traffic incidents in 5 strategic regions. Needs
   TOMTOM_API_KEY (free 2500 req/day at developer.tomtom.com).

3. CCTV webcams (Windy) — public traffic camera locations worldwide.
   Needs WINDY_API_KEY (free 100 req/day at api.windy.com).

4. AI situation brief (Ollama) — LLM-generated 3-paragraph
   intelligence brief synthesizing all dashboard data. Uses local
   Ollama (llama3.2). Falls back to structured metrics summary.

New files: sources/traffic.py, sources/webcams.py, analysis/situation.py
Modified: sources/aviation.py (+fetch_domestic_flights), dashboard/app.py,
dashboard/index.html (drawer sections + HUD pills for all 4 domains).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Marc Shade
2026-02-24 11:46:19 -05:00
co-authored by Claude Opus 4.6
parent fc105872e2
commit fcc702b093
6 changed files with 688 additions and 2 deletions
+16
View File
@@ -41,10 +41,13 @@ from world_intel_mcp.sources import (
social,
nuclear,
service_status,
traffic,
webcams,
)
from world_intel_mcp.analysis.alerts import fetch_alert_digest, fetch_weekly_trends
from world_intel_mcp.analysis.posture import fetch_strategic_posture
from world_intel_mcp.analysis.exposure import fetch_population_exposure
from world_intel_mcp.analysis.situation import fetch_situation_brief
from world_intel_mcp.sources.fleet import fetch_fleet_report
from world_intel_mcp.config.countries import INTEL_HOTSPOTS, STRATEGIC_WATERWAYS
from world_intel_mcp.config.geospatial import MILITARY_BASES, STRATEGIC_PORTS, PIPELINES, NUCLEAR_FACILITIES
@@ -115,6 +118,10 @@ async def _fetch_overview() -> dict:
"strategic_posture": fetch_strategic_posture(fetcher),
"fleet_report": fetch_fleet_report(fetcher),
"population_exposure": fetch_population_exposure(fetcher),
"domestic_flights": aviation.fetch_domestic_flights(fetcher),
"traffic_flow": traffic.fetch_traffic_flow(fetcher),
"traffic_incidents": traffic.fetch_traffic_incidents(fetcher),
"webcams": webcams.fetch_webcams(fetcher),
}
# Per-coro timeout so no single slow source blocks the entire dashboard.
@@ -183,6 +190,15 @@ async def _fetch_overview() -> dict:
"count": len(CABLE_CORRIDORS),
}
# AI situational brief (runs after main gather so it has all data)
try:
result["situation_brief"] = await asyncio.wait_for(
fetch_situation_brief(result), timeout=35.0,
)
except Exception as exc:
logger.warning("Situation brief failed: %s", exc)
result["situation_brief"] = {"error": str(exc)}
# Attach source health + timestamp
result["source_health"] = _breaker.status() if _breaker else {}
result["cache_stats"] = _cache.stats() if _cache else {}