The cache is a rebuildable index over gitea, never a source of truth (D4).
Two tests lock that invariant where the durable cache actually lives:
- packages/core: cache-purity-v0.test.ts — file-backed node:sqlite. Build the
SQLite mirror from a gitea snapshot, capture every re-derived field, delete the
.sqlite file, rebuild from the same snapshot, assert byte-identical. Plus a
structural D4 guard: every issues-table column must map to a gitea field, so a
future user-authored column can't silently break rebuild-ability.
- apps/desktop: snapshot-store.test.ts — the shipped durable cache is the JSON
snapshot-store. Delete the file → loadSnapshot returns null (degrades to
no-cache, never throws), which is what forces the next getSnapshot to reconcile
fresh from gitea. Corrupt/partial files are likewise treated as no-cache.
Stands up vitest for the desktop main process (first unit tests there);
electron is mocked, snapshot path is injected.
No native better-sqlite3 shipped: the SQLite mirror has no consumer on any hot
path yet, so wiring it into main (native module + asarUnpack + dmg re-verify)
would add packaging risk for no runtime benefit. The purity invariant is proven
at the seam for both caches; the native driver migration is deferred until
SQLite becomes load-bearing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>