diff --git a/src/cli.ts b/src/cli.ts index 059c997..494e313 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -339,8 +339,18 @@ program // The daily cache is provider-agnostic: always backfill it from .all so subsequent // provider-filtered reads can derive per-provider cost+calls from DailyEntry.providers. + // Yesterday is always recomputed: it may have been cached mid-day with partial data. const cache = await withDailyCacheLock(async () => { let c = await loadDailyCache() + + // Evict yesterday (and any stale future entries) so the gap fill recomputes them. + const hadYesterday = c.days.some(d => d.date >= yesterdayStr) + if (hadYesterday) { + const freshDays = c.days.filter(d => d.date < yesterdayStr) + const latestFresh = freshDays.length > 0 ? freshDays[freshDays.length - 1].date : null + c = { ...c, days: freshDays, lastComputedDate: latestFresh } + } + const gapStart = c.lastComputedDate ? new Date(new Date(`${c.lastComputedDate}T00:00:00.000Z`).getTime() + MS_PER_DAY) : new Date(todayStart.getTime() - BACKFILL_DAYS * MS_PER_DAY) diff --git a/src/daily-cache.ts b/src/daily-cache.ts index 1320aa6..11903bf 100644 --- a/src/daily-cache.ts +++ b/src/daily-cache.ts @@ -91,14 +91,11 @@ export async function saveDailyCache(cache: DailyCache): Promise { } export function addNewDays(cache: DailyCache, incoming: DailyEntry[], newestDate: string): DailyCache { - const seen = new Set(cache.days.map(d => d.date)) - const merged = [...cache.days] + const byDate = new Map(cache.days.map(d => [d.date, d])) for (const day of incoming) { - if (seen.has(day.date)) continue - seen.add(day.date) - merged.push(day) + byDate.set(day.date, day) } - merged.sort((a, b) => a.date.localeCompare(b.date)) + const merged = Array.from(byDate.values()).sort((a, b) => a.date.localeCompare(b.date)) const nextLast = cache.lastComputedDate && cache.lastComputedDate > newestDate ? cache.lastComputedDate : newestDate diff --git a/tests/daily-cache.test.ts b/tests/daily-cache.test.ts index b1741e3..e89d65d 100644 --- a/tests/daily-cache.test.ts +++ b/tests/daily-cache.test.ts @@ -117,7 +117,7 @@ describe('addNewDays', () => { expect(updated.lastComputedDate).toBe('2026-04-10') }) - it('skips days already present in the cache (first write wins)', () => { + it('replaces existing days with incoming data (last write wins)', () => { const base: DailyCache = { version: DAILY_CACHE_VERSION, lastComputedDate: '2026-04-08', @@ -125,7 +125,7 @@ describe('addNewDays', () => { } const updated = addNewDays(base, [emptyDay('2026-04-08', 99)], '2026-04-08') const aprilEight = updated.days.find(d => d.date === '2026-04-08')! - expect(aprilEight.cost).toBe(5) + expect(aprilEight.cost).toBe(99) }) it('does not regress lastComputedDate if incoming newestDate is older', () => {