diff --git a/tools/loop-metrics/dist/metrics.js b/tools/loop-metrics/dist/metrics.js index 3a3c4224..2b41b2b4 100644 --- a/tools/loop-metrics/dist/metrics.js +++ b/tools/loop-metrics/dist/metrics.js @@ -32,13 +32,13 @@ export function filterEntries(entries, pattern, days) { const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - days); filtered = filtered.filter(e => { - try { - const entryDate = new Date(e.run_id); - return entryDate >= cutoffDate; - } - catch { + const entryDate = new Date(e.run_id); + // An unparseable run_id (e.g. a numeric GitHub run id or a custom + // slug) yields Invalid Date; keep the entry rather than silently + // dropping it from the timeframe view. + if (Number.isNaN(entryDate.getTime())) return true; - } + return entryDate >= cutoffDate; }); } return filtered; diff --git a/tools/loop-metrics/src/metrics.ts b/tools/loop-metrics/src/metrics.ts index aea48321..14afcad5 100644 --- a/tools/loop-metrics/src/metrics.ts +++ b/tools/loop-metrics/src/metrics.ts @@ -60,12 +60,12 @@ export function filterEntries(entries: RunEntry[], pattern?: string, days?: numb cutoffDate.setDate(cutoffDate.getDate() - days); filtered = filtered.filter(e => { - try { - const entryDate = new Date(e.run_id); - return entryDate >= cutoffDate; - } catch { - return true; - } + const entryDate = new Date(e.run_id); + // An unparseable run_id (e.g. a numeric GitHub run id or a custom + // slug) yields Invalid Date; keep the entry rather than silently + // dropping it from the timeframe view. + if (Number.isNaN(entryDate.getTime())) return true; + return entryDate >= cutoffDate; }); } diff --git a/tools/loop-metrics/test/metrics.test.mjs b/tools/loop-metrics/test/metrics.test.mjs index f47e554e..056d793b 100644 --- a/tools/loop-metrics/test/metrics.test.mjs +++ b/tools/loop-metrics/test/metrics.test.mjs @@ -18,3 +18,14 @@ test('loop-metrics filters and aggregates', () => { assert.strictEqual(metrics.totalEscalations, 1); assert.strictEqual(metrics.roiScore, (3 * 10) - (1 * 5)); // 25 }); + +test('filterEntries keeps entries with unparseable run_id when a timeframe is set', () => { + const entries = [ + { run_id: '2026-07-30T08:50:34Z', pattern: 'daily-triage', duration_s: 5, items_found: 1, actions_taken: 2, escalations: 1, tokens_estimate: 52000, outcome: 'report-only' }, + // Numeric GitHub run id is not a parseable date and must not be dropped. + { run_id: '29231015995', pattern: 'daily-triage', duration_s: 8, items_found: 1, actions_taken: 1, escalations: 0, tokens_estimate: 52000, outcome: 'report-only' }, + ]; + + const filtered = filterEntries(entries, 'daily-triage', 30); + assert.strictEqual(filtered.length, 2, 'unparseable run_id entries are kept, not dropped'); +});