каркас: домен, генерация типов фронта, стенд и карточки задач
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений, таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет их через JSON Schema в generated.ts, тест ловит забытую регенерацию. Стенд: docker compose postgres + backend, health отвечает, база досягаема из контейнера бэкенда. Makefile не врёт — нереализованные цели падают и называют карточку, которая их закроет. frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.
This commit is contained in:
parent
4425c7d4ca
commit
7b7dd38e9f
36 changed files with 4997 additions and 0 deletions
114
backend/app/domain/taxonomy.py
Normal file
114
backend/app/domain/taxonomy.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
"""Таксономия ошибок E1–E6 и компетенции.
|
||||
|
||||
Методика: docs/product/METHODOLOGY.md#таксономия-ошибок
|
||||
Правило: каждая отметка несёт код и обоснование. Отметок без объяснения
|
||||
не появляется ни в одном интерфейсе.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import StrEnum
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ErrorCode(StrEnum):
|
||||
E1 = "E1"
|
||||
E2 = "E2"
|
||||
E3 = "E3"
|
||||
E4 = "E4"
|
||||
E5 = "E5"
|
||||
E6 = "E6"
|
||||
|
||||
|
||||
class FindingSource(StrEnum):
|
||||
"""Кто выставил отметку. `judge` — единственный недетерминированный источник."""
|
||||
|
||||
SLOTS = "slots"
|
||||
GROUND_TRUTH = "ground_truth"
|
||||
TIMERS = "timers"
|
||||
KIO = "kio"
|
||||
CHAIN = "chain"
|
||||
JUDGE = "judge"
|
||||
INSTRUCTOR = "instructor"
|
||||
|
||||
|
||||
class ErrorSpec(BaseModel):
|
||||
code: ErrorCode
|
||||
title: str
|
||||
detail: str
|
||||
source: FindingSource
|
||||
|
||||
|
||||
ERRORS: dict[ErrorCode, ErrorSpec] = {
|
||||
ErrorCode.E1: ErrorSpec(
|
||||
code=ErrorCode.E1,
|
||||
title="Пропущенный факт",
|
||||
detail="Обязательный вопрос не прозвучал, факт не добыт",
|
||||
source=FindingSource.SLOTS,
|
||||
),
|
||||
ErrorCode.E2: ErrorSpec(
|
||||
code=ErrorCode.E2,
|
||||
title="Неверная классификация или маршрутизация",
|
||||
detail="Тип происшествия или ДДС определены неверно",
|
||||
source=FindingSource.GROUND_TRUTH,
|
||||
),
|
||||
ErrorCode.E3: ErrorSpec(
|
||||
code=ErrorCode.E3,
|
||||
title="Нарушение временного норматива",
|
||||
detail="Опрос дольше 75 с, ДДС не оповещена за 60 с и т. д.",
|
||||
source=FindingSource.TIMERS,
|
||||
),
|
||||
ErrorCode.E4: ErrorSpec(
|
||||
code=ErrorCode.E4,
|
||||
title="Коммуникативная ошибка",
|
||||
detail="Тон, эмпатия, управление диалогом, лишние вопросы, игнорирование паники",
|
||||
source=FindingSource.JUDGE,
|
||||
),
|
||||
ErrorCode.E5: ErrorSpec(
|
||||
code=ErrorCode.E5,
|
||||
title="Неполнота карточки",
|
||||
detail="Обязательные поля КИО пусты или заполнены неверно",
|
||||
source=FindingSource.KIO,
|
||||
),
|
||||
ErrorCode.E6: ErrorSpec(
|
||||
code=ErrorCode.E6,
|
||||
title="Неверное завершение",
|
||||
detail="Карточка ушла в ДДС непригодной, снятие с контроля до подтверждения",
|
||||
source=FindingSource.CHAIN,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class Competency(StrEnum):
|
||||
"""Шесть осей радара. Проекция уже посчитанных метрик, без пересчёта весов."""
|
||||
|
||||
INTAKE = "intake"
|
||||
INTERVIEW = "interview"
|
||||
CARD = "card"
|
||||
ROUTING = "routing"
|
||||
NORMS = "norms"
|
||||
COMMUNICATION = "communication"
|
||||
|
||||
|
||||
COMPETENCY_LABELS: dict[Competency, str] = {
|
||||
Competency.INTAKE: "Приём вызова",
|
||||
Competency.INTERVIEW: "Опрос и добыча фактов",
|
||||
Competency.CARD: "Заполнение КИО",
|
||||
Competency.ROUTING: "Классификация и маршрутизация",
|
||||
Competency.NORMS: "Соблюдение нормативов",
|
||||
Competency.COMMUNICATION: "Коммуникация в стрессе",
|
||||
}
|
||||
|
||||
|
||||
class Finding(BaseModel):
|
||||
"""Отметка в разборе. `fact` и `norm` — то самое обоснование."""
|
||||
|
||||
code: ErrorCode
|
||||
source: FindingSource
|
||||
summary: str
|
||||
fact: str
|
||||
norm: str | None = None
|
||||
ref: str | None = None
|
||||
competency: Competency | None = None
|
||||
transcript_ref: str | None = None
|
||||
at: datetime | None = None
|
||||
Loading…
Reference in a new issue