Детерминированный движок правил алертов и «действий агента» (ADR-007) и демо-часы (ADR-005). Правила объявлены в config/rules.yaml (пороги, действия, уровни, текст для врача), предикаты реализованы в app/core/rules.py функциями, зарегистрированными под тем же id. Цвета статуса пациента считаются по ADR-006.
Дедуп: если открыт 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)
нет ПДн в логах, нет реальных данных, нет секретов
## Что меняется
Детерминированный движок правил алертов и «действий агента» (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)
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.
Что меняется
Детерминированный движок правил алертов и «действий агента» (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не подавляется никогда (повторно запускать кризисный скрипт не должен оркестратор).recent_hours). Дальше пациент остаётся красным за счёт открытого acute-алерта.cssrs_moderate→ HIGH (SPEC §6: Safety POSSIBLE → high).missed/skipped), и ответ «не принял» в чек-ине.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)Чек-лист
🤖 Generated with Claude Code