Verified medium/low reliability + storage items from the audit (the high-severity vector-cache, FTS-only degrade, and resume cap shipped in #12).
MEDIUM
- Main store runs
synchronous=FULL — store.ts:14-16 sets WAL but not synchronous=NORMAL (the memory store does, memory/store.ts:77). Every synchronous audit() fsyncs the WAL on the event loop; audit fires many times per turn. Fix: one line — PRAGMA synchronous = NORMAL in the constructor.
- Shutdown closes store/memory before sessions drain —
server.ts:125-137 registers sessions→memory→store; LIFO runs store/memory first, so interrupt()'s audit() (session.ts:1209) writes to a closed DB on shutdown-while-working (caught/swallowed → lost audit row, no corruption). Fix: register sessions last (drains first under LIFO), or drain explicitly before closing store/memory.
- No retention/pruning/VACUUM —
audit_log (store.ts:277), episodes/file_reads/turn_usage (memory/store.ts) grow forever (slow-burn, single-user local). Amplifies vector-matrix size. Fix: age/count retention sweep on start + periodic incremental_vacuum/wal_checkpoint(TRUNCATE); ship a codeoid prune.
LOW
- Embed batch not transactional —
engine.ts:299-305 commits per episode (capped at 8) and re-fires the FTS trigger each time. Fix: wrap the batch in db.transaction(...).
- Force-exit timer is
unref'd + no per-cleanup timeout — shutdown.ts:89-99,103-105. Usually fine (sockets registered first keep the loop alive so the timer fires), but a hung last cleanup with no other ref can't be force-killed. Fix: Promise.race each cleanup against a timeout; keep a ref'd grace timer.
INSERT OR REPLACE on createSession would wipe rotation/model columns — store.ts:116-118 lists 8 columns; OR REPLACE deletes+reinserts. Latent only (createSession runs only for fresh UUIDs, session.ts:415). Fix: ON CONFLICT(id) DO UPDATE scoped to create-time columns.
Verified medium/low reliability + storage items from the audit (the high-severity vector-cache, FTS-only degrade, and resume cap shipped in #12).
MEDIUM
synchronous=FULL—store.ts:14-16sets WAL but notsynchronous=NORMAL(the memory store does,memory/store.ts:77). Every synchronousaudit()fsyncs the WAL on the event loop; audit fires many times per turn. Fix: one line —PRAGMA synchronous = NORMALin the constructor.server.ts:125-137registerssessions→memory→store; LIFO runsstore/memoryfirst, sointerrupt()'saudit()(session.ts:1209) writes to a closed DB on shutdown-while-working (caught/swallowed → lost audit row, no corruption). Fix: registersessionslast (drains first under LIFO), or drain explicitly before closing store/memory.audit_log(store.ts:277),episodes/file_reads/turn_usage(memory/store.ts) grow forever (slow-burn, single-user local). Amplifies vector-matrix size. Fix: age/count retention sweep on start + periodicincremental_vacuum/wal_checkpoint(TRUNCATE); ship acodeoid prune.LOW
engine.ts:299-305commits per episode (capped at 8) and re-fires the FTS trigger each time. Fix: wrap the batch indb.transaction(...).unref'd + no per-cleanup timeout —shutdown.ts:89-99,103-105. Usually fine (sockets registered first keep the loop alive so the timer fires), but a hung last cleanup with no other ref can't be force-killed. Fix:Promise.raceeach cleanup against a timeout; keep a ref'd grace timer.INSERT OR REPLACEoncreateSessionwould wipe rotation/model columns —store.ts:116-118lists 8 columns; OR REPLACE deletes+reinserts. Latent only (createSession runs only for fresh UUIDs,session.ts:415). Fix:ON CONFLICT(id) DO UPDATEscoped to create-time columns.