[backend][B] Сервис мониторинга: снимок пациента → правила → алерты, статус, персистентность демо-часов #38
Notifications
Due Date
No due date set.
Blocks
Depends on
#12 [backend][B] API этапа 1: реальная реализация вместо фикстур
MedITron/PTSRaiAgent
Reference: MedITron/PTSRaiAgent#38
Reference in New Issue
Block a user
Описание
Реализация
MonitoringServiceизapp/services/contracts.py. Связывает БД иapp.core.rules(ADR-007): правила детерминированы, сервис персистит результат.Желаемый результат
app/services/snapshot.py:build_snapshot(token, as_of) -> PatientSnapshotизapp.db.repo(маппинг имён:alcohol_bucket→alcohol,sleep_bucket→sleep_hours_bucket; возраст изbirth_year; день терапии из профиля).app/services/monitoring.py:after_data_change(token)→evaluate()→alert/crisisпишутся вalerts+Notifier; кешируемыйstatus_colorв профиле; возврат диалоговых действий движку. Кризис: аудитcrisis_acute, дежурный врач.app.core.clockвclock_state(черезregister_persistence).Зона и владение файлами
Lane B (backend) — владеет:
app/api/**(кромеschemas.py),app/services/**,app/scheduler/**,app/integrations/**(кромеbase.py),app/db/**,scripts/**,data/**,tests/test_api*.py,tests/test_services*.py,tests/test_scheduler*.py,tests/test_seed*.py,tests/test_integrations*.py.Замороженные контракты (менять только отдельным мелким PR с пингом всех):
app/core/types.py,app/dialog/contracts.py,app/api/schemas.py,app/integrations/base.py,app/services/contracts.py,app/main.py,app/config.py,config/modules.yaml,config/rules.yaml,config/scales/*,pyproject.toml/uv.lock,docker-compose.yml,Makefile.Лог выполнения
2026-10-04
app/services/snapshot.py+app/services/monitoring.py(RuleMonitoring, регистрация через register_monitoring), аудит crisis_acute, уведомления врачу и дежурному, кеш status_color, флаг enhanced_monitoring.Контракт с lane A (движок #10, PR #50 смержен). Что сервис мониторинга должен читать из
dialog_state.data(repo.get_dialog_state(s, token).data). Там только коды, текста пациента нет:safety_events— список последних 50 событий:{"ts", "level": "acute"|"possible", "categories": [...], "rules": [...], "source": "lexicon"|"llm"|"both", "handled": "crisis_script"|"crisis_repeat"|"risk_screen"|"dispatched", "state"}. После каждой записи движок вызываетafter_data_change(token). Если естьacute, который ещё не превращён в алерт, нужно создать алертacuteс кодомsafety_acute, уведомить дежурного и записать в аудитcrisis_acute.crisis—{"open", "opened_at", "source": "safety:…"|"scale:phq9"|"rule:<id>", "variant", "closed_at"}.contact_requests—[{"ts"}]: пациент нажал «Связаться с врачом». Нужен алерт уровня info/moderate на дашборд.consent,revoked_at,delete_requested: true— пациент отозвал согласие. Пометить данные к удалению — задача lane B.is_in_crisis(token)должен возвращать True, пока открытacute-алерт без ack. Движок выходит изcrisisпоis_in_crisis()==Falseили по системному событиюdoctor_ack, поэтому при ack острого алерта в API отправьтеEvent(type="system", system="doctor_ack")вget_engine().handle(token, ...).