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

+29 -28
View File
@@ -128,7 +128,7 @@ test('reservation ledger is complete, pinned, and rejects duplicate or malformed
{ ...parseLayerStateTokenReservations(reservationRows) },
{ ...LAYER_STATE_TOKEN_RESERVATIONS },
);
assert.equal(Object.keys(LAYER_STATE_TOKEN_RESERVATIONS).length, 31);
assert.equal(Object.keys(LAYER_STATE_TOKEN_RESERVATIONS).length, 32);
assert.deepEqual(
{ ...LAYER_STATE_TOKEN_RESERVATIONS },
{
@@ -136,6 +136,7 @@ test('reservation ledger is complete, pinned, and rejects duplicate or malformed
'street-level': '0',
'gnss-integrity': '3',
'air-quality': '4',
's2-ghostmaps': '5',
},
);
assert.throws(
@@ -161,9 +162,9 @@ test('reservation ledger is complete, pinned, and rejects duplicate or malformed
/Duplicate layer-state token reservation/,
);
assert.equal(
parseLayerStateTokenReservations([...reservationRows, ['future', '5']])
parseLayerStateTokenReservations([...reservationRows, ['future', '6']])
.future,
'5',
'6',
);
assert.throws(
() =>
@@ -181,14 +182,14 @@ test('reservation ledger is complete, pinned, and rejects duplicate or malformed
test('published retired digits and competing PRs advance the merge-time allocation', () => {
withPublishedBase(
{ rows: [...reservationRows, ['retired-layer', '5']] },
{ rows: [...reservationRows, ['retired-layer', '6']] },
(cwd) => {
const published = readPublishedLayerStateReservations('HEAD', cwd);
assert.equal(nextLayerStateToken(published), '6');
assert.equal(nextLayerStateToken(published), '7');
assert.equal(
validateLayerStateAllocations(published, {
...published,
newcomer: '6',
newcomer: '7',
}),
true,
);
@@ -196,15 +197,15 @@ test('published retired digits and competing PRs advance the merge-time allocati
() =>
validateLayerStateAllocations(published, {
...published,
competing: '5',
competing: '6',
}),
/next free token 6/,
/next free token 7/,
);
assert.throws(
() =>
validateLayerStateAllocations(published, {
...LAYER_STATE_TOKEN_RESERVATIONS,
newcomer: '5',
newcomer: '6',
}),
/changed or removed: retired-layer/,
);
@@ -212,8 +213,8 @@ test('published retired digits and competing PRs advance the merge-time allocati
);
});
test('PR B manually replaces provisional 5 with 6 after PR A publishes 5', () => {
withPublishedBase({ rows: [...reservationRows, ['pr-a', '5']] }, (cwd) => {
test('PR B manually replaces provisional 6 with 7 after PR A publishes 6', () => {
withPublishedBase({ rows: [...reservationRows, ['pr-a', '6']] }, (cwd) => {
mkdirSync(path.join(cwd, 'scripts'));
const fixtureChecker = path.join(
cwd,
@@ -234,8 +235,8 @@ test('PR B manually replaces provisional 5 with 6 after PR A publishes 5', () =>
writeCodecFixture(
cwd,
[...reservationRows, ['pr-b', '5']],
[{ id: 'pr-b', token: '5' }],
[...reservationRows, ['pr-b', '6']],
[{ id: 'pr-b', token: '6' }],
);
const beforeRebase = runCheck();
assert.equal(beforeRebase.status, 1);
@@ -243,10 +244,10 @@ test('PR B manually replaces provisional 5 with 6 after PR A publishes 5', () =>
writeCodecFixture(
cwd,
[...reservationRows, ['pr-a', '5'], ['pr-b', '5']],
[...reservationRows, ['pr-a', '6'], ['pr-b', '6']],
[
{ id: 'pr-a', token: '5' },
{ id: 'pr-b', token: '5' },
{ id: 'pr-a', token: '6' },
{ id: 'pr-b', token: '6' },
],
);
const staleRebase = runCheck();
@@ -254,16 +255,16 @@ test('PR B manually replaces provisional 5 with 6 after PR A publishes 5', () =>
assert.match(staleRebase.stderr, /Duplicate layer-state token reservation/);
const published = readPublishedLayerStateReservations('HEAD', cwd);
assert.equal(nextLayerStateToken(published), '6');
const validBaselineRows = [...reservationRows, ['pr-a', '5']];
writeCodecFixture(cwd, validBaselineRows, [{ id: 'pr-a', token: '5' }]);
assert.equal(nextLayerStateToken(published), '7');
const validBaselineRows = [...reservationRows, ['pr-a', '6']];
writeCodecFixture(cwd, validBaselineRows, [{ id: 'pr-a', token: '6' }]);
const helper = spawnSync(
process.execPath,
[realpathSync(fixtureNext), 'pr-b'],
{ cwd, encoding: 'utf8' },
);
assert.equal(helper.status, 0, helper.stderr);
assert.match(helper.stdout, /pr-b: 6/);
assert.match(helper.stdout, /pr-b: 7/);
assert.deepEqual(
JSON.parse(readFileSync(path.join(cwd, LEDGER_PATH), 'utf8')),
validBaselineRows,
@@ -271,20 +272,20 @@ test('PR B manually replaces provisional 5 with 6 after PR A publishes 5', () =>
);
writeCodecFixture(
cwd,
[...reservationRows, ['pr-a', '5'], ['pr-b', '6']],
[...reservationRows, ['pr-a', '6'], ['pr-b', '7']],
[
{ id: 'pr-a', token: '5' },
{ id: 'pr-b', token: '6' },
{ id: 'pr-a', token: '6' },
{ id: 'pr-b', token: '7' },
],
);
const corrected = runCheck();
assert.equal(corrected.status, 0, corrected.stderr);
assert.match(corrected.stdout, /32 published, 1 new/);
assert.match(corrected.stdout, /33 published, 1 new/);
});
});
test('allocation batches cross the last digit and base-36 pair boundaries in order', () => {
const digitRows = [...'56789'].map((digit) => [`retired-${digit}`, digit]);
const digitRows = [...'6789'].map((digit) => [`retired-${digit}`, digit]);
const allDigits = parseLayerStateTokenReservations([
...reservationRows,
...digitRows,
@@ -336,7 +337,7 @@ test('allocation batches cross the last digit and base-36 pair boundaries in ord
test('an isolated valid two-character fixture round-trips an l field beyond the old 64-character cap', async () => {
const cwd = mkdtempSync(path.join(tmpdir(), 'gev-layer-token-width-'));
try {
const priorDigits = [...'56789'].map((digit) => [
const priorDigits = [...'6789'].map((digit) => [
`qa-prior-digit-${digit}`,
digit,
]);
@@ -373,7 +374,7 @@ test('an isolated valid two-character fixture round-trips an l field beyond the
const params = new URLSearchParams([['v', '2']]);
codec.encodeLayerStateParams(params, state);
assert.ok(params.get('l').length > 64, 'fixture must cross the old cap');
assert.equal(params.get('l').length, 73);
assert.equal(params.get('l').length, 75);
const restored = codec.decodeLayerStateParams(params);
assert.deepEqual(restored?.enabledLayerIds, expectedLayerIds);
assert.deepEqual(restored?.options, state.options);
@@ -391,7 +392,7 @@ test('checker reads a complete future base ledger and rejects retired-token reus
},
(cwd) => {
const published = readPublishedLayerStateReservations('HEAD', cwd);
assert.equal(Object.keys(published).length, 32);
assert.equal(Object.keys(published).length, 33);
assert.equal(published['retired-layer'], '00');
assert.throws(
() =>