Every store gets a limit: a 4-way audit of everything DalkkakAI grows, and the GC that enforces it
After the 255MB-journal freeze, we audited every accumulating store (9 HIGH + 15 MEDIUM unbounded), shipped a startup GC for the safe ones, capped telemetry at birth, partition-loaded the MCP index (48MB vs 170MB RSS measured), and wrote the limits spec with a rule: no new append-file without a limit row.
The 2026-07-16 incident taught us that "it's small now" is how machines freeze. So instead of tripwires-for-later, we ran a 4-way parallel audit over everything the app writes: graph stores, journals/receipts/logs, MCP-server files + renderer localStorage, and runtime artifacts (persona launchers, mission-control ledgers, engineering-run dirs, merge bundles).
Result: 9 HIGH and 15 MEDIUM unbounded accumulators — 589 per-pane identity files with no deletion code anywhere, daily runtime logs kept forever, a new persona launcher script per relaunch, journal archives that only ever grow.
Shipped in one pass:
storage_gc::run_startup_gc()— retention for the mechanically-safe, app-owned stores (journal archives keep-5/30d, dead-letter 5MB fixed archive, runtime logs 14d, pane files 30d with newest-200 protection, launcher generations 14d/newest-50). User repos and~/.codexare excluded by policy — those need receipt-aware flows.- Telemetry capped at birth: the brand-new read-metrics log got its 2MB rolling cap in the same commit that created it.
- The MCP memory index is now partition-loaded per session scope: 48MB vs 170MB RSS measured on the real graph, and scoped RSS stays flat as other projects grow.
docs/product/storage-limits-spec-2026-07-18.md: every store, its decided limit, its status — and the standing rule: a PR that adds an append-file must add a limits row.
Honest remainder: receipts retention, mission-control ledger caps, engineering-run dir sweeps, merge-bundle lifecycle, localStorage per-startup teardown, and periodic (not just startup) journal rotation are TODO rows in the spec, not silent gaps.