- api/index.php: auto-delete legacy dispensa.db when evershelf.db exists
and dispensa.db is empty (<1KB); vacuum-sealed items only show as
expired after VACUUM_EXPIRY_EXTENSION_DAYS (default 30) past printed
date; add dbCleanup() function; add recipe/tx/vacuum params to
getServerSettings + saveSettings intMap; add 'db_cleanup' action
- api/cron_smart_shopping.php: run dbCleanup() each cron cycle
- app.js: add zerowaste_tips_enabled + screensaver_timeout + retention
days to saveSettings POST payload (were missing, causing reset on sync);
asset version bumped to v=20260518b
- .env: added ZEROWASTE_TIPS_ENABLED, RECIPE_RETENTION_DAYS=7,
TRANSACTION_RETENTION_DAYS=7, VACUUM_EXPIRY_EXTENSION_DAYS=30
- Remove recentlyExhausted bypass from shopping_name family suppression:
products recently exhausted (<14d) were incorrectly flagged as critical
even when the same family had ample stock (Yogurt 2002g, Affettato 1022g,
Pane 400g). recentlyExhausted now only bypasses loose token-based coverage.
- Add prewarmShelfLifeCache() in cron: pre-warms opened shelf life via
Gemini AI (max 5 items/cycle) so the UI never blocks on first load.
PHP api/index.php:
- DB connection failure (500) now calls _phpErrorReport()
- Main router catch-all (500) now calls _phpErrorReport()
- undoTransaction DB error (500) now calls _phpErrorReport()
PHP api/cron_smart_shopping.php:
- cron Throwable catch now calls _phpErrorReport() before exit(1)
(fires even in CRON_MODE since _phpErrorReport() has its own guard)
Scale Gateway GatewayWebSocketServer.kt:
- onError() now calls ErrorReporter.report(ex, ...) in addition to Log.e
Combined with previous kiosk commit, every error path in the entire
EverShelf stack now sends an automatic GitHub Issue.