Skip to content

fix(parser): cache parse failures so broken files aren't re-read every run (#441 follow-up)#453

Merged
iamtoruk merged 1 commit into
mainfrom
fix/negative-parse-cache
Jun 6, 2026
Merged

fix(parser): cache parse failures so broken files aren't re-read every run (#441 follow-up)#453
iamtoruk merged 1 commit into
mainfrom
fix/negative-parse-cache

Conversation

@iamtoruk
Copy link
Copy Markdown
Member

@iamtoruk iamtoruk commented Jun 6, 2026

Follow-up to #450 (issue #441). Addresses the two non-blocking items noted there.

Problems

  1. Re-parse loop: when a session file failed to parse, it was excluded but left uncached. Successfully-parsed files get a fingerprint cache entry and are skipped if unchanged, but a failed file had none — so every menubar refresh (~4×/min) re-read and re-parsed it, hitting the same throw. Bounded per file, but wasted I/O forever.
  2. Thin visibility: the warning fired once per provider per process, naming only the first offending file. A systemic break (many bad files of one provider) surfaced as a single line, so the scope of what was skipped was invisible.

Fix

  • Negative-result marker: a failed file is now cached as { fingerprint, turns: [], failed: true }. reconcileFile treats it as unchanged at the same fingerprint → it's skipped (no re-read) until the file actually changes (fingerprint differs → re-parsed/retried). Empty turns means it contributes no usage, same as before.
  • Per-file warnings, capped: warn once per offending file (with its path), capped at 5 per provider per run, then suppressed with a note — instead of once-per-provider. Cached markers mean a given broken file isn't re-encountered across refreshes, so this stays quiet.

Why it's safe

  • A clean array still returns by reference; the marker only changes the failure path.
  • The marker carries no turns, so query-time aggregation is unaffected (no undercount-as-zero — it's simply absent from totals, exactly as before).
  • validateCachedFile accepts the optional failed field; markers round-trip through save/load.

Testing

  • New tests: marker persists through save/load; reconcileFile stays unchanged at the same fingerprint and returns modified once the file changes (retry).
  • Full suite: 1060 tests pass. tsc --noEmit clean.

…y run (#441 follow-up)

Follow-up to #450. When a session file throws during parse it was excluded but
left uncached, so every refresh (~4x/min in the menubar) re-read and re-parsed
it, and only the first failing file per provider was ever surfaced.

- Add a negative-result marker: a failed file is cached as { fingerprint,
  turns: [], failed: true }. reconcileFile treats it as 'unchanged' at the same
  fingerprint, so it's skipped (no re-read) until the file changes. Empty turns
  => contributes no usage.
- Warn per offending file (with its path), capped at 5 per provider per run,
  instead of once-per-provider — so a systemic break surfaces more than one file
  without flooding. Cached markers keep it quiet across refreshes.

Tests: marker round-trips through save/load; reconcile stays 'unchanged' at the
same fingerprint and re-parses when the file changes.
@iamtoruk iamtoruk merged commit efa8593 into main Jun 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant