CI / ruff · pytest (pull_request) Successful in 18s
- 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>
179 lines
8.5 KiB
YAML
179 lines
8.5 KiB
YAML
# Alert & agent-action rules (ADR-007, ADR-008).
|
||
#
|
||
# Split of responsibilities:
|
||
# * This file DECLARES the rules: id, clinical description, thresholds/windows (`params`), which actions the
|
||
# rule produces (type, level, extra params) and the short Russian reason shown on the doctor dashboard.
|
||
# A psychiatrist can change thresholds, levels, actions and texts here without touching code.
|
||
# * `app/core/rules.py` IMPLEMENTS the predicate of each rule as a Python function registered under the
|
||
# same `id` (`@evaluator("<id>")`). The function reads only the patient snapshot and `params` from here.
|
||
# Adding a new rule = new YAML entry + new evaluator; an id without an evaluator fails at load time.
|
||
#
|
||
# Fields:
|
||
# id — stable rule id; also the default alert/reason code (dedup key, stored with the alert).
|
||
# description — what and why (for the reviewer/jury); not shown to patients.
|
||
# enabled — false switches the rule off without deleting it.
|
||
# params — thresholds/windows passed to the evaluator; also available in `reason_ru` as {name}.
|
||
# actions — produced in this order when the predicate fires. `level` is info|moderate|high|acute.
|
||
# Action `params` are merged with values computed by the evaluator.
|
||
# reason_ru — short text for the doctor (str.format with params + evaluator values).
|
||
#
|
||
# Dedup: if a rule produces an `alert` whose code is already open (not acked by the doctor), the whole rule
|
||
# is silent — no repeated alert, no repeated med_info/reach_out. `crisis` is never suppressed.
|
||
#
|
||
# Starting thresholds are from SPEC §6, CLINICAL_MODULES.md and the demo persona; final values are approved
|
||
# by the team psychiatrist.
|
||
|
||
rules:
|
||
# ---------------------------------------------------------------- suicide risk → crisis (red, ADR-006)
|
||
- id: phq9_item9
|
||
description: >
|
||
PHQ-9 item 9 (thoughts of death/self-harm) >= 1 in a recent PHQ-9. Always a crisis: fixed safety
|
||
script, safety plan on screen, C-SSRS screening, immediate escalation to the doctor on duty.
|
||
params: {threshold: 1, recent_hours: 24}
|
||
actions:
|
||
- {type: crisis, level: acute}
|
||
- {type: show_safety_plan}
|
||
- {type: schedule_scale, params: {scale: cssrs_screen, scheduled: false}}
|
||
reason_ru: "PHQ-9 п.9 = {item9} (мысли о смерти/самоповреждении)"
|
||
|
||
- id: cssrs_high
|
||
description: >
|
||
C-SSRS: suicidal ideation with intent/plan or suicidal behaviour (risk "high") → urgent escalation,
|
||
safety plan and crisis contacts on screen.
|
||
params: {}
|
||
actions:
|
||
- {type: crisis, level: acute}
|
||
- {type: show_safety_plan}
|
||
reason_ru: "C-SSRS: высокий риск (намерение/план или поведение)"
|
||
|
||
- id: weapon_access_risk
|
||
description: >
|
||
Access to weapons together with any suicide-risk signal (recent PHQ-9 item 9 >= 1 or C-SSRS >= moderate).
|
||
Means restriction is one of the most evidence-based suicide-prevention measures → crisis safety block.
|
||
params: {item9_threshold: 1, cssrs_min: moderate, recent_hours: 24}
|
||
actions:
|
||
- {type: crisis, level: acute}
|
||
- {type: show_safety_plan, params: {block: means_restriction}}
|
||
reason_ru: "Доступ к оружию при сигнале суицидального риска"
|
||
|
||
- id: cssrs_moderate
|
||
description: >
|
||
C-SSRS moderate (ideation without plan/intent) = SPEC "Safety POSSIBLE" → doctor within 24 h.
|
||
params: {}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
reason_ru: "C-SSRS: умеренный риск, врачу в течение 24 ч"
|
||
|
||
# ---------------------------------------------------------------- scale thresholds (yellow)
|
||
- id: phq9_severe
|
||
description: Latest PHQ-9 total in the severe range (>= 20) → doctor within 24 h.
|
||
params: {threshold: 20}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
reason_ru: "PHQ-9 = {total} (тяжёлая депрессия, порог {threshold})"
|
||
|
||
- id: pcl5_severe
|
||
description: Latest PCL-5 total >= 50 → doctor within 24 h.
|
||
params: {threshold: 50}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
reason_ru: "PCL-5 = {total} (порог {threshold})"
|
||
|
||
- id: phq9_rise
|
||
description: PHQ-9 rose by >= 5 points between the two latest measurements → doctor within 24 h.
|
||
params: {min_rise: 5}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
reason_ru: "Рост PHQ-9 {previous} → {total} (+{rise})"
|
||
|
||
- id: pcl5_rise
|
||
description: PCL-5 rose by >= 10 points between the two latest measurements (veteran module) → doctor.
|
||
params: {min_rise: 10}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
reason_ru: "Рост PCL-5 {previous} → {total} (+{rise})"
|
||
|
||
- id: auditc_positive
|
||
description: >
|
||
AUDIT-C positive screen (>= 4 men / >= 3 women). Alcohol is a suicide risk factor and interacts with
|
||
antidepressants → flag for the visit, daily alcohol question.
|
||
params: {threshold_m: 4, threshold_f: 3}
|
||
actions:
|
||
- {type: alert, level: moderate}
|
||
reason_ru: "AUDIT-C = {total} (положительный скрининг, порог {threshold})"
|
||
|
||
# ---------------------------------------------------------------- medication adherence
|
||
- id: quit_intent
|
||
description: >
|
||
Patient says they want to stop the medication (extracted from free text), or skips the dose after having
|
||
expressed that intent within the window. Delayed SSRI effect (2–4 weeks) is the usual reason → explain,
|
||
advise not to stop without the doctor, notify the doctor.
|
||
params: {window_days: 7}
|
||
actions:
|
||
- {type: alert, level: high}
|
||
- {type: med_info, params: {topic: delayed_effect}}
|
||
reason_ru: "Намерение прекратить приём препарата"
|
||
|
||
- id: missed_doses_7d
|
||
description: >
|
||
>= 3 days with a missed/skipped dose in the last 7 days → check-in about the reasons, flag for the visit.
|
||
params: {threshold: 3, window_days: 7}
|
||
actions:
|
||
- {type: alert, level: moderate}
|
||
- {type: reach_out, params: {topic: missed_doses}}
|
||
reason_ru: "Пропуски приёма: {count} из {window_days} дней"
|
||
|
||
- id: side_effect_3d
|
||
description: >
|
||
Side-effect complaints on 3 consecutive days (e.g. SSRI nausea, persona day 4) → flag for the doctor.
|
||
params: {consecutive_days: 3}
|
||
actions:
|
||
- {type: alert, level: moderate}
|
||
reason_ru: "Побочные эффекты {consecutive_days} дня подряд: {effects}"
|
||
|
||
# ---------------------------------------------------------------- daily check-in patterns
|
||
- id: sleep_lt4_3n
|
||
description: Sleep < 4 h for 3 consecutive nights (F_Y6) → flag for the doctor.
|
||
params: {consecutive_days: 3}
|
||
actions:
|
||
- {type: alert, level: moderate}
|
||
reason_ru: "Сон < 4 ч {consecutive_days} ночи подряд"
|
||
|
||
- id: alcohol_3d
|
||
description: >
|
||
Alcohol on 3 consecutive days (F_Y5) → information about alcohol/antidepressant interaction,
|
||
flag for the doctor, suggest an earlier visit.
|
||
params: {consecutive_days: 3}
|
||
actions:
|
||
- {type: alert, level: moderate}
|
||
- {type: med_info, params: {topic: alcohol_interaction}}
|
||
- {type: suggest_visit, params: {reason: alcohol}}
|
||
reason_ru: "Алкоголь {consecutive_days} дня подряд"
|
||
|
||
- id: mood_low_3d
|
||
description: >
|
||
Mood <= 3 (0–10) on 3 consecutive days → unscheduled PHQ-9 (ADR-002). Not an alert by itself; skipped if
|
||
an unscheduled PHQ-9 was already taken within the cooldown.
|
||
params: {threshold: 3, consecutive_days: 3, cooldown_days: 7}
|
||
actions:
|
||
- {type: schedule_scale, params: {scale: phq9, scheduled: false}}
|
||
reason_ru: "Настроение ≤ {threshold} {consecutive_days} дня подряд → внеплановый PHQ-9"
|
||
|
||
- id: no_contact_3d
|
||
description: >
|
||
No message from the patient for > 3 days. Silence itself is a risk signal → grey flag, caring contact.
|
||
params: {days: 3}
|
||
actions:
|
||
- {type: alert, level: info}
|
||
- {type: reach_out, params: {topic: silence}}
|
||
reason_ru: "Нет ответа пациента {silent_days} дн."
|
||
|
||
- id: young_adult_start
|
||
description: >
|
||
Age < 25 in the first 4 weeks of antidepressant therapy: possible increase of suicidal thoughts (FDA
|
||
boxed warning) → enhanced monitoring (more frequent check-ins and C-SSRS).
|
||
params: {age_below: 25, max_therapy_day: 28}
|
||
actions:
|
||
- {type: enhanced_monitoring, level: info}
|
||
reason_ru: "Возраст < 25, первые 4 недели терапии: усиленный мониторинг"
|