Реальный MonitoringService вместо NoopMonitoring: снимок пациента из clinical-БД → детерминированные правила (app.core.rules) → алерты в alerts, аудит crisis_acute, кеш status_color, уведомление врача (кризис — ещё и дежурному). Движку возвращаются только диалоговые действия. Смещение демо-часов сохраняется в clock_state и восстанавливается при старте.
app/services/snapshot.py — build_snapshot(session, token, as_of): маппинг sleep_bucket→sleep_hours_bucket, alcohol_bucket→alcohol, возраст из birth_year, день терапии, cssrs_risk из C-SSRS за последние 24 ч, weapon_access из dialog_state.data["facts"].
app/services/monitoring.py — RuleMonitoring (регистрируется при импорте), refresh_status() (для ack в #12), init_clock_persistence().
Кризис не перезапускается, пока его acute-алерт открыт (rules.evaluate кризисы не дедуплицирует — это задача оркестратора).
enhanced_monitoring ставит флаг в профиле, в движок не уходит.
Ошибка канала уведомлений не откатывает алерт.
app/scheduler/jobs.py: start() — восстановление часов (main.py заморожен).
tests/test_contracts.py::test_stubs_are_usable — теперь на sqlite в памяти: заглушки мониторинга больше нет, сервис ходит в БД.
Как проверить
make lint && make test — tests/test_services_monitoring.py: 13 дней Андрея через сервис → цвета G G G Y Y G G G G Y Y Y R, алерты, аудит, уведомления, персистентность часов.
Чек-лист
rebase на origin/dev
make lint + make test зелёные (693 passed)
лог в issue (### 2026-10-04)
нет ПДн в логах, нет реальных данных, нет секретов
## Что меняется
Реальный `MonitoringService` вместо `NoopMonitoring`: снимок пациента из clinical-БД → детерминированные правила (`app.core.rules`) → алерты в `alerts`, аудит `crisis_acute`, кеш `status_color`, уведомление врача (кризис — ещё и дежурному). Движку возвращаются только диалоговые действия. Смещение демо-часов сохраняется в `clock_state` и восстанавливается при старте.
Closes #38
## Зона
B
## Детали
- `app/services/snapshot.py` — `build_snapshot(session, token, as_of)`: маппинг `sleep_bucket`→`sleep_hours_bucket`, `alcohol_bucket`→`alcohol`, возраст из `birth_year`, день терапии, `cssrs_risk` из C-SSRS за последние 24 ч, `weapon_access` из `dialog_state.data["facts"]`.
- `app/services/monitoring.py` — `RuleMonitoring` (регистрируется при импорте), `refresh_status()` (для ack в #12), `init_clock_persistence()`.
- Кризис не перезапускается, пока его acute-алерт открыт (rules.evaluate кризисы не дедуплицирует — это задача оркестратора).
- `enhanced_monitoring` ставит флаг в профиле, в движок не уходит.
- Ошибка канала уведомлений не откатывает алерт.
- `app/scheduler/jobs.py: start()` — восстановление часов (main.py заморожен).
- `tests/test_contracts.py::test_stubs_are_usable` — теперь на sqlite в памяти: заглушки мониторинга больше нет, сервис ходит в БД.
## Как проверить
`make lint && make test` — `tests/test_services_monitoring.py`: 13 дней Андрея через сервис → цвета G G G Y Y G G G G Y Y Y R, алерты, аудит, уведомления, персистентность часов.
## Чек-лист
- [x] rebase на origin/dev
- [x] make lint + make test зелёные (693 passed)
- [x] лог в issue (### 2026-10-04)
- [x] нет ПДн в логах, нет реальных данных, нет секретов
- [x] общие файлы не трогались
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- 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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что меняется
Реальный
MonitoringServiceвместоNoopMonitoring: снимок пациента из clinical-БД → детерминированные правила (app.core.rules) → алерты вalerts, аудитcrisis_acute, кешstatus_color, уведомление врача (кризис — ещё и дежурному). Движку возвращаются только диалоговые действия. Смещение демо-часов сохраняется вclock_stateи восстанавливается при старте.Closes #38
Зона
B
Детали
app/services/snapshot.py—build_snapshot(session, token, as_of): маппингsleep_bucket→sleep_hours_bucket,alcohol_bucket→alcohol, возраст изbirth_year, день терапии,cssrs_riskиз C-SSRS за последние 24 ч,weapon_accessизdialog_state.data["facts"].app/services/monitoring.py—RuleMonitoring(регистрируется при импорте),refresh_status()(для ack в #12),init_clock_persistence().enhanced_monitoringставит флаг в профиле, в движок не уходит.app/scheduler/jobs.py: start()— восстановление часов (main.py заморожен).tests/test_contracts.py::test_stubs_are_usable— теперь на sqlite в памяти: заглушки мониторинга больше нет, сервис ходит в БД.Как проверить
make lint && make test—tests/test_services_monitoring.py: 13 дней Андрея через сервис → цвета G G G Y Y G G G G Y Y Y R, алерты, аудит, уведомления, персистентность часов.Чек-лист
🤖 Generated with Claude Code