feat(backend): monitoring service — snapshot, rules, alerts, status colour, clock persistence
CI / ruff · pytest (pull_request) Successful in 1m11s

- app/services/snapshot.py: PatientSnapshot from the clinical DB (field mapping, age, therapy day,
  recent C-SSRS risk, weapon access from dialog facts)
- app/services/monitoring.py: RuleMonitoring registered via register_monitoring; persists alert/crisis
  actions, crisis_acute audit, enhanced_monitoring flag, cached status_color, notifies the doctor (and
  the doctor on duty for crises) after commit; a running crisis is not restarted
- demo clock offset persisted in clock_state, restored on scheduler start
- tests: Andrey's 13 days through the service → G G G Y Y G G G G Y Y Y R

Refs #38

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 03:13:57 +03:00
co-authored by Claude Opus 5.5
parent 20973bef17
commit 4c0836a1be
5 changed files with 548 additions and 3 deletions
+6
View File
@@ -12,6 +12,7 @@ from datetime import datetime
from zoneinfo import ZoneInfo
from sqlalchemy import select, text
from sqlalchemy.exc import SQLAlchemyError
from app.core import clock
from app.core.intake_runtime import due_scales, intake_enabled, load_runtime
@@ -21,6 +22,7 @@ from app.db.intake import QuestionnaireTask
from app.db.session import get_clinical_session
from app.dialog.contracts import Event, Reply, get_engine
from app.integrations.base import integrations
from app.services import monitoring
from app.services import questionnaire as service
log = logging.getLogger(__name__)
@@ -163,6 +165,10 @@ async def _run():
async def start():
global _worker
try:
await monitoring.init_clock_persistence()
except (OSError, SQLAlchemyError) as exc:
log.error("clock persistence unavailable error=%s", type(exc).__name__)
if _worker is None and intake_enabled():
_worker = asyncio.create_task(_run())