Collect and save hourly snapshots of SciDEX knowledge growth metrics (analyses, hypotheses, KG edges, papers, wiki pages, causal edges). Detect catastrophic loss (regressions) and stalled growth. This is a recurring task that runs every hour to track system growth over time.
ERROR level with metric name, previous value, current valueWARNING levelanalyses_count, hypotheses_count, kg_edges_countThe metrics.py module already provides:
collect_snapshot() — collect current metric valuessave_snapshot() — store to knowledge_snapshots tabledetect_regressions() — find decreased metricsdetect_stalls() — find stalled metricsrun_snapshot_cycle() — main entry pointmetrics.run_snapshot_cycle()knowledge_snapshots table populated with metric valuesmetrics.py module (already implemented)demo_live_growth_metrics_spec.md)metrics.py already implements snapshot collection and regression detectiondocs/planning/specs/05b6876b_61a_spec.mdpython3 metrics.py — snapshot collected successfullyhypotheses_count, kg_edges_count (zero growth 2+ hours)datetime.utcnow() → datetime.now(timezone.utc)python3 metrics.py — snapshot collected successfullykg_edges_count (zero growth 2+ hours) — WARNING loggeddatetime.utcnow() deprecation warnings in get_history() and project_milestones()python3 metrics.py — snapshot collected successfullyanalyses_count, hypotheses_count, kg_edges_count (zero growth 2+ hours) — WARNING loggedpython3 metrics.py — snapshot collected successfullyhypotheses_count, kg_edges_count (zero growth 2+ hours) — WARNING loggedmetrics.py inline fallback had if os.environ.get('SCIDEX_DB_BACKEND', '').lower() == 'postgres' — defaulting to SQLite when env var is unset (empty string != 'postgres')SCIDEX_DB_BACKEND == 'sqlite'scidex/senate/metrics.py already uses PG via get_db() from scidex.core.database — the inline fallback was the broken piecepython3 metrics.py with worktree-first sys.path runs clean (collects, saves, detects stalls)scidex.senate.metrics is unavailable; in normal operation it delegates to the canonical module which uses PGmetrics.py get_db() function; scidex/senate/metrics.py unchanged (already correct)orchestra reset 05b6876b-61a9-4a49-8881-17e8db81746ccollect_snapshot() read KPIs from theme_config registry instead of hardcoded SQL dictget_enabled_kpis() helper: queries theme_config WHERE theme_id='S8' AND key LIKE 'kpi.%' AND enabled=true, falls back to _LEGACY_KPISdetect_stalls() now reads stall-tracked metrics from theme_config key s8.stall_tracked; falls back to _STALL_TRACKEDdetect_regressions() dynamically discovers metrics from knowledge_snapshots table (adapts to registry changes)calculate_growth_rates() and get_growth_history() now use registry-derived KPI listsave_snapshot(): uses PostgreSQL date_trunc('hour', timestamp) to detect duplicate hour-bucket inserts; skips insert if bucket already exists (timezone-aware)idx_edges_source index causes "database disk image malformed" on queries using source_id != '' or relation IN (5 values)wiki_pages table corrupted (COUNT(*) fails), but wiki_pages_fts FTS virtual table is intactmetrics.py and scidex/senate/metrics.py:kg_edges_count: removed WHERE source_id != '' AND target_id != '' filter → uses full table count (707K)wiki_pages_count: use wiki_pages_fts as proxy (17574 pages, FTS intact)causal_edges_count: replaced IN (...) with OR chain to avoid corrupted index
python3 metrics.py now runs clean (no DB errors)orchestra update --id 05b6876b-61a9-4a49-8881-17e8db81746c --status open