The file was UTF-8 without BOM; Windows PowerShell 5.1 reads it as CP1252,
where the box-drawing/em-dash/arrow bytes (0x94/0x92) decode to smart quotes
(U+201D/U+2019) that PS treats as string delimiters, breaking the parser
("string is missing the terminator"). Replaced -, =, em/en dash, arrows and
smart quotes with ASCII equivalents.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause of the 2GB prod import.db: the sync_run_orders audit junction
recorded every order on every run; under the 1-minute scheduler ~98% of
21.7M rows were no-op ALREADY_IMPORTED re-observations. NSSM stdout/stderr
also grew unbounded (rotation never applied to the live service).
Changes:
- sqlite_service: skip ALREADY_IMPORTED rows in sync_run_orders (write-side
guard, _SKIP_JUNCTION_STATUSES); add prune_sync_history(retention_days)
with incremental_vacuum.
- maintenance_service (new): cleanup_old_logs + run_daily_maintenance.
- scheduler_service: start_maintenance_job (daily CronTrigger).
- main.py: RotatingFileHandler (sync_comenzi_current.log, 10MB x5) instead
of a new timestamped file per start; schedule daily maintenance + one-shot
catch-up at startup.
- scripts/db_maintenance.py (new): one-shot prune + VACUUM + log cleanup,
plain sqlite3, invoked by deploy.ps1 while the service is stopped.
- deploy.ps1: stop -> run db_maintenance.py -> (re)apply NSSM AppRotate*
idempotently -> start, so rotation reaches pre-existing services.
Retention defaults: 7 days history, 7 days logs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>