feat(core): движок правил алертов и действий + демо-часы #30

Merged
Eleboba merged 1 commits from feat/5-rules into dev 2026-10-03 14:59:47 +03:00
Owner

Что меняется

Детерминированный движок правил алертов и «действий агента» (ADR-007) и демо-часы (ADR-005). Правила объявлены в config/rules.yaml (пороги, действия, уровни, текст для врача), предикаты реализованы в app/core/rules.py функциями, зарегистрированными под тем же id. Цвета статуса пациента считаются по ADR-006.

Closes #5

Зона

core

Публичный API

  • app.core.clock: now() -> datetime (с tz), today(), offset(), advance(days=0, hours=0, minutes=0), set_now(dt), reset(), register_persistence(load, save)
  • app.core.rules: PatientSnapshot, DailyCheckin, ScalePoint, DoseRecord, Action (.creates_alert), evaluate(snapshot, config=None) -> list[Action], load_rules(path=None), color(levels), patient_status(open_alert_levels) -> PatientStatus(color, top_level)

Решения

  • Дедуп: если открыт alert с кодом правила, правило молчит целиком: не повторяются ни алерт, ни med_info, ни reach_out. crisis не подавляется никогда (повторно запускать кризисный скрипт не должен оркестратор).
  • П.9 PHQ-9 → crisis только для PHQ-9 за последние 24 ч (recent_hours). Дальше пациент остаётся красным за счёт открытого acute-алерта.
  • Серии «N дней подряд» заканчиваются сегодня, а если сегодняшнего чек-ина ещё нет — вчера. Пропущенный день серию прерывает.
  • Добавлено cssrs_moderate → HIGH (SPEC §6: Safety POSSIBLE → high).
  • Пропуски 3/7 считаются по дням: учитываются и записи доз (missed/skipped), и ответ «не принял» в чек-ине.
  • Траектория персоны совпала с таблицей без отступлений: дни 11–12 жёлтые, потому что алерты alcohol_3d и sleep_lt4_3n открыты (врач их не подтверждал). В день 6 врач подтверждает quit_intent и side_effect_3d. В день 13 до внепланового PHQ-9 срабатывает mood_low_3d → schedule_scale(phq9), после него — phq9_item9 (crisis) и phq9_rise (13 → 18).

Как проверить

make lint test (tests/test_rules.py, tests/test_clock.py)

Чек-лист

  • rebase на origin/dev
  • make lint + make test зелёные
  • лог в issue (### 2026-10-03)
  • нет ПДн в логах, нет реальных данных, нет секретов

🤖 Generated with Claude Code

## Что меняется Детерминированный движок правил алертов и «действий агента» (ADR-007) и демо-часы (ADR-005). Правила объявлены в `config/rules.yaml` (пороги, действия, уровни, текст для врача), предикаты реализованы в `app/core/rules.py` функциями, зарегистрированными под тем же id. Цвета статуса пациента считаются по ADR-006. Closes #5 ## Зона core ## Публичный API - `app.core.clock`: `now() -> datetime` (с tz), `today()`, `offset()`, `advance(days=0, hours=0, minutes=0)`, `set_now(dt)`, `reset()`, `register_persistence(load, save)` - `app.core.rules`: `PatientSnapshot`, `DailyCheckin`, `ScalePoint`, `DoseRecord`, `Action` (`.creates_alert`), `evaluate(snapshot, config=None) -> list[Action]`, `load_rules(path=None)`, `color(levels)`, `patient_status(open_alert_levels) -> PatientStatus(color, top_level)` ## Решения - Дедуп: если открыт `alert` с кодом правила, правило молчит целиком: не повторяются ни алерт, ни `med_info`, ни `reach_out`. `crisis` не подавляется никогда (повторно запускать кризисный скрипт не должен оркестратор). - П.9 PHQ-9 → crisis только для PHQ-9 за последние 24 ч (`recent_hours`). Дальше пациент остаётся красным за счёт открытого acute-алерта. - Серии «N дней подряд» заканчиваются сегодня, а если сегодняшнего чек-ина ещё нет — вчера. Пропущенный день серию прерывает. - Добавлено `cssrs_moderate` → HIGH (SPEC §6: Safety POSSIBLE → high). - Пропуски 3/7 считаются по дням: учитываются и записи доз (`missed`/`skipped`), и ответ «не принял» в чек-ине. - Траектория персоны совпала с таблицей без отступлений: дни 11–12 жёлтые, потому что алерты `alcohol_3d` и `sleep_lt4_3n` открыты (врач их не подтверждал). В день 6 врач подтверждает `quit_intent` и `side_effect_3d`. В день 13 до внепланового PHQ-9 срабатывает `mood_low_3d` → `schedule_scale(phq9)`, после него — `phq9_item9` (crisis) и `phq9_rise` (13 → 18). ## Как проверить `make lint test` (`tests/test_rules.py`, `tests/test_clock.py`) ## Чек-лист - [x] rebase на origin/dev - [x] make lint + make test зелёные - [x] лог в issue (### 2026-10-03) - [x] нет ПДн в логах, нет реальных данных, нет секретов 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Eleboba added 1 commit 2026-10-03 14:59:09 +03:00
feat(core): rule engine for alerts/agent actions and virtual demo clock
CI / ruff · pytest (pull_request) Successful in 18s
711c646876
- app/core/clock.py: now()/today(), virtual offset (advance/set_now/reset),
  pluggable offset persistence hook (ADR-005)
- config/rules.yaml + app/core/rules.py: YAML declares rules (params, actions,
  levels, reason_ru), Python evaluators implement predicates by id; dedup of
  open alerts, crisis never suppressed; ADR-006 colours (ADR-007)
- tests: per-rule unit tests, dedup, clock, 13-day demo persona trajectory

Refs #5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eleboba merged commit 62f34731f7 into dev 2026-10-03 14:59:47 +03:00
Eleboba deleted branch feat/5-rules 2026-10-03 14:59:48 +03:00
Sign in to join this conversation.