From af128bd4cd23c36bcdbd3dc30de6048d416ed645 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Sun, 11 Oct 2026 09:51:14 -0400 Subject: [PATCH 1/5] fix(regional): keep impossible compact article dates unknown --- CHANGELOG.md | 1 + docs/CURRENT-STATE.md | 5 +++ src/data/regional-calendar-evidence.test.mjs | 43 ++++++++++++++++++++ src/data/regionalModel.js | 17 ++++++-- 4 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 src/data/regional-calendar-evidence.test.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index a770fbd35..6212e745c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Tool string length validation counts Unicode characters correctly, including characters outside the basic multilingual plane. - Director timeline seeks cross the dateline along the short longitude arc. +- Regional articles retain unknown publication times when compact source dates do not identify a real calendar instant. - Treat explicitly current, complete empty vessel coverage as a successful update, clearing obsolete contacts while retaining stale or incomplete snapshots. diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 1f794a5b5..03d98aa1c 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -5326,3 +5326,8 @@ datacenters, dams and the Nepal locator retain that shared credit while displaye Military fragments stitch by source identity. Different mapped parcels merge only when their footprints touch or contain one another, never across a seam tolerance gap. + + +### fix(regional): keep impossible compact article dates unknown + +Round-trip compact timestamps through a valid Date and retain the article with an unknown timestamp when its source date is impossible. Valid compact and ordinary ISO output formats are preserved. diff --git a/src/data/regional-calendar-evidence.test.mjs b/src/data/regional-calendar-evidence.test.mjs new file mode 100644 index 000000000..a442a9feb --- /dev/null +++ b/src/data/regional-calendar-evidence.test.mjs @@ -0,0 +1,43 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { normalizeRegionalArticles } from './regionalModel.js'; +test('compact source dates must denote an actual calendar instant', () => { + for (const date of [ + '20260230T120000Z', + '20260431T120000Z', + '20261301T120000Z', + '20260716T240000Z', + '20260716T126000Z', + '20260716T120060Z', + ]) { + const [article] = normalizeRegionalArticles({ + articles: [ + { + title: 'Fixture', + url: 'https://fixture.example/news', + seendate: date, + }, + ], + }); + assert.equal(article.publishedAt, null, date); + assert.equal(article.title, 'Fixture'); + } + for (const [input, expected] of [ + ['20240229T004500Z', '2024-02-29T00:45:00Z'], + ['20260716T000000Z', '2026-07-16T00:00:00Z'], + ['2026-07-16T12:00:00Z', '2026-07-16T12:00:00.000Z'], + ]) { + assert.equal( + normalizeRegionalArticles({ + articles: [ + { + title: 'Fixture', + url: 'https://fixture.example/news', + seendate: input, + }, + ], + })[0].publishedAt, + expected, + ); + } +}); diff --git a/src/data/regionalModel.js b/src/data/regionalModel.js index 3a6d79f14..fca473994 100644 --- a/src/data/regionalModel.js +++ b/src/data/regionalModel.js @@ -67,11 +67,20 @@ export function normalizeRegionalArticles(payload, limit = MAX_ARTICLES) { seen.add(signature); const rawDate = cleanText(row?.seendate, 32); const compactDate = /^(\d{8})T(\d{6})Z$/.exec(rawDate); - const publishedAt = compactDate + const candidateDate = compactDate ? `${compactDate[1].slice(0, 4)}-${compactDate[1].slice(4, 6)}-${compactDate[1].slice(6, 8)}T${compactDate[2].slice(0, 2)}:${compactDate[2].slice(2, 4)}:${compactDate[2].slice(4, 6)}Z` - : Number.isNaN(Date.parse(rawDate)) - ? null - : new Date(rawDate).toISOString(); + : rawDate; + const parsedMs = Date.parse(candidateDate); + const validDate = + Number.isFinite(parsedMs) && + (!compactDate || + new Date(parsedMs).toISOString().slice(0, 19) === + candidateDate.slice(0, 19)); + const publishedAt = validDate + ? compactDate + ? candidateDate + : new Date(parsedMs).toISOString() + : null; articles.push({ title, url, From 5cb79cd69df472db04059324e5b23673bb12b571 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Mon, 12 Oct 2026 11:14:32 -0400 Subject: [PATCH 2/5] docs: address maintainer review for PR #1051 --- docs/CURRENT-STATE.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 03d98aa1c..a8dec3873 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1140,6 +1140,8 @@ stalled downloads are cancelled. Development and preview use the same handler. ## Remaining local service modules +GDELT compact dates that do not name a real calendar instant keep the article with an unknown publication time. + Overpass query validation, geometry simplification, disk caching and upstream transport now have separate modules; military-installation search reuses that transport. Regional briefing combines separate place, news and weather sources, @@ -5326,8 +5328,3 @@ datacenters, dams and the Nepal locator retain that shared credit while displaye Military fragments stitch by source identity. Different mapped parcels merge only when their footprints touch or contain one another, never across a seam tolerance gap. - - -### fix(regional): keep impossible compact article dates unknown - -Round-trip compact timestamps through a valid Date and retain the article with an unknown timestamp when its source date is impossible. Valid compact and ordinary ISO output formats are preserved. From 2c7d27ec6d31a4a6bcd3134c86a70f613c33623b Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Mon, 12 Oct 2026 11:15:51 -0400 Subject: [PATCH 3/5] docs: place publication-time behavior beside regional briefing --- docs/CURRENT-STATE.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index a8dec3873..066cf5e37 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1140,12 +1140,11 @@ stalled downloads are cancelled. Development and preview use the same handler. ## Remaining local service modules -GDELT compact dates that do not name a real calendar instant keep the article with an unknown publication time. - Overpass query validation, geometry simplification, disk caching and upstream transport now have separate modules; military-installation search reuses that transport. Regional briefing combines separate place, news and weather sources, -while weather effects uses only the weather source. Existing process-scoped +while weather effects uses only the weather source. +GDELT compact dates that do not name a real calendar instant keep the article with an unknown publication time. Existing process-scoped caches, rate limits, stale fallbacks and route ordering are preserved. Local voice has separate HUD-summary, debug-log and Realtime-token handlers, From fa374025892e701ee6d9572379c4260c0a6e25a7 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Mon, 12 Oct 2026 11:17:02 -0400 Subject: [PATCH 4/5] docs: wrap regional publication-time prose --- docs/CURRENT-STATE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 066cf5e37..76d65d82d 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1144,7 +1144,8 @@ Overpass query validation, geometry simplification, disk caching and upstream transport now have separate modules; military-installation search reuses that transport. Regional briefing combines separate place, news and weather sources, while weather effects uses only the weather source. -GDELT compact dates that do not name a real calendar instant keep the article with an unknown publication time. Existing process-scoped +GDELT compact dates that do not name a real calendar instant keep the article +with an unknown publication time. Existing process-scoped caches, rate limits, stale fallbacks and route ordering are preserved. Local voice has separate HUD-summary, debug-log and Realtime-token handlers, From 4fcca5b21564f28c58d94fda02d4987d7d7f8fc5 Mon Sep 17 00:00:00 2001 From: Rudy Celekli Date: Wed, 14 Oct 2026 20:13:40 -0400 Subject: [PATCH 5/5] docs: separate CHANGELOG bullets after rebase Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6212e745c..098fc54a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Tool string length validation counts Unicode characters correctly, including characters outside the basic multilingual plane. - Director timeline seeks cross the dateline along the short longitude arc. + - Regional articles retain unknown publication times when compact source dates do not identify a real calendar instant. - Treat explicitly current, complete empty vessel coverage as a successful update,