Получены первичные данные, названные в ТЗ: памятка по АРМ-112, классификатор
происшествий на 1283 кода и 32 экзаменационных билета. Файлы в docs/spec/source/
под гитом: документ, на который ссылается норматив, должен приезжать вместе с кодом.
Что изменилось по существу:
- Норматив подтверждения карточки был 4 секунды со ссылкой на ГОСТ, где этого числа
нет. Памятка и ТЗ независимо называют 30 секунд — исправлено в domain/timers.py
с правильной ссылкой (ПП РФ № 1931), в контракте и в generated.ts.
- Оператор в боевом АРМ-112 службу не выбирает: он проставляет признаки, а список
оповещения из 5–11 служб считается по ЕКП. Наше поле dds моделирует не ту работу.
- Сторона ДДС описана памяткой подробнее, чем реализована: девять статусов
реагирования автоматом, семь статусов карточки, обязательные комментарии
к отказам и таксономия ошибок с примерами.
- 96 учебных вызовов из билетов расшифрованы слово в слово в docs/spec/TICKETS.md;
сложность в них делается адресом и профильностью, а не сюжетом.
Документы: DATASET.md, TICKETS.md, правки NORMATIVES.md (НПА, ЕКП, статусы),
GAP.md (пункты 13–15), TZ.md (предположение «датасета не будет» не подтвердилось).
Карточки: новые 32–36 (классификатор, статусы реагирования, билеты, уточнение
адреса, непрофильные вызовы); в девятнадцати существующих — раздел «Датасет»
с расхождениями, включая выполненные: lct-01 моделирует не ту карточку КИО,
lct-12 сравнивает адрес так, что уточнивший его курсант получает расхождение
с эталоном, lct-10 не содержит трёх блоков боевого АРМ.
Эталонный диалог собирается кодом из фактов и чек-листа: написанный
руками, он разошёлся бы с фактами при первой же правке сценария,
и курсанта оштрафовали бы за правильный ответ.
Отчёт: метрики фактом против норматива со ссылкой, отметка E1 на каждый
недобытый факт с эталонным вопросом, расхождение самооценки — что
курсант заметил сам, чего не заметил, что отметил зря. Не заметил —
самое ценное для разбора.
Внешний монитор — не отдельное приложение, а другой режим отрисовки тех
же событий: крупный таймер опроса, ход разговора, карточка, после оценки
разбор на весь экран.
Коррекция преподавателем сохраняет автооценку рядом: видно, что
скорректировано и кем.
Найдено: все метрики весили одинаково, и курсант, не задавший ни одного
вопроса, но заполнивший карточку руками, получал 87 из 100. Предварительные
веса (полнота опроса — 4) дают 74; окончательные утверждает методист,
вопрос записан в DEBRIEF.md.
Каждая метрика — факт против норматива со ссылкой: «94 с при ≤ 75 с,
ГОСТ Р 22.7.03-2021», а не балл. По недобытому факту — отдельная отметка
E1 с эталонным вопросом: в разборе нужен конкретный вопрос, не процент.
Радар — проекция тех же метрик без пересчёта весов, коммуникация без
судьи не рисуется нулём.
Таймер, не остановленный событием, — провал, а не зачёт: время
недоказуемо, операция не завершена. Метрика, которую нечем посчитать
(полнота опроса без модели эмбеддингов), видна как «не посчитано» —
молча выброшенная выглядела бы пройденной.
Найдено противоречие: таймеры опроса (75 с) и оповещения ДДС (60 с)
стартовали на ответе и останавливались передачей в ДДС — один отрезок,
два лимита. Опрос за законные 70 с давал E3, а на экране курсанта
краснел таймер посреди нормального разговора. События «опрос закончен»
в контракте нет, поэтому dds_notify снят с учёта, вопрос записан в
CONTRACT.md.
KIO проверяет присваивание: card.dds = "03" клало в карточку сырую
строку вместо кода ДДС, и падала уже оценка, далеко от места ошибки.
Координаты были представлены дважды: кортежем в КИО и объектом в данных
ЭРА-ГЛОНАСС. Теперь Coords {lat, lon} везде — в кортеже не видно, где
широта, и ошибка всплывает на карте у диспетчера, а не в типах.
required_fields едет в call.incoming и session.snapshot: обязательность
полей задаёт сценарий, без списка АРМ не подсветит незаполненное поле,
и курсант узнаёт о неполноте карточки только из разбора.
Канал error получил коды (ErrorKind, восемь значений) — фронт разбирает
код, а не текст сообщения. Имя не ErrorCode: оно занято таксономией E1–E6,
два одинаковых имени дали бы коллизию в generated.ts.
Добавлены поля, которые спрашивает чек-лист, а записать было некуда:
куда идёт дым, уехал ли нарушитель, код домофона.
Документы догнали код: mkh → gkh, payload transcript.append с якорем ref,
причина director у tts.cancel, attempt и stopped у таймеров.
Контракт в коде: КИО по нормативу, 43 события WS по шести союзам направлений,
таймеры ГОСТ, таксономия E1–E6, шесть компетенций радара. make types гоняет
их через JSON Schema в generated.ts, тест ловит забытую регенерацию.
Стенд: docker compose postgres + backend, health отвечает, база досягаема
из контейнера бэкенда. Makefile не врёт — нереализованные цели падают
и называют карточку, которая их закроет.
frontend/.npmrc: под WSL2 npm install зависает на дефолтных 15 сокетах.