feat: crisis message after the test and non-blocking; weapon answer triggers nothing; ЕМИАС demo = Никита
CI / ruff · pytest (pull_request) Successful in 2m33s

- CRISIS_BLOCKING (default off for the demo): a crisis no longer locks the dialog; the message and the
  doctor's acute alert still happen. The clinical protocol (blocking, immediate stop) stays behind the flag and
  keeps its tests.
- Crisis signals inside a questionnaire (intake red flags, high C-SSRS, PHQ-9 item 9) no longer stop it: the
  test is finished and the crisis message comes at the end; the doctor's alert is raised at once/at the end.
- Weapon access: asked and stored, triggers nothing (rule disabled, no red flag, no safety block).
- ЕМИАС demo persona is «Никита В.»; the one-click demo stays «Андрей С.».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 23:30:05 +03:00
co-authored by Claude Opus 5.5
parent 967ae2d5b6
commit 531bef1e73
16 changed files with 142 additions and 16 deletions
+2 -1
View File
@@ -25,7 +25,8 @@ DOCTOR_ID = "doc-smirnova"
# Synthetic personas for the demo console and the demo ЕМИАС sign-in of the patient web app.
DEMO_PERSONAS: list[DemoPersona] = [
DemoPersona(token="tok-andrey", display_name="Андрей С.", therapy_day=13, scenario="data/synthetic/andrey.jsonl"),
# ЕМИАС demo sign-in shows this persona as «Никита В.» (the one-click demo on the welcome screen is «Андрей С.»).
DemoPersona(token="tok-andrey", display_name="Никита В.", therapy_day=13, scenario="data/synthetic/andrey.jsonl"),
]
+4 -2
View File
@@ -158,6 +158,7 @@ async def auth_emias_demo(body: EmiasDemoIn) -> AuthOut:
DEMO_SOURCE = "tok-andrey"
ONE_CLICK_NAME = "Андрей С." # «Демо: войти как Андрей»; the ЕМИАС demo persona is named in fixtures (Никита)
@router.post("/auth/demo/fresh", response_model=AuthOut)
@@ -172,12 +173,13 @@ async def _fresh_demo_copy(*, start_in_chat: bool) -> AuthOut:
token = f"{DEMO_SOURCE}-{secrets.token_hex(4)}"
now = clock.now()
persona = next(p for p in fixtures.DEMO_PERSONAS if p.token == DEMO_SOURCE)
name = persona.display_name if not start_in_chat else ONE_CLICK_NAME
snils = f"000-{secrets.randbelow(10**3):03d}-{secrets.randbelow(10**3):03d} {secrets.randbelow(100):02d}"
async with get_identity_session() as s:
await identity_repo.create_patient(
s,
token=token,
display_name=f"{persona.display_name} (демо)",
display_name=f"{name} (демо)",
snils=snils,
clinic_id="demo",
doctor_id=fixtures.DOCTOR_ID,
@@ -194,7 +196,7 @@ async def _fresh_demo_copy(*, start_in_chat: bool) -> AuthOut:
consent = {"consent": True, "consent_ver": "demo", "consent_at": now.isoformat(), "revoked_at": None}
await repo.set_dialog_state(s, token=token, state="idle", data={**consent, "adult": True}, now=now)
log.info("web auth: demo fresh tok=%s", token[:14])
return AuthOut(token=token, mode="emias", display_name=persona.display_name)
return AuthOut(token=token, mode="emias", display_name=name)
@router.post("/auth/anonymous", response_model=AuthOut)