Evidence (reproduced locally 2026-06-12)
Astro's glob loader caches parsed entries in .astro/data-store.json keyed by file content digest only. A schema change with unchanged content files does not invalidate the cache, so getEntry()/getCollection() keep returning data parsed by the old schema.
Observed concretely on this machine: .astro/data-store.json (mtime Jun 3) held top_wallets items as {truncated_id, category} — hypothetical_pnl_usd stripped, because the cached parse predated commit a379d8b which added that field to truncatedWallet (Zod strips undeclared keys). A fresh pnpm dev on Jun 12 happily reused it: every wallet on /statements/2026-05-31-weekly rendered Bucket/Share as —, while production (built fresh in CI) showed <$25 / ~+$25 / ~+$175 etc. Deleting data-store.json and re-syncing fixed dev instantly (done — local cache is healed).
Why it matters beyond confusing dev sessions: package.json exposes deploy, deploy:dev, deploy:staging, deploy:production that build locally — a local deploy after a schema change can ship stale/wrong data to a live Worker. CI deploys are safe only because the checkout is fresh.
TDD plan / fix directions (pick smallest that closes the hole)
- Make local builds immune: change the build script to clear the content-layer store first —
"build": "astro build --force" if supported by the installed Astro (check astro build --help; content-layer --force re-syncs), else "prebuild": "rm -rf .astro/data-store.json". Test: a scripts/-level test (same convention as wrangler-config.test.ts) asserting the build/deploy scripts include the invalidation step — guards against someone removing it.
- Optionally do the same for
dev (slower startup vs correctness — document the tradeoff; minimum: add a troubleshooting note in CLAUDE.md "if content data looks stale: rm .astro/data-store.json").
- Consider an upstream Astro issue/check — schema-hash-aware invalidation is arguably an Astro bug; worth a quick search of withastro/astro issues before working around it forever.
Acceptance criteria
| AC |
Test |
pnpm build (and all deploy:* paths) never reuses a parse made by an older schema |
script-content test + manual repro: stale store + build → built worker contains current fields |
| Documented recovery for dev staleness |
CLAUDE.md note |
Evidence (reproduced locally 2026-06-12)
Astro's glob loader caches parsed entries in
.astro/data-store.jsonkeyed by file content digest only. A schema change with unchanged content files does not invalidate the cache, sogetEntry()/getCollection()keep returning data parsed by the old schema.Observed concretely on this machine:
.astro/data-store.json(mtime Jun 3) heldtop_walletsitems as{truncated_id, category}—hypothetical_pnl_usdstripped, because the cached parse predated commit a379d8b which added that field totruncatedWallet(Zod strips undeclared keys). A freshpnpm devon Jun 12 happily reused it: every wallet on/statements/2026-05-31-weeklyrendered Bucket/Share as—, while production (built fresh in CI) showed<$25 / ~+$25 / ~+$175etc. Deletingdata-store.jsonand re-syncing fixed dev instantly (done — local cache is healed).Why it matters beyond confusing dev sessions:
package.jsonexposesdeploy,deploy:dev,deploy:staging,deploy:productionthat build locally — a local deploy after a schema change can ship stale/wrong data to a live Worker. CI deploys are safe only because the checkout is fresh.TDD plan / fix directions (pick smallest that closes the hole)
"build": "astro build --force"if supported by the installed Astro (checkastro build --help; content-layer--forcere-syncs), else"prebuild": "rm -rf .astro/data-store.json". Test: ascripts/-level test (same convention aswrangler-config.test.ts) asserting the build/deploy scripts include the invalidation step — guards against someone removing it.dev(slower startup vs correctness — document the tradeoff; minimum: add a troubleshooting note in CLAUDE.md "if content data looks stale: rm .astro/data-store.json").Acceptance criteria
pnpm build(and all deploy:* paths) never reuses a parse made by an older schema