diff --git a/mac/Sources/CodeBurnMenubar/CodeBurnApp.swift b/mac/Sources/CodeBurnMenubar/CodeBurnApp.swift index 095b4df..7f9ec47 100644 --- a/mac/Sources/CodeBurnMenubar/CodeBurnApp.swift +++ b/mac/Sources/CodeBurnMenubar/CodeBurnApp.swift @@ -78,9 +78,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate { // regardless of whether the user is currently viewing Today or a // different period / provider. await self.store.refreshQuietly(period: .today) - // Refresh the currently-viewed payload. Optimize is fast (~1s warm-cache) - // so include findings on every refresh. + self.refreshStatusButton() await self.store.refresh(includeOptimize: true) + self.refreshStatusButton() try? await Task.sleep(nanoseconds: refreshIntervalNanos) } } diff --git a/src/cli.ts b/src/cli.ts index 7bd91a9..e655180 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -388,7 +388,7 @@ program .option('--no-cache', 'Rebuild the parsed source cache for this run') .action(async (opts) => { await loadPricing() - const noCache = noCacheRequested(opts) + const noCache = noCacheRequested(opts) || opts.format === 'menubar-json' const parseOptions = buildParseOptions(noCache, opts.format === 'terminal') const pf = opts.provider const fp = (p: ProjectSummary[]) => filterProjectsByName(p, opts.project, opts.exclude) diff --git a/src/dashboard.tsx b/src/dashboard.tsx index 0f54eba..ee505cf 100644 --- a/src/dashboard.tsx +++ b/src/dashboard.tsx @@ -706,11 +706,11 @@ function InteractiveDashboard({ initialProjects, initialPeriod, initialProvider, } }, [findCachedWindow, makeCacheToken, noCache, storeCachedWindow]) - const reloadData = useCallback(async (p: Period, prov: string, options?: { silent?: boolean }) => { + const reloadData = useCallback(async (p: Period, prov: string, options?: { silent?: boolean; skipCache?: boolean }) => { const range = getDateRange(p) const request = ++reloadSeqRef.current const token = makeCacheToken(prov, p) - const cachedWindow = findCachedWindow(prov, range) + const cachedWindow = options?.skipCache ? undefined : findCachedWindow(prov, range) if (!options?.silent) { setOptimizeResult(null) } @@ -835,7 +835,7 @@ function InteractiveDashboard({ initialProjects, initialPeriod, initialProvider, useEffect(() => { if (!refreshSeconds || refreshSeconds <= 0) return - const id = setInterval(() => { reloadData(period, activeProvider) }, refreshSeconds * 1000) + const id = setInterval(() => { reloadData(period, activeProvider, { skipCache: true }) }, refreshSeconds * 1000) return () => clearInterval(id) }, [refreshSeconds, period, activeProvider, reloadData]) diff --git a/src/parser.ts b/src/parser.ts index 3a0eb77..ed00d73 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -671,11 +671,6 @@ async function evaluateSourceManifestState( return state } - const overlap = isManifestDateRangeOverlap(manifestEntry, dateRange) - if (overlap === false) { - return { source, parserVersion, manifestEntry, action: 'skip', reason: 'range-miss' } - } - if (!manifestEntry.fingerprint || manifestEntry.fingerprintPath !== fingerprintPath) { const state: SourceManifestState = { source, parserVersion, manifestEntry, action: 'refresh', reason: 'fingerprint-miss' } logCacheDebug(source.provider, source.path, state.reason!) @@ -690,6 +685,10 @@ async function evaluateSourceManifestState( } if (fingerprintMatches(currentFingerprint, manifestEntry.fingerprint)) { + const overlap = isManifestDateRangeOverlap(manifestEntry, dateRange) + if (overlap === false) { + return { source, parserVersion, manifestEntry, action: 'skip', reason: 'range-miss' } + } return { source, parserVersion, manifestEntry, action: 'use-cache', currentFingerprint } } @@ -767,7 +766,7 @@ async function refreshClaudeCacheUnit( if (state.action === 'use-cache') { const cached = await readSourceCacheEntry(manifest, 'claude', state.source.path, { allowStaleFingerprint: true }) - if (cached) { + if (cached && cached.sessions.length > 0) { addSeenDeduplicationKeysFromSessions(cached.sessions, localSeenMsgIds) return { session: cached.sessions[0] ?? null, wrote: false, refreshed: false } } @@ -969,7 +968,7 @@ async function parseProviderSources( let fullSessions: SessionSummary[] | null = null if (state.action === 'use-cache') { const cached = await readSourceCacheEntry(cacheManifest, providerName, state.source.path, { allowStaleFingerprint: true }) - if (cached) fullSessions = cached.sessions + if (cached && cached.sessions.length > 0) fullSessions = cached.sessions } if (!fullSessions) {