feat: add S2 GhostMaps live intel layer

Adds an "S2 GhostMaps" layer (Events group) that renders S2 Underground's
GhostMaps KMZ exports (Common Intelligence Picture, Kinetic 30d, Border
Crisis, Iran CIP/Kinetic, Yemen FLOT, latest incident drop).

- server/providers/ghostMaps.js: watcher polls the repo's git smart-HTTP
  ref advertisement (default every 15s, GHOSTMAPS_POLL_SECONDS), fetches
  the tree only on a new head, caches commit-pinned files by blob sha and
  pushes catalog updates to browsers over SSE (/api/ghostmaps/events).
- src/layers/ghostMaps: KML reader, ArcGIS popup-table parsing, per-product
  data sources, product chips, horizon-culled pins, report cards.
- Unit tests, QA gate (scripts/qa-ghostmaps.mjs), credits (CC BY-NC-SA 4.0),
  i18n, voice manifest, layer-state token 5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
GPTmadeitandClaude Opus 5.5 committed 2026-10-20 16:24:53 -04:00
1 parent 713285b554
commit 1f77d2290c
36 files changed
+3247 -52

No files matched your search

+31 -1
View File
@@ -3004,5 +3004,35 @@
"Gemini access was refused. Check the API key and model access.": "Доступ к Gemini запрещён. Проверьте ключ API и доступ к модели.",
"Gemini Live is unavailable for the configured model.": "Gemini Live недоступен для выбранной модели.",
"Token request is too large": "Запрос токена слишком велик",
"Use an empty JSON token request": "Используйте запрос токена с пустым объектом JSON"
"Use an empty JSON token request": "Используйте запрос токена с пустым объектом JSON",
"S2 GhostMaps": "S2 GhostMaps",
"Intel Picture": "Разведкартина",
"Kinetic 30d": "Боевые 30 дн.",
"Border Crisis": "Кризис на границе",
"Iran Picture": "Иран: картина",
"Iran Kinetic": "Иран: боевые",
"Yemen FLOT": "Йемен: линия фронта",
"Latest Drop": "Новый выпуск",
"GhostMaps file could not be read": "Не удалось прочитать файл GhostMaps",
"GhostMaps catalog unavailable": "Каталог GhostMaps недоступен",
"Malformed GhostMaps catalog": "Повреждённый каталог GhostMaps",
"{count} source links ↗ · click card to open the first": {
"one": "{count} ссылка на источник ↗ · нажмите на карточку, чтобы открыть",
"few": "{count} ссылки на источники ↗ · нажмите на карточку, чтобы открыть первую",
"many": "{count} ссылок на источники ↗ · нажмите на карточку, чтобы открыть первую",
"other": "{count} ссылки на источники ↗ · нажмите на карточку, чтобы открыть первую"
},
"S2 · {name}": "S2 · {name}",
"Report": "Сводка",
"Open the source for {title}": "Открыть источник: {title}",
"LIVE · GitHub {commit} · {message} · checked every {seconds}s": "В ЭФИРЕ · GitHub {commit} · {message} · проверка каждые {seconds} с",
"GitHub {commit} · {message} · reconnecting for live updates": "GitHub {commit} · {message} · переподключение для обновлений в реальном времени",
"Connecting to the S2 GhostMaps repository…": "Подключение к репозиторию S2 GhostMaps…",
"{count} placemarks": {
"one": "{count} метка",
"few": "{count} метки",
"many": "{count} меток",
"other": "{count} метки"
},
"S2 Underground publishes these KMZ products to GitHub. New uploads are detected within seconds and replace the previous edition automatically. Click a marker for its report.": "S2 Underground публикует эти продукты KMZ на GitHub. Новые файлы обнаруживаются за секунды и автоматически заменяют предыдущий выпуск. Нажмите на метку, чтобы открыть её сводку."
}