Repository navigation
Description
Summary
The aggregator's freshness gates accept a generatedAt that is not a date at all — and a date arbitrarily far in the future — and report the data as live/fresh indefinitely:
orchestrationSectionProblem(pm-stack/aggregator/src/feed.ts:120-135, the check itself at :124) checks onlytypeof s.generatedAt === "string". It never checks that the string parses as a date.diagnoseOrchestrationSection(feed.ts:165-176, age at :170) computesageMs = Math.max(0, now - Date.parse(s.generatedAt)). For an unparseable stringDate.parseisNaN,Math.max(0, NaN)isNaN, andNaN > ORCHESTRATION_STALE_MSisfalse— so the section diagnoses aslive, withageMs: NaN. For a future stamp the age clamps to0, so the section staysliveuntil 90 minutes after its future date.isFleetFeed(feed.ts:193-204) has the same shape:generatedAtis string-only. A feed stamped"not-a-date"passes the gate and is served byloadFeed.feedAgeText(feed.ts:225-227) renders the garbage case literally asNaNd oldin the provenance strings (sources/live.ts:715,757,892,…), and the future case asfresh.buildHealth(health.ts:229,249-250) derivesfeedAgeMsthe same clamped way, so a garbage/future feed is neverstaleand never setsdegraded.
Verified (this run, on main db6f7d0)
Probe ON THE LAPTOP (Bun, driving the real feed.ts, sha256 identical both sides; probe + log in the goal's hidden_files/probe-2026-10-27-laneB-feeddate/):
- Control, section stamped 10 min ago →
state=live(correct); 2 h ago →state=stale(correct). - Section stamped
"not-a-date"→state=live,ageMs=NaN,feedAgeText="NaNd old". - Section stamped
+30 daysin the future →state=live,ageMs=0,feedAgeText="fresh"— and it stays live until 90 min after that future date. isFleetFeedaccepts both the garbage and the +30d feed (true); the valid control alsotrue.
Why it matters
The diagnosis is the aggregator's honesty backbone (#1139/#1140): it decides whether Today / Needs-you render the orchestration section as current or show the "section is stale — its last published state" banners (render.ts:2215,2428), what provenance claims (live (fleet feed · …)), and whether /health reports the stack degraded. A publisher bug or clock skew that emits a malformed or future generatedAt therefore defeats every one of those surfaces at once — stale tiers, goals, and measurements present as live readings indefinitely, with no banner and no health signal. That is precisely the failure class the diagnosis was built to surface ("a publisher whose section is being rejected has a bug to fix"), except this input is never rejected.
Distinct from #1541 (quota-current's measuredAt freshness in a different module, different gate, different fix surface).
Acceptance criteria
- A section whose
generatedAtdoes not parse as a date diagnoses asinvalid(failing check namedgeneratedAt), notlive;orchestrationSectionProblemis still the single source of truth for the gate. - A section/feed stamped implausibly in the future (beyond a small pinned clock-skew tolerance) is not reported
live/fresh— it diagnoses stale or invalid per a documented rule, and the tolerance is pinned in a test. -
isFleetFeedrejects a feed whosegeneratedAtdoes not parse;loadFeedtherefore returns null for it instead of serving it as current. -
feedAgeText/ageMsTextcan never renderNaNd oldfor an input that reaches them (defence in depth at the validator is enough if the render paths are unreachable with NaN — say which in the fix). - Regression tests in pm-stack/aggregator/test/orchestration.test.ts (and health tests if buildHealth's feed age changes): garbage date, future date, and the existing fresh/stale controls.
- Existing orchestration/health test suites still pass.
Activity
developing-today commentedon Oct 28, 2026
CODE-608
dezren39 commentedon Oct 28, 2026
🤖 Agent note · filed
48 remaining items
dezren39 commentedon Oct 28, 2026
🤖 Agent note · picked up
Merge pull request #1693 from developing-today/queue/1830-1564-genera…
dezren39 commentedon Oct 28, 2026
🤖 Agent note · done