feat(web): two-stage questionnaires, screening result and diary by result

- Sign-in: centred ЕМИАС card without the sidebar; anonymous entry asks «Депрессия / ПТСР».
- Stage 1 is the same for everyone and follows the fixed order of the MVP questionnaire:
  PHQ-2 → trauma filter/TSQ → RUS-AUDIT-S → C-SSRS → context; stage 2 only where stage 1
  is positive. Starts without a profile.
- After stage 1 the patient sees a preliminary result (screening, not a diagnosis), stored
  with the record; it switches on the diary modules (depression / PTSD).
- Stage 2 diary: morning (sleep, sleep quality, alcohol) and evening (mood, medication,
  3 PHQ-9 items in rotation, short PCL-5); C-SSRS since last contact only under risk;
  flags on weekly means against the personal norm; scheduled full scales with change
  (remission, response, worsening).
- Questionnaire log: GET /me/{token}/results and the «Мои результаты» screen.
- Questionnaires centred without the sidebar and without scale names; «Продолжить позже»
  goes home; confirmations are toasts; free-text comments are optional.
- Demo policy config/questionnaire_demo.yaml (INTAKE_DEMO only, not a clinical approval).

ADR-012.

Refs #77

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 15:14:09 +03:00
co-authored by Claude Opus 5.5
parent 6e7c89900b
commit 290b0d6151
36 changed files with 1900 additions and 691 deletions
+73 -178
View File
@@ -1,189 +1,84 @@
version: diary-v2-2026-10-03
core:
- id: mood
text: 'Какое у Вас сегодня настроение?
# Stage 2 daily diary — «Этап 2: наблюдение после диагноза» (@Andrey, 2026-10-03), p.1–3.
# Every block comes from an instrument checked for frequent use; there are no own questions. No validated thresholds
# exist for daily data: the diary shows a trend and brings a full scale forward, routes come from full scales only.
# Modules follow the screening result of stage 1 (profile modules): depression → «depression», PTSD → «veteran».
version: diary-v3-2026-10-04
0 — самое плохое, 10 — самое хорошее.'
options:
- value: 0
label: '0'
- value: 1
label: '1'
- value: 2
label: '2'
- value: 3
label: '3'
- value: 4
label: '4'
- value: 5
label: '5'
- value: 6
label: '6'
- value: 7
label: '7'
- value: 8
label: '8'
- value: 9
label: '9'
- value: 10
label: '10'
# Core — everyone. Morning block after waking (the sleep diary is built for it), evening block at 20:00.
morning:
- id: sleep_hours
text: Сколько часов Вы спали прошлой ночью?
source: Consensus Sleep Diary
text: Сколько часов Вы спали этой ночью?
numeric: true
- id: rested
text: 'Насколько Вы выспались?
0 — совсем не выспались, 4 — полностью выспались.'
max: 24
- id: sleep_quality
source: Consensus Sleep Diary
text: Как Вы оцениваете качество своего сна?
options:
- value: 0
label: '0'
- value: 1
label: '1'
- value: 2
label: '2'
- value: 3
label: '3'
- value: 4
label: '4'
- {value: 0, label: Очень плохо}
- {value: 1, label: Плохо}
- {value: 2, label: Удовлетворительно}
- {value: 3, label: Хорошо}
- {value: 4, label: Очень хорошо}
- id: alcohol_portions
source: принцип Timeline Followback; порция по RUS-AUDIT
text: |-
Сколько стандартных порций алкоголя Вы выпили вчера?
Одна порция — 100 мл вина, 250 мл пива или 30 мл крепкого алкоголя. Если не пили — введите 0.
numeric: true
max: 50
evening:
- id: mood
source: ежедневная оценка настроения (недельные средние коррелируют с PHQ-9)
text: |-
Как Вы оцениваете своё настроение сегодня?
0 — самое плохое, 10 — самое хорошее.
options:
- {value: 0, label: '0'}
- {value: 1, label: '1'}
- {value: 2, label: '2'}
- {value: 3, label: '3'}
- {value: 4, label: '4'}
- {value: 5, label: '5'}
- {value: 6, label: '6'}
- {value: 7, label: '7'}
- {value: 8, label: '8'}
- {value: 9, label: '9'}
- {value: 10, label: '10'}
- id: medication
text: Приняли ли Вы сегодня лекарства по схеме?
source: КР ПТСР — дневник приёма лекарств
text: Приняли ли Вы сегодня лекарства, назначенные врачом?
options:
- value: full
label: По схеме
- value: partial
label: Частично
- value: none
label: Нет
- value: not_prescribed
label: Не назначены
- {value: 'yes', label: Да}
- {value: 'no', label: Нет}
- {value: not_prescribed, label: Лекарства не назначены}
- id: medication_reason
text: Почему не приняли лекарства по схеме?
source: КР ПТСР — дневник приёма лекарств
text: Почему не приняли?
options:
- value: forgot
label: Забыл(а)
- value: side_effects
label: Побочные эффекты
- value: declined
label: Не хочу
- value: ran_out
label: Закончились
- value: other
label: Другая причина
- id: side_effects
text: Беспокоили ли Вас сегодня побочные эффекты лекарств?
options: &id001
- value: 1
label: Да
- value: 0
label: Нет
- id: substances
text: Употребляли ли Вы сегодня алкоголь или другие вещества?
options: *id001
- id: comment
text: Что хотите передать врачу?
optional: true
ptsd:
- id: intrusions
text: 'Насколько за последние сутки Вас беспокоили: нежелательные воспоминания о событии?'
options: &id002
- value: 0
label: Совсем нет
- value: 1
label: Немного
- value: 2
label: Умеренно
- value: 3
label: Сильно
- value: 4
label: Крайне сильно
- id: nightmares
text: 'Насколько за последние сутки Вас беспокоили: кошмары прошлой ночью?'
options: *id002
- id: avoidance
text: 'Насколько за последние сутки Вас беспокоили: желание избегать мест, людей и мыслей, напоминающих о событии?'
options: *id002
- id: hypervigilance
text: 'Насколько за последние сутки Вас беспокоили: настороженность, вздрагивание, ощущение опасности?'
options: *id002
- id: irritability
text: 'Насколько за последние сутки Вас беспокоили: раздражительность или вспышки гнева?'
options: *id002
- {value: forgot, label: Забыл(а)}
- {value: side_effects, label: Побочные эффекты}
- {value: declined, label: Решил(а) не принимать}
- {value: ran_out, label: Закончились}
# Depression module: PHQ-9 items with the official Russian text (config/instruments/intake_forms.yaml), answer
# options adapted to one day. Three items a day in rotation: day 1 — items 1–3, day 2 — 4–6, day 3 — 7–9.
# Item 9 ≥1 → stop and the crisis protocol (stage 1 rule).
depression:
- id: interest
text: 'Насколько Вам сегодня было интересно и приятно что-то делать?
0 — совсем нет, 4 — крайне сильно.'
options: *id002
- id: depressed
text: Насколько Вы сегодня чувствовали подавленность или безнадёжность?
options: *id002
- id: energy
text: 'Насколько у Вас сегодня были силы и энергия?
0 — совсем нет, 4 — крайне сильно.'
options: *id002
- id: planned_activity
text: Сделали ли Вы сегодня хотя бы одно запланированное дело?
options: *id001
suicide:
- id: death_thoughts
text: Были ли у Вас сегодня мысли о смерти или о том, что не хочется жить?
options: *id001
- id: thoughts_intensity
text: 'Если да — насколько сильными они были?
0 — совсем слабые, 10 — максимально сильные.'
form: phq9
items_per_day: 3
question: 'Насколько сегодня Вас беспокоило:'
options:
- value: 0
label: '0'
- value: 1
label: '1'
- value: 2
label: '2'
- value: 3
label: '3'
- value: 4
label: '4'
- value: 5
label: '5'
- value: 6
label: '6'
- value: 7
label: '7'
- value: 8
label: '8'
- value: 9
label: '9'
- value: 10
label: '10'
- id: hope
text: 'Насколько Вы верите, что станет лучше?
- {value: 0, label: Совсем нет}
- {value: 1, label: Немного}
- {value: 2, label: Умеренно}
- {value: 3, label: Сильно}
0 — совсем не верю, 10 — полностью верю.'
options:
- value: 0
label: '0'
- value: 1
label: '1'
- value: 2
label: '2'
- value: 3
label: '3'
- value: 4
label: '4'
- value: 5
label: '5'
- value: 6
label: '6'
- value: 7
label: '7'
- value: 8
label: '8'
- value: 9
label: '9'
- value: 10
label: '10'
- id: burden
text: Чувствовали ли Вы себя обузой для близких?
options: *id001
weekly: true
# PTSD module: short 4-item PCL-5 (Price et al., 2016), one item per cluster B, C, D, E; «today» instead of «the
# past month», options 0–4 of PCL-5. Item numbers must still be checked against the article (PDF p.7, «Медику»).
ptsd:
form: pcl5
items: [pcl5_1, pcl5_7, pcl5_10, pcl5_18]
question: 'Насколько сильно сегодня Вас беспокоили:'
+17 -7
View File
@@ -1,17 +1,27 @@
version: intake-v2-2026-10-03
version: intake-v3-2026-10-04
enabled: false
approval: null
# Release decisions cover texts, diary anchors/thresholds, schedules and contact readiness.
content_review: null
contact_review: null
timezone: Europe/Moscow
daily_hour: 19
mood_baseline_days: 7
mood_bad_days: 3
mood_drop: 3
sleep_bad_days: 3
# Stage 2 diary («Этап 2: наблюдение после диагноза»): morning block after waking, evening block at 20:00.
morning_hour: 8
evening_hour: 20
# Personal norm = the first `norm_days` of observation; compared with the mean of the last `week_days`.
# Flag numbers are the team's candidates (PDF «Этап 2», p.4) — agree with the doctor.
norm_days: 14
week_days: 7
min_norm_values: 7
min_week_values: 4
mood_drop: 3 # weekly mood mean fell ≥3 below the norm → unscheduled PHQ-9
depression_item_rise: 1.0 # weekly mean of a PHQ-9 diary item rose ≥1 above its norm → PHQ-9 earlier
ptsd_sum_rise: 3.0 # weekly mean of the 4-item PCL-5 sum rose ≥3 above the norm → PCL-5 earlier
sleep_bad_days: 3 # <4 h or «очень плохо» three nights in a row → flag to the doctor
sleep_hours_below: 4
nightmares_at: 3
alcohol_heavy_portions: 6 # ≥6 standard drinks a day = heavy day (volumes of RUS-AUDIT item 3)
alcohol_heavy_days: 2 # heavy days in a week → full RUS-AUDIT
adherence_below: 0.8 # share of days with medication taken over a week
missed_medication_days: 3
high_risk_silence_days: 2
medication_days: [7, 14, 28]
+21
View File
@@ -0,0 +1,21 @@
# DEMO ONLY (INTAKE_DEMO=1 + demo clock, synthetic data). NOT a clinical approval: the real policy is
# config/questionnaire.yaml and stays closed until the doctor's decisions C01–C09 (docs/clinical/README.md).
# Values follow the MVP PDF so the demo can reach a result and stage 2:
# C01 → graded: low C-SSRS risk shows the safety plan and continues (PDF p.11, routing table);
# C02 → full RUS-AUDIT from zone II of RUS-AUDIT-S (WHO zones, Bunova 2022).
version: mvp-v2-demo-2026-10-04
approval:
reviewer: "DEMO — синтетические данные, не клиническое согласование"
decision_reference: "INTAKE_DEMO"
approved_at: "2026-10-04T00:00:00+03:00"
policy_version: mvp-v2-demo-2026-10-04
cssrs_positive_policy: graded
rus_audit_s_expand_from_zone: 2
phq2_expand_at: 2
tsq_expand_at: 6
phq9_psychologist_at: 5
phq9_specialist_at: 10
phq9_priority_at: 20
pcl5_specialist_at: 31
pcl5_priority_at: 50
pcl5_behavior_flag_at: 3
+4
View File
@@ -14,7 +14,11 @@ sex: "Укажите пол для интерпретации алкогольн
tbi: "Были ли у Вас контузия или черепно-мозговая травма?"
psychotropics: "Принимаете ли Вы сейчас психотропные препараты?"
missing_followup: "Для оценки изменений со времени прошлого контакта нужна консультация специалиста. Если Вам нужна помощь сейчас, нажмите кнопку ниже."
side_effects: "Беспокоили ли Вас за последнее время побочные эффекты лекарств?"
numeric_portions: "Введите число стандартных порций, например 0 или 2."
diary_done: "Дневник на сегодня уже заполнен. Спасибо!"
periods:
since_last_contact: "С момента Вашего последнего ответа на эти вопросы."
past_month: "За последний месяц."
lifetime: "За всю жизнь."
past_3_months: "За последние три месяца."
+120
View File
@@ -0,0 +1,120 @@
# Patient-facing interpretation of questionnaire results (ADR-008: texts in config). The rules that pick a text are
# deterministic (app/core/interpretation.py) and use the thresholds of config/questionnaire*.yaml, PDF «Опросники для
# MVP» (stage 1) and «Этап 2» (follow-up). The app never diagnoses: every result is a screening result.
disclaimer: "Это результат скрининга, а не диагноз. Диагноз ставит врач после очной консультации."
intake:
ok:
title: "Признаков депрессии и ПТСР не выявлено"
text: "По Вашим ответам сейчас нет признаков, которые требуют обращения к специалисту. Можно спать спокойно: продолжайте короткий дневник — так Вы заметите изменения раньше."
attention:
title: "Есть признаки, которые стоит обсудить со специалистом"
text: "Это не диагноз, но ответы похожи на те, что бывают при состояниях ниже. Ниже — что именно мы заметили и что делать дальше."
findings:
depression_suspected:
title: "Предположение депрессии"
text: "Ответы указывают на выраженные симптомы депрессии за последние 2 недели. Включаем модуль «Депрессия» в ежедневном дневнике."
depression_mild:
title: "Лёгкие симптомы депрессии"
text: "Есть отдельные симптомы сниженного настроения. Они часто проходят сами, но за ними стоит последить."
ptsd_suspected:
title: "Склонность к ПТСР"
text: "Ответы указывают на выраженные последствия пережитого травматического события за последний месяц. Включаем модуль «ПТСР» в ежедневном дневнике."
ptsd_signs:
title: "Отдельные признаки посттравматического стресса"
text: "После травматического события есть отдельные реакции, но их выраженность ниже порога вероятного ПТСР."
alcohol_risky:
title: "Рискованное употребление алкоголя"
text: "Употребление алкоголя выше безопасного уровня. Стоит сократить его и обсудить это с врачом."
alcohol_high:
title: "Высокий риск зависимости от алкоголя"
text: "Рекомендуем консультацию нарколога — параллельно с основным маршрутом."
suicide_low:
title: "Тяжёлые мысли"
text: "Вы отметили мысли о смерти. Мы добавили план безопасности и будем каждый день коротко спрашивать о самочувствии. Если станет тяжело — звоните 112 или на телефон доверия."
tbi:
title: "Контузия или ЧМТ"
text: "Рекомендуем консультацию невролога."
routes:
urgent_psychiatrist: "Срочно свяжитесь с психиатром — сегодня или завтра."
priority_psychiatrist: "Рекомендуем приоритетную запись к психиатру в ближайшие дни."
psychiatrist_or_psychotherapist: "Рекомендуем плановую запись к психиатру или психотерапевту."
psychologist: "Рекомендуем консультацию психолога."
self_help: "Достаточно самопомощи и короткого ежедневного дневника."
modules:
title: "Что дальше"
diary: "Каждый день — короткий дневник: 3 вопроса утром и 2 вечером{modules}. Полные опросники — по расписанию."
names:
depression: "«Депрессия»"
veteran: "«ПТСР»"
with: ", плюс модуль {names}"
scales:
phq9:
title: "Опросник PHQ-9 (депрессия)"
levels:
minimal: "минимальные симптомы"
mild: "лёгкие симптомы"
moderate: "умеренные симптомы"
moderately_severe: "умеренно тяжёлые симптомы"
severe: "тяжёлые симптомы"
pcl5:
title: "Опросник PCL-5 (ПТСР)"
levels:
below: "ниже порога вероятного ПТСР"
probable: "выше порога вероятного ПТСР"
rus_audit_s:
title: "Опросник RUS-AUDIT-S (алкоголь)"
levels:
zone_1: "относительно низкий риск"
zone_2: "опасное употребление"
zone_3: "пагубное употребление"
zone_4: "риск зависимости"
unknown: "нельзя оценить без указания пола"
score: "{title}: {total} — {level}."
change:
remission: "Это ремиссия по шкале — отличный результат."
response: "По сравнению с началом наблюдения — ответ на лечение."
improved: "По сравнению с началом наблюдения — клинически значимое улучшение."
stable: "По сравнению с началом наблюдения существенных изменений нет."
worse: "По сравнению с прошлым замером состояние ухудшилось. Врач получит сигнал и пересмотрит план."
diary:
saved: "Спасибо, дневник за {part} сохранён."
parts:
morning: "утро"
evening: "вечер"
flags:
phq9_due_mood: "Настроение за неделю заметно ниже Вашей обычной нормы — предложим полный опросник PHQ-9 раньше срока."
phq9_due_depression: "Симптомы депрессии за неделю выше Вашей нормы — предложим полный опросник PHQ-9 раньше срока."
pcl5_due_ptsd: "Симптомы ПТСР за неделю выше Вашей нормы — предложим полный опросник PCL-5 раньше срока."
sleep_review: "Несколько ночей подряд очень плохой или короткий сон. Врач увидит это в сводке."
alcohol_on_medication: "Много алкоголя при приёме лекарств опасно. Врач получит отметку."
rus_audit_due_alcohol: "За неделю было несколько дней с большим количеством алкоголя — предложим опросник об алкоголе."
medication_contact: "Несколько дней подряд без лекарств. Не прекращайте приём без врача — мы сообщим ему."
adherence_review: "За неделю лекарства пропущены чаще, чем в 1 из 5 дней. Обсудите это с врачом."
side_effects_review: "Вы отметили побочные эффекты — врач получит отметку."
cssrs:
none: "Спасибо за ответы."
low: "Спасибо, что ответили честно. Откройте план безопасности, если станет тяжело."
kinds:
intake: "Первичный опрос"
diary_morning: "Дневник — утро"
diary_evening: "Дневник — вечер"
cssrs_since_contact: "Вопросы о безопасности"
phq9: "PHQ-9 по расписанию"
pcl5: "PCL-5 по расписанию"
rus_audit_s: "Алкоголь по расписанию"
diary: "Дневник"
status:
complete: "пройден"
review_required: "остановлен для оценки специалиста"
interrupted: "прерван: открыта экстренная помощь"
active: "в процессе"
paused: "на паузе"
cancelled: "отменён"