Files
agents/docs/agent/COMPLETED_TASKS.md
T
2026-10-17 15:04:28 +07:00

371 lines
126 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Завершённые задачи
Архив задач, переведённых в статус `DONE`.
### ED-046 — Подсказка игроку о локальной сети
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Цель: на странице игрока показывать «Подключитесь к Wi-Fi организатора и обновите страницу.» при открытии онлайн-сервера для игры с готовым офлайн-пакетом.
- Критерии: подсказка сверху независимо от статуса игры; скрыта на локальном сервере, при отсутствии пакета или его подготовке; обновляется существующим поллингом.
- Ограничения: без изменений API, бэкенда и автоматического переключения сервера.
- Проверка: `npm run type-check`, `npm run lint`, `npm run lint:css`; ревью diff по стандарту фронтенда.
- Результат: добавлен информационный n-alert над содержимым страницы игрока; используются существующие uiStore и данные игры. API и бэкенд не менялись.
- Проверено: `npm run type-check`, `npm run lint`, `npm run lint:css`, `git diff --check` — успешно; diff проверен по стандарту фронтенда. Условие показа и обновление существующим поллингом проверены по коду.
- Не проверено: браузерный сценарий на живой офлайн-площадке. Commit/push не выполнялись.
### ED-040 — Дипломы призёров в печатном комплекте
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: добавить три красивых универсальных пустых диплома за 1–3 места.
- Решение: вертикальный A4, существующая состаренная бумага, двойная коричневая рамка с угловыми украшениями, логотип в медальоне, машинописный «ДИПЛОМ», поле команды, красно-коричневый штамп с римским местом и поля даты/подписи; `Для ведущего/Дипломы/` в ZIP.
- Критерии: три отдельных одностраничных PDF, верные места, пустые поля, без названий сценария и игры и без номеров страниц; дипломы доступны до игры и без команд.
- Ограничения: существующие ассеты, шрифт и PDF-библиотека; без новых зависимостей, API, автозаполнения, дипломов участников и commit/push.
- Проверка: `go test ./...`, `git diff --check`, ревью Go-стандарта; тесты архива, места, кириллицы, формата A4 и пустых полей; визуальная проверка всех трёх дипломов.
- Результат: три универсальных диплома добавляются в `Для ведущего/Дипломы/` каждого печатного ZIP, даже без команд; фон, логотип и машинописный шрифт переиспользованы, новые зависимости не добавлены.
- Проверено: `go test ./...` и `git diff --check` прошли; тесты проверяют три файла в архиве, отсутствие названий игры/сценария, места, кириллицу, один вертикальный A4, исходные ассеты и шрифт. Все три PDF визуально проверены; Go-стандарт соблюдён.
- Ограничения: физическая печать и браузер не проверялись; бумажная текстура увеличивает расход краски. Примеры сохранены только в `/tmp/ed040-diploma-{1,2,3}.pdf`; временный генератор удалён. Commit/push не выполнялись.
### ED-039 — Черновики без сценария и лист выдачи улик
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: убрать название сценария из обоих черновиков, исключить развязку из печатного комплекта, очистить подписи улик как у игроков и растянуть таблицу на доступную ширину страницы.
- Результат: генератор черновиков получает только заголовок и не выводит сценарий. Документ ведущего переименован в «Ответы.pdf», генератор принимает только вопросы и сохраняет правильные ответы без доступа к развязке. В `issuancePDF` подписи очищаются существующим `ClearText(clue.Name)`; исходные названия не изменяются. Столбец команды остаётся 51 мм, остальные столбцы равномерно занимают всю ширину альбомного A4 между полями 15 мм, включая последнюю неполную группу.
- Ограничения: исходные файлы улик, сценарий в БД, интерфейс ведущего и API не менялись; зависимости не добавлены; commit/push не выполнялись; существовавшее изменение backend-бинарника не затронуто.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно; весь изменённый код и тесты проверены по Go-стандарту. Тест полного архива проверяет отсутствие развязки во всех генерируемых PDF, наличие правильных ответов и отсутствие сценария в обоих черновиках. Геометрия готового PDF проверяет полную ширину каждого листа при 0/1/8/9/17 уликах; тест подписей проверяет очистку `([код])` и сохранность оригинального названия.
- Дополнительная проверка: визуально проверены черновик, документ ответов, таблица на три улики и последняя страница таблицы на 17 улик; чистые подписи и полная ширина подтверждены. Примеры находятся только в `/tmp/ed039-print-preview`. На вопрос пользователя указано точное место очистки — `internal/services/game_print_service/pdf.go:251`.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции; существующее ограничение исходного шрифта из ED-034 сохраняется.
### ED-038 — Крупнее название сценария, без номеров страниц
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: увеличить название сценария в шапке до 18 пунктов, сохранив одну строку; убрать номера страниц во всех генерируемых PDF комплекта.
- Результат: базовый размер подписи увеличен с 14 до 18 пунктов, длинные названия уменьшаются по доступной ширине без обрезки. Общий footer с нумерацией полностью удалён; PDF игрока и ведущего создаются без номеров страниц. Генератор QR нумерацию и раньше не добавлял.
- Ограничения: поля, одностраничность правил и вопросов, API и состав ZIP сохраняются; исходные улики не менялись; зависимости не добавлены; commit/push не выполнялись; существовавшее изменение backend-бинарника не затронуто.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно; изменённый код и тесты проверены по Go-стандарту. Тест подписи обновлён на 18 пунктов, добавлен тест отсутствия номеров на двух страницах PDF игрока и ведущего; существующие проверки длинных названий, правил и вопросов прошли.
- Дополнительная проверка: многостраничное введение визуально проверено; извлечённый текст всех страниц не содержит нумерации. Координаты короткого и длинного названия проверены: подпись ниже «Вечерний детектив», в одну строку, без пересечения. Примеры находятся только в `/tmp/ed038-intro.pdf` и `/tmp/ed038-long-title.pdf`.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции. Длинные подписи по-прежнему уменьшаются для размещения в одной строке; ограничение исходного шрифта из ED-034 сохраняется.
### ED-037 — Крупная подпись сценария и правила на одном листе
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: увеличить название сценария в шапке, сохранить одну строку; оба варианта правил размещать на одном A4; добавить отступ над полем команды.
- Результат: подпись сценария увеличена с 10 до 14 пунктов; длинные названия уменьшаются по доступной ширине без обрезки. Перед «Команда:» в вопросах и обоих черновиках добавлены 3 мм, дополнительный отступ учитывается при подгонке вопросов. Правила печатаются на одном A4 с полным текстом и разделами; размер текста, заголовков, межстрочных интервалов и отступов подбирается по доступной высоте. Подбор размера шрифта переиспользован для правил и вопросов.
- Ограничения: правила остаются без названия сценария; API и состав ZIP не менялись; зависимости не добавлены; commit/push не выполнялись; существовавшее изменение backend-бинарника не затронуто.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно; весь diff проверен по Go-стандарту. Тесты проверяют очные/онлайн/длинные/пустые правила на одну страницу, сохранность полного текста и разделов, ошибку неподдерживаемого текста, подпись до 14 пунктов. Существующие тесты длинных названий, геометрии вопросов и состава архива прошли.
- Дополнительная проверка: визуально проверены оба варианта правил, вопросы и черновик; координаты извлечённого текста проверены для правил, вопросов и обоих черновиков — одна страница, текст внутри полей, поле команды ниже заголовка. PDF-примеры находятся только в `/tmp/ed037-print-preview`.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции. Длинные названия и объёмные тексты уменьшаются для сохранения одной строки/страницы; ограничение исходного шрифта из ED-034 сохраняется.
### ED-036 — Правила без названия сценария
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: убрать название сценария со всех страниц PDF правил, сохранив логотип и «Вечерний детектив».
- Результат: генератор правил больше не принимает название сценария и создаёт фирменную шапку с пустой подписью. Обновлены caller сборки архива и тест ассетов; тест полного архива проверяет отсутствие названия сценария в правилах и сохранение его в остальных документах.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно; изменённый код проверен по Go-стандарту. Правила визуально проверены после рендера, пример сохранён только в `/tmp/ed036-rules.pdf`.
- Ограничения: остальные документы, API и состав ZIP не менялись; commit/push не выполнялись; существовавшее изменение backend-бинарника не затронуто.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции.
### ED-035 — Название сценария в шапке и вопросы на одном листе
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: название сценария второй строкой рядом с логотипом под «Вечерний детектив»; название игры не подставляется в генерируемые PDF; вопросы всегда на одном листе A4.
- Результат: генераторы получают `scenario.Name`; на правилах, введении и обоих черновиках название повторяется только в шапке, длинная подпись уменьшается без обрезки. В документах ведущего название игры заменено названием сценария. На бланке вопросов сохранены нумерация, поле команды и четыре строки ответа после каждого вопроса; шрифт до 11 пунктов подбирается по фактической высоте перенесённых строк, интервалы и поля ответа уменьшаются пропорционально. Автоматические переносы на второй лист отключены.
- Ограничения: API, состав ZIP и исходные улики не менялись; зависимости не добавлены; нижнего ограничения размера шрифта нет по выбору пользователя, поэтому большой объём может стать очень мелким. Существующее ограничение исходного машинописного шрифта описано в ED-034 и не менялось. Commit/push не выполнялись.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно. После уточнения теста геометрии повторно успешно проверен пакет `game_print_service`. Ревью изменённого кода и тестов по Go-стандарту выполнено.
- Дополнительная проверка: разные названия игры и сценария, в том числе название игры с эмодзи; название игры отсутствует в извлечённом тексте всех генерируемых PDF, название сценария встречается один раз на страницу документов игрока. Длинная подпись сохраняется и повторяется в шапке; многостраничное введение сохраняет текст. Пустой список, 3/40/200 вопросов, длинные абзацы и явные переносы проверены на одну страницу; геометрия готового PDF проверяет четыре линии ответа на вопрос и нижнее поле. Бланки на 8 и 40 вопросов и вторую страницу введения проверены визуально; `pdfinfo` подтверждает один лист A4, `pdftotext` — сохранность текста.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции. Примеры PDF сохранены только в `/tmp/ed035-print-preview`; существовавшее изменение backend-бинарника не затронуто.
### ED-034 — Фирменное оформление PDF игрока
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Цель: оформить правила, введение, вопросы и оба черновика машинописным шрифтом фронтенда и предоставленным логотипом.
- Решение: белая бумага A4, поля 15 мм, шапка с цветным логотипом шириной 18 мм и сохранением пропорций, названием «Вечерний детектив» и разделителем на каждой странице; шрифт `a_OldTyper.ttf` в заголовках, тексте и нумерации.
- Результат: точные копии шрифта и логотипа встроены через `go:embed`; для пяти документов игрока добавлено фирменное оформление, верхняя граница текста перенесена на 43 мм под шапку. Общие функции заголовка и нумерации сохраняют выбранный шрифт. Кириллица, содержание и поля ответов сохраняются на новых страницах.
- Ограничения: API, состав ZIP, оригиналы улик и оформление документов ведущего не менялись; новые зависимости не добавлены; commit/push не выполнялись. Исходный файл логотипа во фронтенде не изменён.
- Проверка: `gofmt`, `go test ./...`, `git diff --check` — успешно; полный прогон тестов выполнен с разрешённым доступом к системному кэшу после ошибки read-only в песочнице. Ревью всего diff по Go-стандарту выполнено, нарушений в изменённом коде не осталось.
- Дополнительная проверка: тесты встроенного шрифта и оригинального JPEG, повторения логотипа на страницах и отступа текста, сохранения стиля ведущего, длинного введения и вопросов; `pdftotext` проверяет сохранность текста и повторение шапки. Все пять документов визуально проверены, включая вторые страницы правил и вопросов. Копии ассетов сверены с исходниками через `cmp`; PDF-примеры находятся только в `/tmp/ed034-print-preview`.
- Известное ограничение: исходный `a_OldTyper.ttf` содержит `OS/2 fsType=0x0002`; библиотека PDF выводит предупреждение `ERROR - copyright restrictions.` при встраивании. Шрифт и его флаги не изменялись, предупреждение не подавлялось; PDF создаётся и отображается. Пользователь уведомлён об этом в процессе работы.
- Не проверено: физическая печать, браузер на живом сервере и PostgreSQL-интеграции; фронтенд-проверки не запускались, его код не менялся.
### ED-033 — Скачать материалы игры для печати
- Статус: `DONE`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Цель: кнопка в настройках игры скачивает ZIP с двумя папками «Для игрока» и «Для ведущего».
- Решение: игроку — правила по формату игры, введение, вопросы с полями ответа, оригиналы улик и два черновика («Список пидарасов», «Черновик расследования»); ведущему — ответы и развязка, QR активных команд, пустая таблица выдачи улик и список внешних материалов для ручного скачивания.
- Критерии: кириллица и A4; таблица разбивается по строкам и столбцам с повторением подписей; отменённые команды исключены; без команд QR пропускается и остаются пустые строки таблицы; оригиналы улик сохраняются и не дублируются; доступ проверяется сервером; приватный архив не кэшируется.
- Ограничения: без карты и описаний точек, новых зависимостей и миграций; используются существующие правила, PDF, QR, шрифт, хранилище и бинарный клиент; commit/push не выполнялись.
- Результат: добавлен RPC `DownloadGamePrintMaterials` / GET `/api/games/{ID}/print-materials`, подключён сервис сборки и кнопка с загрузкой и обработкой ошибок. Общий генератор QR использует тот же список активных команд, что таблица выдачи. Оригиналы PDF, изображений и аудио сохраняются без преобразования. Ошибки файлов, отмена и лимит комплекта 256 МБ обрабатываются; неподдерживаемые шрифтом символы возвращают явную ошибку вместо повреждённого PDF.
- Проверка: `make generate` и `npm run proto:gen`; `go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`, `git diff --check` — успешно. Финальный прогон Go-тестов выполнен с разрешённым доступом к системному кэшу после ошибки read-only в песочнице. Ревью всего diff по Go- и frontend-стандартам выполнено, нарушений в изменённых участках не осталось.
- Дополнительная проверка: тесты состава и двух папок ZIP, сохранности оригиналов, дедупликации, отсутствия секретов в папке игрока, формата правил, пустого списка и отменённых команд, доступа ролей, заголовков скачивания, ошибок, отмены и превышения размера. Текст PDF проверен через `pdftotext`; правила, вопросы и таблица на 40 команд / 17 улик визуально проверены после рендера.
- Не проверено: браузерный flow на живом сервере, физическая печать и интеграционные тесты PostgreSQL (`TEST_DATABASE_URL` не задан). Тестовые PDF сохранены только в `/tmp`, изменения сборочных артефактов фронтенда убраны из diff; существовавшее изменение backend-бинарника не затронуто.
### ED-032 — Название команды перед стартом игры в интерфейсе игрока
- Статус: `DONE`
- Приоритет: `P2`
- Репозитории: `evening_detective_frontend`, `evening_detective_server`
- Цель: после входа в команду показывать игроку название его команды на экране ожидания старта игры.
- Решение: `GetTeamActions` заполняет существующее поле `game.teams` только ID и названием текущей команды после проверки доступа; `TeamStoryPage` выводит название над QR-кодом на экране ожидания, используя текущий стиль.
- Критерии: после входа в команду до начала игры видно её название; после обновления страницы название сохраняется; отображается название именно той команды, в которую вошёл игрок; вход в команду и запуск игры продолжают работать.
- Ограничения: минимальное изменение интерфейса; не добавлять зависимости; не менять авторизацию и игровую логику. Пользователь разрешил дополнить ответ `GetTeamStory` названием текущей команды; используется существующее поле `game.teams`, только ID и название текущей команды.
- Не входит: редактирование названия команды; изменение экранов во время игры и после её завершения; редизайн экрана ожидания.
- Проверка: `cd evening_detective_frontend && npm run type-check && npm run lint && npm run lint:css`; ручное ревью diff по `docs/FRONTEND_CODE_STANDARD.md`.
- Ручная проверка: войти в команду до старта игры, проверить её название на экране ожидания, обновить страницу и убедиться, что название отображается; запустить игру и проверить штатный переход к игре.
- Результат: название загружается с сервера при открытии и обновлении страницы; protobuf, вход и переходы игры не менялись. Регрессионный тест проверяет ID и название без приватных данных. По уточнению пользователя название выделено жирным без подписи «Команда»; две строки над QR-кодом заменены на «Код для подключения».
- Проверки: `gofmt`, `go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css` — успешно; `TestFinishedTeamStoryPostgres` с локальной тестовой БД — успешно. Весь diff вручную проверен по `GO_STANDARD.md` и `FRONTEND_CODE_STANDARD.md`; нарушений нет. Браузерный smoke не выполнялся.
### ED-031 — UUID v7 команд во всех окружениях
- Статус: `DONE`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`, инфраструктурные проверки
- Цель: независимое создание команд онлайн и на нескольких автономных площадках без пересечения ID; сохранение ID при переносе и возврате результатов.
- Решение: UUID v7 генерируется в Go; БД хранит UUID, API и фронтенд используют строки. Миграция заменяет старые ID, сохраняя игровые данные и связи; пакеты игры и результатов переходят на версию 2.
- Критерии: все способы создания команд используют v7; игровые операции, карта, QR, отзывы, MCP и устройства работают; перенос и возврат сохраняют UUID; миграция сохраняет данные.
- Ограничения: старые ссылки и ZIP не поддерживаются; перед обновлением завершить текущие переносы, сохранить резервные копии и согласованно обновить окружения. Новые зависимости, commit и push исключены.
- Проверка: миграция отдельной тестовой БД; `go test ./...`; `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`; сценарии `tests/venue/flow.py`.
- Результат: UUID v7 генерируется существующей Go-зависимостью во всех способах создания команд; изменены UUID/FK/карта, API, frontend, QR, MCP, устройства, экспорт/импорт и возврат. Форматы пакетов версии 2 сохраняют UUID. Добавлена миграция заполненной БД; старые реестры переноса очищаются без удаления игрового прогресса и материалов. Документирован согласованный переход и откат из резервной копии. Новых зависимостей нет.
- Сопутствующее исправление: браузерная проверка обнаружила гонку загрузки прав при прямом открытии вкладки ответов. Загрузка теперь реактивна после получения роли и при выборе вкладки, без двойного запроса.
- Проверки: `make generate`, `npm run proto:gen`, `go test ./...` и полный Go-набор с изолированным PostgreSQL прошли; проверены независимые UUID v7 в трёх схемах, публичная регистрация, неверные ID и отклонение ZIP v1. `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` и оба Node-теста присутствия устройств прошли. `tests/venue/flow.py --apply --browser` проверил миграцию, оба формата игры, перенос/возврат, конкурентность, повтор и рестарт; финальный frontend дополнительно прошёл Firefox 1440px online и 390px offline на отдельном временном стенде. `git diff --check` прошёл в корне и обоих репозиториях; выполнено независимое ревью и сверка стандартов Go/frontend.
- Ограничения проверки: миграции рабочих БД и развёртывание не выполнялись; реальные телефоны, камера и аппаратная работа без WAN не проверялись. Commit/push не выполнялись. Существовавшие изменения `prod`, `reproxy` и backend-бинарника сохранены.
### ED-029 — Автономная площадка и панель организатора
- Статус: `DONE` — закрыта 2026-10-11 по явному указанию пользователя; код и автоматические проверки завершены, аппаратная приёмка этапа 15 не выполнена.
- Репозитории: корневой, `evening_detective_server`, `evening_detective_frontend`.
- Цель: реализовать принятый пользователем план из 15 последовательных этапов: автономное окружение; локальные организаторы; прежние адреса через Cudy; пакет игры; экспорт со статусом офлайн-режима; локальный импорт; интерфейс передачи; полный билетный и игровой flow; пакет результатов; возврат онлайн; интерфейс возврата; устройства; панель состояния; сбор данных Cudy; Wi-Fi и испытание площадки.
- Критерии: проверяемый результат каждого этапа; цикл «онлайн → ноутбук → проведение → онлайн» через интерфейс с сохранением QR, билетов и связей; повторные импорты без дублей; мониторинг устройств и Wi-Fi; полный прогон без WAN, 100 клиентов и проверка покрытия.
- Ограничения: только тестовые игры до завершения возврата; существующие правила игры и формат `offline` сохраняются; без несогласованных новых зависимостей и отклонений от стандартов; без персональных списков игроков, CPU/памяти Cudy и автоматического переключения серверов; настройки роутера менять только по явному запросу пользователя; секреты и пакеты вне Git; commit/push выполняет пользователь.
- Проверка: Go-стандарт и `go test ./...`; PostgreSQL-интеграционные тесты для атомарности; frontend-стандарт, type-check, lint, lint:css и build; штатная генерация protobuf; ручные контрольные точки после этапов 3, 8, 11, 15.
- Прогресс: этапы 1–2 реализованы и проверены в локальном Docker-окружении. Добавлены отдельный Compose, подготовка образов заранее, постоянные тома, миграции перед стартом, healthchecks и прокси. Явный `APP_MODE=venue` отключает SMTP, фоновые письма и внешний webhook; почтовые операции аккаунта возвращают безопасную ошибку до изменения данных. Локальные аккаунты создаются штатным `dev-user.sql`, роли и правила автоматического подтверждения команд сохраняются. Этап 3 принят пользователем после проверки без WAN; формат и код пакета игры (этап 4) реализованы и проверены. Экспорт со статусом офлайн-режима (этап 5) и локальный импорт (этап 6) реализованы и проверены. Этап 7 реализован и проверен; этап 8 проверен на изолированном стенде и принят пользователем на аппаратной контрольной точке; этапы 9–13 реализованы и проверены; этап 14 реализован и проверен на настоящем TR3000; код и автоматические проверки этапа 15 завершены, ожидается аппаратная приёмка Wi-Fi.
- Дополнение по запросу пользователя: структура `venue` приведена к `prod` (`backend/`, `frontend/dist/`, `migrations/`, `Dockerfile.backend`, `docker-compose.yml`, `deploy.sh`); имена основных Compose-сервисов совпадают. Общая генерация `make build` / `make prod-build` готовит артефакты обеих папок; frontend собирается отдельно с настройками своего окружения. Текущие файлы `prod` при этой работе не изменяются; сборка проверяется с production-выводом в `/tmp`.
- Упрощение запуска: отдельные `init.sh` и `prepare.sh` удалены, всё собрано в `deploy.sh`. Единственная команда запуска — `make venue`: создаёт `.env` только при его отсутствии, при необходимости готовит зависимости/образы и автоматически создаёт организатора. Повторный готовый запуск не собирает и не скачивает образы. `make venue-update` явно пересобирает окружение с интернетом. Аккаунт организатора синхронизируется со значениями `.env` при каждом запуске. Первый запуск, повторный запуск без интернета и обновление проверяются `python3 tests/venue/deploy.py` с подставными командами; реальный готовый запуск проверен через Docker и API-smoke.
- Настройки площадки: по запросу пользователя необязательный `venue/.env.example` удалён; настройки создаются автоматически через `make venue`. Убраны ссылка и проверка примера; `python3 tests/venue/deploy.py` прошёл. Существующая `.env` не изменялась.
- Группировка проверок: `deploy.py` и `smoke.py` собраны в `tests/venue/` с поясняющим README, пути к площадке и команды в документации обновлены; для обычного запуска эти файлы не нужны. `python3 tests/venue/deploy.py` и `python3 tests/venue/smoke.py --verify` прошли; diff проверен.
- Уточнение названия: автономная площадка называется `venue`, чтобы не смешивать её с локальной разработкой. Папка, Make-команды, образ, Docker-проект, режим `APP_MODE=venue` и настройки `VENUE_*` переименованы; существующая `.env` перенесена с сохранением секретов и учётной записи. Служебные имена прежних томов сохранены для сохранности данных; тома подключаются как внешние и создаются автоматически при первом запуске. Go-тесты, тест запуска и API-smoke после переименования прошли; `prod` не изменён. Ручное ревью diff по стандарту Go выполнено.
- Проверка дополнения завершена: `make build PROD_DIR=/tmp/evening-artifacts-check` прошёл, backend и миграции в обоих наборах совпадают; type-check и две frontend-сборки прошли. Проверены Compose config, shell-синтаксис и diff. Local собран и запущен через новый `deploy.sh`; API-smoke и Firefox подтвердили вход, тестовую игру, подтверждённую команду и сохранность материала. Контрольные суммы файлов `prod` до и после работы совпадают. Проверка production-запуска не выполнялась; существующие файлы и конфигурация `prod` не изменены.
- Результат проверки этапов 1–2: ручное ревью diff по Go- и frontend-стандартам выполнено, отклонений нет; `gofmt`, `go test ./...`, frontend `type-check`, `lint`, `lint:css`, сборка и полный `sh venue/prepare.sh` прошли. Compose config и shell-синтаксис проверены. Smoke через API создал тестовую игру, подтверждённую команду и материал; после `down` / `up --no-build --pull never` всё сохранилось. Firefox без окна подтвердил реальный вход, экран игры и команду после перезапуска. Приложение не имеет внешнего маршрута сети. Повторная инициализация не перезаписывает секреты. Инструкции запуска и повторяемый API-smoke находятся в корневом README и `tests/venue/smoke.py`. Проверка телефонов при отключённом WAN ещё не выполнена.
- Внешние данные: запрошены модель/IP Cudy, постоянный IP ноутбука, доступ к проверенной прошивке и возможность DNS-проверки для сертификатов. Проверки телефонов, 100 клиентов и покрытия требуют оборудования.
- Привязка ноутбука на Cudy по явному запросу «закрепи сам»: перед изменением подтверждены текущие IP 192.168.10.155 и MAC BC:D2:2C:29:4A:96. Через штатную форму IP/MAC Binding добавлена запись `Venue laptop`, выполнен Save & Apply; повторное чтение подтвердило ровно одну новую запись с нужной парой IP/MAC и сохранность обеих существующих привязок. DHCP/DNS-настройки и прошивка не менялись. Проверка DNS venue по UDP/TCP после сохранения прошла. Принудительное переподключение ноутбука для проверки новой DHCP-аренды не выполнялось; проверка телефонов без WAN остаётся обязательной.
- Локальный DNS по согласованию пользователя добавлен: CoreDNS 1.14.7 запускается с venue на TCP/UDP 53 только на `VENUE_BIND_IP`; оба домена возвращают этот IPv4, AAAA-запросы не получают внешних адресов. Отдельные локальные зоны не пересылаются upstream; остальные домены направляются в 1.1.1.1/8.8.8.8 при доступном WAN. DNS подключён только к сети публикации портов и не имеет доступа к внутренней сети приложения/БД. Образ закреплён по версии, скачивается при отсутствии и используется повторно; новая инфраструктурная зависимость явно согласована пользователем. Локальная `.env` изменена только в `VENUE_BIND_IP=192.168.10.155`, секреты сохранены. `make venue` успешно пересобрал образ из готовых файлов, выполнил миграции и перезапустил HTTPS/DNS с сохранением томов. Настройки Cudy не менялись.
- Проверки DNS: `python3 tests/venue/deploy.py`, `python3 tests/venue/https.py --docker`, `python3 tests/venue/dns.py --docker`, `python3 tests/venue/dns.py --server 192.168.10.155`, shell-/Python-синтаксис и `git diff --check` прошли. Реальный CoreDNS в отдельной внутренней Docker-сети подтвердил локальные ответы по UDP/TCP и отсутствие внешних IPv6-ответов без WAN до/после перезапуска. Проверены Compose mount/порты/DNS-IP и изоляция backend; обычный внешний домен успешно разрешается через upstream на запущенной площадке. HTTPS-smoke с принудительным разрешением обоих имён только в IP ноутбука и обычной проверкой TLS подтвердил вход организатора, сохранность тестовой игры/команды/материала, SPA и отключённые email-операции. Ручное ревью diff выполнено; код Go/Vue и protobuf не менялся. Проверка DNS через DHCP Cudy и телефонов без WAN ещё требуется; IP ноутбука пока динамический.
- Проверка реального Cudy: TR3000, прошивка 2.5.27 DE, панель доступна на 192.168.10.1; текущий DHCP-IP ноутбука 192.168.10.155 ещё не закреплён. По предоставленному пользователем файлу выполнен вход и прочитаны Custom DNS и DHCP. В этих разделах нет формы статических записей «домен → IP»: Custom DNS выбирает upstream DNS, DHCP позволяет выдавать клиентам Preferred/Alternate DNS. Настройки роутера не менялись. Для сохранения штатной прошивки предложен отдельный локальный DNS на ноутбуке с двумя записями и выдачей его адреса через DHCP; это дополнение к прежнему плану требует согласования инфраструктуры. Пользовательский pass.txt защищён режимом 600 и исключён из Git; пароль и сессионные данные не выводились. Следующий шаг — согласовать реализацию локального DNS, закрепить IP, настроить DHCP и выполнить аппаратную приёмку.
- Выпуск сертификата по запросу пользователя начат: скачан официальный образ Certbot, отдельный ACME-аккаунт и запрос на два домена созданы в игнорируемом `venue/certificates/acme/` с ограниченным доступом. Certbot ожидает добавления двух TXT-записей DNS-01 в публичный DNS; доступ к DNS в среде отсутствует, значения переданы пользователю. Сертификат ещё не выдан и не установлен; production-ключи и настройки не использованы, площадка не перезапускалась. После появления записей проверить публичный DNS, завершить валидацию, установить полную цепочку и ключ в `venue/certificates/` и проверить их перед запуском.
- Результат выпуска сертификата: после добавления пользователем TXT-записей оба значения проверены через публичный DNS, DNS-01 успешно пройден. Отдельный сертификат Let's Encrypt для обоих прежних доменов установлен в `venue/certificates/fullchain.pem`, ключ — в `privkey.pem` с режимом 600; каталог и ACME-файлы вне Git, production-ключ не использован. Срок действия до 2027-01-08 06:53:26 UTC. OpenSSL подтвердил системное доверие полной цепочке, оба домена и соответствие ключа; игнорирование обоих файлов проверено. Автопродления нет: до истечения срока повторить DNS-01 и установить обновлённые PEM-файлы. Площадка в рамках выпуска сертификата не перезапускалась; Cudy и телефоны без WAN ещё не проверены.
- Актуальный запуск по последующему запросу пользователя: `make venue` всегда использует HTTPS-дополнение, выполняет `docker compose build --pull=false` из заранее подготовленных артефактов и `up --force-recreate --no-build --pull never`; тома данных сохраняются. `venue-update` и `venue-https` — алиасы единого запуска. Сертификат проверяется до Docker; Go/Vue и npm-зависимости при деплое не собираются. Отсутствующие runtime-образы и базовый Alpine скачиваются, имеющиеся не обновляются автоматически. HTTPS теперь используется smoke-проверкой по умолчанию. README и тесты приведены к единому поведению; `python3 tests/venue/deploy.py`, shell-синтаксис, Python-синтаксис, dry-run всех трёх Make-команд и `git diff --check` прошли; diff вручную проверен. Реальный перезапуск площадки с публичным сертификатом и сборка Docker-образа без WAN не выполнялись; Cudy и проверка телефонов остаются внешней контрольной точкой.
- Уточнение сборки по запросу пользователя: деплой больше не вызывает `make build`, Go/Vue-сборку или установку npm-зависимостей. Артефакты заранее готовятся существующим `make prod-build` в обеих папках; при отсутствии бинарника, Goose, bootstrap SQL, frontend или SQL-миграций запуск завершается до Docker с понятной ошибкой. `make venue-update` только упаковывает готовые файлы в Docker-образ и подготавливает runtime-образы. README обновлён; тесты первого, автономного и update-запуска подтверждают отсутствие make/npm, ошибки отсутствующих артефактов и сохранность настроек. `python3 tests/venue/deploy.py`, `python3 tests/venue/https.py`, `bash -n venue/deploy.sh`, `git diff --check` прошли; diff вручную проверен. Повторная реальная сборка приложения и запуск площадки не выполнялись; код дочерних репозиториев не менялся.
- Подготовка этапа 3: добавлены `make venue-https`, отдельное Compose-дополнение и Nginx-конфигурация для прежних доменов интерфейса/API. HTTP перенаправляется на HTTPS с сохранением пути и параметров; API и материалы доступны через домен интерфейса и прежний API-домен. HTTPS-дополнение задаёт публичные адреса ссылок без изменения `.env`. Сертификат и ключ подключаются только для чтения из игнорируемого каталога; до Docker проверяются доверие полной цепочке, оба домена, срок действия и соответствие ключа. Повторный HTTPS-запуск перечитывает сертификат без пересборки. Обычный HTTP-запуск сохранён; добавлены HTTPS-smoke и инструкции DNS-01, LAN, продления и ручной приёмки. Код Go/Vue, protobuf, схема БД и конфигурация `prod` не менялись; новых зависимостей нет.
- Проверки подготовки этапа 3: `python3 tests/venue/deploy.py`, `python3 tests/venue/https.py --docker`, `bash -n venue/deploy.sh` и `git diff --check` прошли; Python-файлы проверены на синтаксис. Проверены реальный Compose merge, прежние тома и внутренняя сеть backend. Временные Docker-контейнеры с тестовым CA подтвердили проверяемый TLS/SNI, оба домена, redirects, API/материалы, SPA-пути с параметрами, перезапуск и замену сертификата через reload; свои ресурсы тест удалил. Проверки сертификатов покрывают отсутствующие/повреждённые файлы, неверный и зашифрованный ключ, недоверенную/неполную цепочку, отсутствие каждого домена и истечение срока; ошибка возникает до Docker, повторный готовый запуск не скачивает и не собирает образы, `.env` сохраняется. Ручное ревью diff выполнено; стандарты Go/Vue не затронуты. Реальное HTTPS-развёртывание, системное доверие телефонов, Cudy и WAN-off smoke не проверены из-за отсутствия оборудования/сертификата. Commit/push не выполнялись.
- Подтверждение пользователя: venue работает в браузере ноутбука и на телефоне после настройки DNS. Проверка Android/iPhone при отключённом WAN и мобильных данных ещё не подтверждена.
- Проверка ноутбука после изменения настроек роутера пользователем: системный DNS разрешает UI-домен в 192.168.10.155; HTTPS UI и API возвращают HTTP 200 с этого IP, сертификат проходит проверку. В DHCP также получен второй DNS 192.168.10.10; его назначение не проверено. Пользователь подтвердил открытие venue на телефоне, проверка без WAN ещё не выполнена. В браузере ноутбука остаётся проверить обновление DNS-кэша и использование системного DNS.
- Результат настройки DHCP: по запросу пользователя в Cudy сохранён Preferred DNS=192.168.10.155, Alternate DNS пустой. Повторное чтение формы подтвердило значения и сохранение остальных настроек DHCP; проверка локальных доменов по UDP/TCP прошла. Получение DNS клиентами после обновления DHCP-аренды ещё не проверено.
- Приёмка этапа 3: пользователь сообщил «все проверил работает» после контрольного списка LAN-портов, обновления DNS устройств и проверки Android/iPhone с отключёнными WAN и мобильными данными. Аппаратный блокер снят по подтверждению пользователя; агент самостоятельно эти проверки не повторял.
- Результат этапа 4: добавлен `GamePackageService` для потоковой сборки и автономного чтения ZIP версии 1 из подготовленного снимка. Пакет сохраняет исходные ID, пароли QR, хеши/статусы билетов, email капитанов, сценарий с ответами, план экранов, карту команд/стола, плейлисты и все медиа. Внешние HTTP/HTTPS-медиа скачиваются с проверками адресов DNS/соединения/перенаправлений; локальные файлы доступны через адаптер существующего хранилища. Совпадающие файлы хранятся один раз. Архив и распакованный объём ограничены 1 ГиБ, файл — 64 МиБ, JSON — 8 МиБ, количество записей — 4096. Проверяются версия, связи, размеры, SHA-256, MIME, опасные пути, дубли и отсутствующие/посторонние файлы; временные каталоги и файлы имеют права 0700/0600 и очищаются на ошибке. БД, API, protobuf, зависимости и текущий архив сценария не изменены. Контракт и владение временными файлами описаны в `evening_detective_server/docs/GAME_PACKAGE.md`.
- Проверки этапа 4: `gofmt`, `go test ./internal/services/game_package_service -count=1`, полный `go test ./...` и `git diff --check` прошли. Табличные тесты проверяют сохранение данных/секретов QR/билетов, оба назначения плейлистов, автономное чтение, внешние/локальные URL, дедупликацию, запрещённые адреса и redirects, повреждённые пакеты, масштабированные лимиты ZIP/распакованного объёма и отмену во время извлечения с сохранением родительского каталога. Потоковое чтение проверено на генерируемых медиа 1 и 16 МиБ с ограниченным размером чтения. Ручное ревью всего нового кода по Go-стандарту и независимое ревью проведены; замечания исправлены. Реальный пакет на 1 ГиБ, скачивание с внешнего production-хостинга и перенос игры между БД не проверялись; UI/экспорт/импорт реализуются на следующих этапах. Commit/push не выполнялись.
- Результат этапа 5: сохранён согласованный SQL-снимок и одна активная попытка экспорта на игру. Снимок учитывает выбранную музыку в `game_music_states`, команды, билеты, сценарий, план экранов и карту. Пакет собирается в фоне, потоково хранится в закрытом RustFS; PostgreSQL-очередь, heartbeat 30 секунд, аренда 2 минуты, timeout 30 минут и защита от устаревшего worker сохранены. API и оба protobuf-клиента сгенерированы; права трёх ролей и запрет экспорта в `venue` проверены. Повторное скачивание отдаёт те же байты, обрыв не меняет состояние.
- Изменение решения (2026-10-11): по запросу пользователя жёсткая блокировка полностью удалена; функции/триггеры БД не используются. Все обычные операции игры, команды, билеты, прогресс, музыка, карта, экраны и почтовые задания продолжают штатную работу. В списке игр и на странице управления показываются подготовка офлайн-пакета (`preparing`) и «Игра в офлайн-режиме» (`ready`). Это информационная отметка, без изменения игрового `status` или `format`; при ошибке она исчезает. Онлайн-изменения после запуска не попадают в сохранённый пакет; локальный импорт реализован на этапе 6; возврат ещё не реализован.
- Проверка этапа 5: ранее прошли реальный тестовый RustFS-цикл с перезапуском, проверкой ZIP кодеком, приватностью объекта, потоковой выдачей/обрывом и повторным скачиванием одинаковых байтов. После упрощения прошёл полный `go test ./...` с PostgreSQL: снимок, редактирование в `preparing`/`ready`, конкурентный запуск, аренда, устаревшая публикация, ошибка/повторный запуск и завершение/очистка после удаления игры. Frontend `type-check`, `lint`, `lint:css` и Vite build в `/tmp` прошли; `gofmt` и diff проверены. Проверка интерфейса в браузере и повторный реальный RustFS-цикл в этом уточнении не выполнялись. API описан в backend `docs/GAME_PACKAGE.md`. Production-развёртывание, commit и push не выполняются.
- Результат этапа 6: добавлен потоковый `POST /api/games/import` (сырой ZIP, JWT, роли admin/developer/organizer, только venue) и соответствующий protobuf-контракт. Кодек проверяет пакет до записи; игра, команды, билеты, сценарий, плейлисты, треки, план экранов, карта и метаданные публикуются одной транзакцией после загрузки медиа в локальный RustFS. ID игры/команд/билетов, пароли QR, хеши и состояния билетов сохранены. Сценарий/плейлисты/треки получают отдельные локальные ID; сценарий принадлежит импортирующему пользователю, исходные пользовательские ссылки не связываются с локальными аккаунтами. Исходный снимок и соответствия ID сохраняются в закрытом реестре импорта. Занятые ID/хеши и другой пакет той же игры отклоняются; повтор того же ZIP ничего не меняет, в том числе после локального редактирования или удаления игры. Реестр, heartbeat 30 секунд, аренда 2 минуты и timeout 30 минут защищают публикацию; очистка ошибок повторяется после перезапуска и не удаляет медиа при неопределённом ответе commit. Для маршрута импорта venue-прокси настроены лимит 1 ГиБ и потоковая передача; production-конфигурация не менялась.
- Проверки этапа 6: штатные `make generate` и `npm run proto:gen`; полный обычный `go test ./...`; PostgreSQL-тесты импорта, экспорта и API; `go test -race` для imports repo/service и app; frontend type-check, lint, lint:css и Vite build в `/tmp`; `python3 tests/venue/deploy.py`, `python3 tests/venue/https.py --docker` и diff-проверки прошли. Тесты покрывают связи исходных ID, локальные копии, QR/билеты, пустые наборы данных, последовательности, повтор/конкурентность, конфликты до/после загрузки, изменённые байты под тем же package ID, rollback, отмену, аренду/timeout, ошибки очистки и неопределённый commit. Реальный HTTP/RustFS smoke прошёл в отдельной internal Docker-сети без WAN, с отдельными PostgreSQL/RustFS, чтением медиа, перезапуском хранилища и повторным импортом; тестовые контейнеры и данные удалены. Nginx проверен на обоих HTTPS-доменах, включая POST импорта. Ручное ревью изменений по Go/frontend-стандартам выполнено. Пакет на 1 ГиБ, реальные телефоны и обновление работающей площадки не проверялись; новая миграция `20261011120000_create_game_imports.sql` требуется при обновлении. Commit/push не выполнялись.
- Результат этапа 7: в настройках игры на подтверждённом prod доступны подготовка и скачивание пакета, состояния из `game.export` восстанавливаются через существующий polling; ошибка допускает повтор подготовки, готовый ZIP — повтор скачивания. Добавлены пояснения о снимке и отсутствии подтверждения импорта. На venue в списке игр добавлена Naive UI-модалка импорта одного непустого ZIP до 1 ГиБ с именем/размером; загрузка блокирует повтор, смену файла, Escape и закрытие. После импорта обновляется список, показаны обычный/повторный результат и открытие с проверкой доступности игры; удалённая игра не восстанавливается. Действия доступны admin/organizer/developer, при неизвестной среде скрыты. Бинарный клиент сохраняет JWT-refresh, отправляет исходный File с `application/zip`, использует generated тип импорта, поддерживает обе формы ошибок и имя из Content-Disposition; object URL освобождается. Backend/API, зависимости и маршруты не менялись.
- Проверки этапа 7: frontend type-check, lint, lint:css, Vite-сборка в `/tmp` и diff-проверка прошли; ручное ревью по frontend-стандарту выполнено. Все 17 тестов `node src/stores/__tests__/auth.test.ts` прошли, включая ZIP-body/JWT-refresh, результат импорта, оба формата серверных ошибок, сетевую ошибку и UTF-8-имя скачивания. Firefox с подставным API на 1440/390 px проверил export polling, восстановление подготовки после обновления, ошибку/повтор и скачивание; импорт, повтор, удалённую игру, конфликт и сетевую ошибку; пустой файл, расширение, лимит; блокировки отправки/выбора/закрытия, Escape, клавиатурный focus в модалке, роли и неизвестную среду. Реальный перенос между серверами, телефоны и Blob-пакет на 1 ГиБ в этом этапе не проверялись; развёртывание не выполнялось.
- Результат автоматической части этапа 8: добавлены повторяемые `tests/venue/flow.py` и `flow_browser.py`, команды и ручной контрольный список в README проверок. Актуальный код собирается в `/tmp`; стенд запускает два настоящих backend prod/venue с отдельными PostgreSQL/RustFS в Docker internal-сети без WAN, SMTP направлен в локальный sink. API проверяет оба формата, экспорт/импорт ZIP, исходные ссылки/ID/пароли команд и билетов, статусы участия, QR/PDF, обычный/повторный/конкурентный приём билетов, отказ без авторизации и неверные ссылки, локальные команды/билеты, старт/ходы/выдачу материалов/паузу/продолжение/завершение, ответы и баллы, результаты, перезапуск всех venue-сервисов и повторный импорт без потери прогресса. Проверена независимость источника и площадки; ограничения формата `offline` сохранены. После проверки удаляются только ресурсы стенда; ошибка очистки одного ресурса не останавливает попытки очистить остальные.
- Исправления этапа 8: общий gameplay-сервис проверяет `run` до записи хода и подтверждения участия, одинаково для API/MCP; безопасная ошибка отображается как FailedPrecondition. Кнопка хода блокируется вне `run` и при отправке; отказ показывается пользователю и сохраняет код. Кнопкам lifecycle добавлены доступные имена. Конкурентный приём билета теперь перечитывает текущее состояние и сообщает «билет уже использован», а не ошибочно «игра уже завершена». PostgreSQL-тест конкурентности синхронизирует запросы блокировкой строки: до исправления воспроизводил ошибку, после исправления проходит.
- Проверки этапа 8: `python3 tests/venue/flow.py --browser` прошёл с реальными API/хранилищем и отдельным браузерным стендом. Firefox проверил полный UI-flow на 1440 px (`online`) и 390 px (`offline`), реальное скачивание/загрузку ZIP, билеты, ходы и polling, паузу с введённым кодом, двойную отправку, отказ с сохранением ввода, выдачу материала, оценивание/результаты, завершённый экран игрока, неверный пароль и клавиатурный focus в модалке. Внутри стенда прошли PostgreSQL-регрессии gameplay/lifecycle, tickets, MCP и app; отдельно прошёл полный `go test ./...`. Frontend type-check, lint, lint:css и сборка в `/tmp` прошли; синтаксис Python, `gofmt`, diff-проверки, ручное ревью по Go/frontend-стандартам и независимое ревью затронутого flow выполнены. API/protobuf, миграции и зависимости не менялись. Работающие окружения и Cudy не изменялись; существующие пользовательские изменения бинарника и `prod` сохранены.
- Приёмка этапа 8: пользователь подтвердил «Этап 8 принят» при согласовании следующего этапа. Отдельный повтор аппаратной проверки агентом не выполнялся.
- Результат этапа 9: добавлен серверный сервис подготовки и проверки ZIP результатов версии 1, без новых API/UI, protobuf, миграций и зависимостей. Read-only PostgreSQL-снимок `REPEATABLE READ` связывает завершённую импортированную venue-игру с ID/SHA-256 исходного пакета. Сохраняются итоговые команды/участие, исходные и новые билеты, явные удаления, пароли QR/хеши билетов, порядок и время ходов/MCP, материалы и их выдача, ответы и nullable баллы. Исходные ссылки пользователей восстанавливаются из реестра; локальные исполнители вынесены в отдельное пространство. Материалы ссылаются на исходный ZIP, без локальных адресов RustFS. Изменённый игровой сценарий/формат и неизвестные материалы отклоняются. Повторная подготовка создаёт новый снимок с актуальными оценками и не меняет игру; кодек проверяет состав, версию, размеры/CRC/SHA-256, лимиты JSON/ZIP, уникальность и связи. Контракт описан в backend `docs/GAME_PACKAGE.md`.
- Проверки этапа 9: полный `go test ./...`, unit-тесты кодека/снимка и `python3 tests/venue/flow.py --results` прошли. Изолированный PostgreSQL/RustFS-стенд проверил обе игры, связь с исходным ZIP, новые локальные записи, прогресс/выдачу/ответы/баллы, свежий снимок после оценивания, конкурентное оценивание, сохранность предыдущего пакета, повтор после перезапуска и отсутствие изменений исходных игр. Unit-тесты проверяют удаления, пустые наборы, повторные/неизвестные ходы/MCP, исходных и локальных исполнителей, повреждённые ZIP и связи, лимиты, отмену и ошибки записи. `gofmt`, Python-синтаксис, diff-проверки, ручное ревью по Go-стандарту и независимое read-only ревью выполнены. Frontend-код не менялся; его штатная сборка в `/tmp` прошла в составе стенда. Тестовые пакеты/контейнеры удалены; работающие окружения и Cudy не менялись. Commit/push и развёртывание не выполнялись.
- Результат этапа 10: серверный `GameResultsApplyService` принимает ZIP только в `prod`, проверяет источник/игру/ID/SHA-256 экспорта и сохранённый исходный ZIP из закрытого хранилища. Источник команд/билетов/сценария/материалов/вопросов сверяется с ZIP, формат неизменяем. По уточнению пользователя ZIP считается источником истины: возвращаемые поля, включая онлайн-прогресс/баллы/формат и игровой сценарий, перезаписываются без сравнения с исходным или последним применённым состоянием. Изменённый сценарий восстанавливается отдельной копией для игры, не меняя сценарии других игр; исходные онлайн-ссылки материалов сохраняются. Одна `SERIALIZABLE` транзакция с блокировками и максимум тремя попытками при serialization failure/deadlock записывает итоговые команды/участие, билеты, удаления и связи карты, ходы/MCP, материалы/выдачу, ответы, nullable баллы, `finish` и фактические даты. Баллы не пересчитываются; оформление, плановая дата, музыка, карта и экраны сохраняют онлайн-изменения. Исходные ID сохраняются; новые команды сохраняют venue-ID/пароль, новым билетам/ходам/уликам выделяются онлайн-ID с реестром соответствий. Материалы возвращаются в исходные онлайн-ссылки без новых загрузок и скачивания URL. Онлайн-ссылки пользователей и технические почтовые поля сохраняются, локальные исполнители остаются в закрытом реестре; новые почтовые задания/токены не создаются, возвращённые игры исключены из очереди новых напоминаний об отзыве.
- Реестр этапа 10: миграция `game_returns` сохраняет ID/хеш ZIP, экспорт, исходный ID игры, точное UTC-время подготовки с наносекундами, время применения, соответствия ID (включая сценарий), локальных исполнителей и инициатора. Реестр остаётся после удаления игры. Повтор тех же байтов возвращает сохранённую запись, включая старый пакет после нового и повтор после удаления игры; тот же ID с другими байтами отклоняется. Новый пакет требует строго более позднего `created_at`, без поправок часов. `game.export` скрывается в игре/списке после успешного возврата соответствующего экспорта; исходный экспорт остаётся `ready`, ZIP сохраняется. Входной ZIP проходит приватный staging, чтобы проверенные данные и SHA-256 относились к одним байтам; временные файлы 0600/0700 удаляются при успехе, отказе и отмене.
- Проверки этапа 10: полный `go test ./...` с отдельным PostgreSQL, релевантный `go test -race`, unit-тесты источника/материалов/пользователей/безопасных ошибок/private staging, PostgreSQL-регрессии rollback/удалений/ID и хеш-коллизий/последовательностей/точных повторов/конкурентности/порядка пакетов (включая шаг 1 нс)/исправленных баллов/онлайн-редактирования/почтовых заданий прошли. `python3 tests/venue/flow.py --apply` прошёл для обоих форматов с настоящими venue-ZIP, prod PostgreSQL/private RustFS, исправлением баллов, прежними и новыми ссылками, сохранением оформления, исчезновением офлайн-отметки и повтором старого пакета после нового/перезапуска prod. `gofmt`, Python-синтаксис, diff-проверки, ручное ревью по Go-стандарту и независимое read-only ревью выполнены. Контракт обновлён в backend `docs/GAME_PACKAGE.md`; API/UI, protobuf и зависимости не менялись. Тестовые контейнеры/ZIP удалены; рабочие окружения и Cudy не менялись. Commit/push и развёртывание не выполнялись.
- Уточнение этапа 10 (2026-10-11): по запросу пользователя возвращаемый ZIP — источник истины, включая игровой сценарий. Удалены сравнения с исходным/последним онлайн-состоянием и поле `snapshot` реестра. При отличии сценария создаётся копия для игры с исходными вопросами и онлайн-ссылками материалов; другие игры сохраняют свой сценарий, ID копии записывается в соответствиях. Проверки после изменения: полный `go test ./...` с отдельным PostgreSQL, race для return repo/results service/export service, `flow.py --apply` обоих форматов с перезапуском prod, `gofmt`, diff-проверка и ручное ревью по Go-стандарту прошли. PostgreSQL-регрессии проверяют перезапись онлайн-команд/ответов/баллов/формата, удаление добавленных онлайн-команд, смену/правки общего сценария и отсутствие повторного копирования неизменённого сценария. Онлайн-правки возвращаемых данных теряются намеренно; проверки источника, порядка пакетов, коллизий и атомарность сохранены.
- Ограничение этапа 10: подлинность ZIP криптографически не подтверждается. `nextval` PostgreSQL не откатывается: большие разрывы venue-ID расходуют sequence даже при отказе. Продвижение выполняется пакетами с пределом пять секунд, затем данные откатываются и выдаётся безопасная повторяемая ошибка; INT32-потолок отклоняется. Перед поддержкой таких площадок требуется расширение типов ID; лимит отмечен `shortcut:` в коде и контракте.
- Результат этапа 11 (2026-10-11): подключены сервисы подготовки/применения, protobuf/OpenAPI и отдельные HTTP handlers `results-package/download` и `results-package/apply`. Venue выдаёт свежий ZIP завершённой импортированной игры после полной подготовки в файле 0600; prod принимает ограниченный поток до 1 ГиБ без обязательного Content-Length. Положительный ID и совпадение с manifest проверяются до повтора и изменений; временные файлы очищаются. Ответ содержит только gameID/packageID/appliedAt; безопасные ошибки 400/413/409/503, права организатора/администратора/разработчика. В настройках игры добавлены скачивание и применение ZIP, явное предупреждение о перезаписи данных/сценария и сохранении оформления/музыки, клиентская валидация, обновление авторизации, загрузка и блокировка повторного запроса. После успеха страница пересоздаётся и перечитывает данные без старых ответов/черновиков; повтор сообщает «Результаты приняты». Возврат остаётся доступен после снятия офлайн-отметки. Обновлены репозиторные proxy configs (1 ГиБ/30 минут), контракт и изолированный стенд; работающие серверы не менялись.
- Проверки этапа 11: штатная генерация обоих репозиториев, gofmt, `go test ./...`, PostgreSQL/race-регрессии return repo/results/export service и HTTP поверх реального сервиса, frontend type-check/lint/lint:css/build, diff-проверки и ручное ревью по обоим стандартам прошли. Независимое ревью не выявило замечаний. `python3 tests/venue/flow.py --apply --browser` прошёл полный цикл реальных API/PostgreSQL/RustFS/Firefox для online (1440 px) и offline (390 px): кнопка свежего ZIP → страница prod → результаты, прежние ссылки/билеты, сохранённые название/описание, снятая офлайн-отметка, исправленный балл, перезаписанный онлайн-ответ, повтор старого ZIP после нового и перезапуска. Проверены чужой ID до/после применения, права, MIME, заявленный размер, поток без Content-Length, безопасные ошибки и очистка файлов. Аппаратный прогон на телефонах не повторялся.
- Результат этапа 12 (2026-10-11): добавлены потокобезопасный сервис присутствия в памяти, wiring, protobuf/OpenAPI `POST /api/devices/heartbeat` и `GET /api/devices` с фильтром игры. Проверяются UUID, взаимоисключающие контексты, JWT/существующие права игры, пароль команды и неотменённое участие без загрузки сценария/прогресса, существующая сессия экрана; ID игры команды/экрана определяет сервер. Реестр хранит только проверенные связи, UUID, серверные времена и последние IP/User-Agent; credentials не сохраняются и не выдаются. Полная замена/очистка контекста, граница связи строго менее 60 секунд, удаление через 15 минут при обновлении/чтении, предел 1024 с `ResourceExhausted` без вытеснения существующих записей. В prod heartbeat явно возвращает `enabled=false`, список недоступен.
- Браузер этапа 12: общий heartbeat в App сразу/каждые 20 секунд без параллельных запросов, при видимости/восстановлении сети и смене контекста. UUID профиля отдельно от авторизации в localStorage с временным fallback, UUID подключения на экземпляр приложения. Контекст страницы очищается при уходе, отозванный lifecycle не может восстановить старые связи; смена игры/пароля пересоздаёт page-компонент. Generated client и обновление JWT организатора переиспользованы; публичные credentials команды/экрана не запускают обновление JWT. После `enabled=false` polling прекращается. Ошибки не показывают toast и повторяются по интервалу. UI списка устройств не добавлен.
- Проверки этапа 12: штатная генерация обоих репозиториев, gofmt, `go test ./...`, race для presence service/app, frontend type-check/lint/lint:css/build, self-check UUID/store/composable и diff-проверки прошли. Unit-тесты с управляемыми часами покрывают повтор/вкладки/смену и очистку связей, границы 60 секунд/15 минут, лимит и конкурентное чтение/обновление; API-тесты — роли, режимы, safe errors и отсутствие секретов. `python3 tests/venue/flow.py --browser` прошёл изолированные реальные API/PostgreSQL/RustFS/Firefox: credentials/отменённое участие, UUID/поля, группировку вкладок игрока/организатора/экрана, фильтр и привязку экрана, SPA-навигацию, прекращение heartbeat и восстановление сети, повторную регистрацию штатным интервалом после перезапуска backend. Независимое ревью выявило два замечания (публичный heartbeat не должен обновлять JWT, обрезка User-Agent должна сохранять UTF-8); оба исправлены и покрыты регрессиями. Итоговое ручное ревью по Go/Frontend стандартам выполнено; замечаний не осталось.
- Результат этапа 13 (2026-10-11): venue-вкладка «Состояние» `/games/:id?tab=state` показывает серверные connected/serverTime, количество доступных устройств/устройств без связи/подключений, UUID профиля, последние обращения и раскрываемые подключения с типом, ID команды/экрана, статусом, IP и User-Agent. Нет связи идёт первым, затем UUID; непривязанные браузеры исключает фильтр игры. Generated GetDevices вызывается сразу и каждые 5 секунд через useSimplePolling только на активной вкладке, без параллельных запросов; поздние ответы после смены игры, ухода и уничтожения игнорируются. Первичная загрузка, пустой список, встроенная ошибка, сохранение предыдущего снимка/времени и повтор реализованы без повторных toast. Вкладка доступна с клавиатуры. Игровые показатели, Cudy и история присутствия не добавлялись.
- Доступ этапа 13: GetGames/GetGame и UI permissions расширены для разработчика только в venue. Разработчик без организатора/администратора/автора получает явный whitelist ID/названия/описания/формата/места/планового начала/статуса; GetGame использует краткое чтение без сценария/команд. UI скрывает создание и результаты, показывает название и только состояние, нормализует другие tab, не загружает экраны/музыку/план/карту/ответы; heartbeat остаётся браузерным. Дополнительные роли, импорт и запреты игровых действий сохранены; prod новые права не получает. При смене роли полный поздний GetGame не применяется, приватные баннер/модалки скрываются.
- Проверки этапа 13: gofmt, полный go test ./..., race-тесты device_presence_service/app с управляемыми часами этапа 12; frontend type-check/lint/lint:css/build и self-check gameState прошли. Self-check покрывает сводку/сортировку, активность, отсутствие параллельных запросов, поздние ответы, ошибку/восстановление. Изолированные PostgreSQL/RustFS API-регрессии и Firefox проверили организатора, три подключения одного профиля, клавиатуру, смену контекста, пустой список, потерю/восстановление GetDevices, остановку запросов на другой вкладке, разработчика venue/prod, безопасные GetGame/GetGames и отсутствие закрытых фоновых запросов. API/protobuf/миграции/зависимости не менялись. Ручное ревью diff по Go/frontend-стандартам и независимое read-only ревью выполнены; пользовательские изменения prod/reproxy/backend-бинарника сохранены. Работающие окружения и Cudy не менялись.
- Результат этапа 14 (2026-10-11): отдельный процесс того же backend-бинарника `--collect-cudy` читает текущих Wi-Fi-клиентов Cudy через штатный вход и GET страницы клиентов раз в 10 секунд. Проверен настоящий TR3000 V1 2.5.27-20260804-183625; настройки не менялись. Собираются только MAC/IP/диапазон/доступный сигнал dBm, без имён, трафика и истории. Пароль читается из локального файла, не выдаётся API/логами; `venue/cudy/` исключён из Git. URL ограничен числовым private/loopback IP, redirects тем же host/scheme, ответ 2 МиБ, HTTP timeout 5 секунд, сессия переиспользуется и восстанавливается. Неизвестная разметка вызывает ошибку вместо ложного пустого списка. Collector изолирован в entrance без БД/RustFS; backend сохраняет внутреннюю сеть и читает общий атомарный снимок read-only. Без credential-файла обращений к роутеру нет.
- Результат автоматической части этапа 15: Wi-Fi-блок вкладки состояния показывает весь Cudy независимо от игры, MAC/IP/диапазон/dBm или «Нет данных», число клиентов, последний успешный снимок, ошибку/устаревание. При ошибке collector сохраняет прежние данные и время, включая перезапуск; свежесть 30 секунд считает сервер, история не сохраняется. MAC не связывается предположениями с UUID браузера. Существующий GetDevices расширен Wi-Fi-полем с теми же venue/role guards, нового endpoint/миграций/зависимостей нет. Обновлены protobuf/OpenAPI и оба generated clients.
- Проверки этапов 14–15: gofmt, `go test ./...`, race Cudy/wifi/presence/app, frontend type-check/lint/lint:css/build и self-check состояния прошли. Mock Cudy проверяет hash/CSRF/session/readonly GET, DOM/оба диапазона/сигнал/неизвестную разметку; снимок проверен атомарно и с управляемыми часами; CLI self-check подтвердил сохранение клиентов/времени после перезапуска при недоступном роутере. Firefox выявил прежнюю гонку раннего возврата ZIP до загрузки ID игры; действия передачи/возврата теперь появляются только после загрузки положительного ID. Итоговый изолированный Firefox-прогон обоих форматов (1440/390 px) прошёл: Wi-Fi fixtures, устройства/роли/polling и полный цикл ZIP до повторного возврата после перезапуска. Полный API-flow с PostgreSQL/race-регрессиями также прошёл; временные стенды удалены. `load.py` прошёл на отдельном Docker-стенде без WAN: 100 виртуальных профилей, 25 команд, 60 секунд, 300 heartbeat, 1200 story, 50 ходов, 25 ответов и 12 опросов состояния; ровно 100 доступных устройств и ноль HTTP-ошибок. p95: heartbeat 118 мс, story 68 мс, move 109 мс, answers 45 мс, devices 138 мс (бюджет теста 2 с). Нагрузка backend идёт по HTTP напрямую; DNS/HTTPS/Nginx проверены отдельно `dns.py --docker`/`https.py --docker`. Ручное ревью по стандартам и независимое read-only ревью выполнены; замечание о ложном пустом DOM исправлено и покрыто регрессией.
- Закрытие (2026-10-11): пользователь явно поручил закрыть задачу после сообщения об оставшихся проверках. ED-029 перенесена в архив по результатам реализации и автоматических проверок; аппаратная приёмка не считается выполненной. Непроверенные пункты: реальные Android/iPhone без WAN на обновлённой версии, 100 настоящих Wi-Fi-устройств, покрытие зала и фактический ZIP 1 ГиБ. Чек-лист сохранён в `tests/venue/README.md`. Всего 15 этапов; ZIP остаётся неподписанным. Развёртывание, commit/push не выполнялись.
### ED-030 — Индикатор среды сервиса в интерфейсе
- Статус: `DONE`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`.
- Связь: дополнение к ED-029; не требует готовности DNS/HTTPS и Cudy.
- Цель: пользователь видит, к какой среде подключён интерфейс: `PROD` или `VENUE`.
- Решение: показывать компактную подпись среды в общем интерфейсе рядом с навигацией; получать среду от подключённого бэкенда по фактическому режиму запуска (`APP_MODE=venue` — площадка, штатный онлайн-режим — production).
- Критерии: подпись видна на компьютере и телефоне; PROD и VENUE различаются текстом, а не только цветом; среда определяется сервером, а не адресом сайта или настройкой сборки фронтенда; при загрузке или ошибке получения среды интерфейс не показывает неподтверждённый PROD/VENUE.
- Ограничения: без переключения серверов, изменения игровых правил, показа секретов, новых зависимостей и изменения папки `prod`; использовать существующую навигацию, API и стандарты обоих репозиториев.
- Проверка: ручной прогон обоих режимов и недоступного API; Go-тесты; frontend type-check, lint, lint:css и build; при изменении protobuf — штатная генерация обоих клиентов.
- Результат: поле `environment` добавлено в существующий публичный GetPermissions API; значение определяется тем же режимом запуска бэкенда, который отключает внешние интеграции площадки. В HeaderMenu добавлены русские подписи «Сервер» (PROD) и «Локальная сеть» (VENUE) через Naive UI; загрузка, неизвестная среда и ошибки не подменяются production. Сведения меню хранятся в общем UI-store; устаревшие ответы не заменяют новые, а права не применяются после смены токена.
- Проверки: штатные `make generate` и `npm run proto:gen`, `gofmt`, `go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` и `git diff --check` прошли. Табличный Go-тест проверяет оба режима для гостя, пользователя и администратора. Firefox headless с подменой API проверил PROD/VENUE до и после входа, загрузку, серверную и сетевую ошибки, неизвестное значение; подпись находится внутри viewport при ширине 1440 и 390 px.
- Ревью: diff проверен по стандартам обоих репозиториев; зависимости не добавлены, generated-файлы получены штатной генерацией. Сборочные изменения `dist` исключены из diff; папка `prod` и существующие локальные артефакты бэкенда не менялись.
- Ограничение проверки: реальные Android/iPhone и развёртывание обновлённой версии не проверялись; для появления индикатора нужно обновить бэкенд и фронтенд. Миграция БД не требуется. Commit и push не выполнялись.
### ED-028 — Роль разработчика и общий таскменеджер
- Статус: `DONE`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: добавлены роль `developer`, выдача и отзыв роли на странице пользователей, право `tasks_page` и общая доска `/tasks` для разработчиков и администратора. Реализованы четыре статуса, создание и редактирование, назначение разработчика, необязательная календарная дата завершения, фильтр по ответственному, перенос карточек и удаление с подтверждением. PostgreSQL хранит задачи; версии защищают от конкурентной перезаписи, форма сохраняет черновик при конфликте. При отзыве роли прежнее назначение сохраняется; при удалении пользователя задача сохраняется без ссылок на него.
- Стандарты: ручное ревью всего diff по `GO_STANDARD.md` и `FRONTEND_CODE_STANDARD.md` выполнено; новые зависимости не добавлены; API сгенерирован штатными командами; сборочные изменения `dist` исключены из diff.
- Проверки: `make generate`, `npm run proto:gen`, стандартный `go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` и `git diff --check` пройдены. Интеграционный `go test ./internal/repos/tasks_repo -count=1 -v` с отдельной `TEST_DATABASE_URL` пройден: ограничения БД, назначения, смена статусов, конкурентные записи, удаление пользователей и миграция Up/Down. Шесть тестов дедлайна пройдены в `Asia/Barnaul` и `America/Los_Angeles`.
- Проверка браузера: Firefox headless с подменой API — создание, назначение ответственного и даты, редактирование, сохранение черновика при конфликте, перетаскивание, подтверждение удаления и отказ пользователю без роли; мобильная ширина 380 px, горизонтальная прокрутка только внутри доски. Полный сценарий с работающим production-сервисом не запускался.
- Известное ограничение проверки: дополнительный полный `go test ./...` с `TEST_DATABASE_URL` обнаружил существующие ошибки игровых фикстур в `answer_service`, `game_service`, `gameplay_service`, `participation_service` (временные таблицы не соответствуют текущей схеме). Эти тесты не менялись; стандартный полный прогон и новые интеграционные тесты проходят.
- Запуск: применить миграцию `20261007130000_create_developer_tasks.sql` штатным процессом миграций и выдать пользователю роль на странице `/users`; после нового входа доступна `/tasks`. Production-миграции, commit и push не выполнялись.
### ED-020 — Музыка из плейлиста на экранах игры
- Статус: `DONE`
- Приоритет: `P1`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: добавлены общие MP3-плейлисты и треки, назначение default-плейлиста сценарию и выбор музыки для игры. Состояние музыки хранится на уровне игры и синхронизируется через существующий polling экранов; добавлены play/pause/stop, выбор трека, громкость, loop, автопереход и единственный экран со звуком. Добавлены UI управления во вкладке «Экраны» и выбор плейлиста в редакторе сценария.
- Проверки: `GOCACHE=/tmp/evening-detective-go-cache go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` и `git diff --check` пройдены; protobuf сгенерирован штатными командами.
- Ручная проверка: не выполнялась в среде агента; требуется проверить загрузку MP3 от ролей, воспроизведение на двух экранах, автопереход, loop и переподключение.
### ED-027 — Упростить экран игры организатора
- Статус: `DONE`
- Приоритет: `P1`
- Репозиторий: `evening_detective_frontend`
- Результат: админский экран игры разделён на вкладки «Игра», «Команды», «Экраны» и «Карта». Вкладка «Игра» открывается по умолчанию и содержит статус, таймер, управление состоянием и служебные действия; выбранная вкладка хранится в query-параметре `tab` и восстанавливается после обновления. Существующие панели, API и игровая логика сохранены.
- Проверки: `npm run type-check`, `npm run lint`, `npm run lint:css`, `git diff --check` пройдены.
- Ручная проверка: не выполнялась в среде агента; требуется проверить переключение вкладок и основные действия на реальном экране организатора, включая узкую ширину.
### ED-015 — План экранов игры для организатора
- Статус: `DONE`
- Приоритет: `P1`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: добавлен необязательный план экранов игры с линейными шагами, текущим индексом и параметрами текста и таймера. Организатор может создать, изменить, удалить и переставить шаги, а также перейти на любой шаг; состояние применяется ко всем подключённым экранам и повторно применяется при привязке нового экрана. Добавлен текстовый режим экрана. Игры без плана продолжают работать через существующее ручное управление; синхронизация использует текущий polling.
- Проверки: целевые backend-пакеты и `screen_plan_service` проходят; frontend `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` и `git diff --check` пройдены; protobuf сгенерирован штатными командами. Полный backend `go test ./...` дополнительно упирается в sandbox-запрет `listen tcp` в gateway-тестах.
- Ручная проверка: не выполнялась в среде агента; требуется проверить реальными экранами создание плана, переходы, синхронизацию нескольких дисплеев и переподключение.
### ED-016 — Привязка экрана к игре через сканер
- Статус: `DONE`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: на странице игры добавлено сканирование QR-кода экрана с немедленной привязкой к текущей игре; список экранов показывает онлайн/оффлайн-состояние и предупреждает о недоступности более минуты. Сервер разрешает управление организатору и администратору, корректно перепривязывает экран и переносит текущее состояние целевой игры.
- Проверки: `GOCACHE=/tmp/evening-detective-go-cache go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `git diff --check` пройдены.
### ED-026 — Количество игроков при создании команды из панели игры
- Статус: `DONE`
- Приоритет: `P1`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: в форме создания команды на `GamePage` добавлено количество игроков со значением `1` по умолчанию и диапазоном `1–8`. Значение передаётся через `AddTeam` и сохраняется в существующем `teams.participants_count`; старые flow без значения сохранены.
- Проверки: `go test ./...`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` пройдены; protobuf сгенерирован штатными командами; `git diff --check` пройден.
### ED-023 — Оценка сложности игры в отзыве и каталоге
- Статус: `DONE`
- Приоритет: `P1`
- Репозитории: `evening_detective_server`, `evening_detective_frontend`
- Результат: в отзыв добавлена обязательная оценка сложности `1–3`; значение хранится в существующей таблице отзывов и передаётся через protobuf. Средняя сложность считается по одобренным отзывам завершённых игр сценария и отображается как «лёгкая», «средняя» или «тяжёлая» в каталоге и карточке сценария. Старые отзывы поддержаны значением по умолчанию `2`; рейтинг `1–5`, модерация и запрет повторного отзыва сохранены.
- Проверки: `go test ./...` пройден с кэшем в `/tmp`; `npm run type-check`, `npm run lint`, `npm run lint:css` пройдены; protobuf сгенерирован штатными командами; `git diff --check` пройден.
### ED-012 — Строгий стандарт написания фронтенда
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: создан обязательный стандарт `docs/FRONTEND_CODE_STANDARD.md` как
единственный источник правил структуры, компонентов, composables, функций,
типов, API, состояния, стилей, форм, доступности и проверок. Фронтендный
`AGENTS.md` оставлен указателем и операционными правилами, а корневой
`AGENTS.md` содержит условную ссылку для задач фронтенда.
- Проверки: проверены ссылки и однозначное размещение типовых видов кода;
`git diff --check` пройден; продуктовый код и зависимости не менялись.
### ED-025 — Доступ к БД только через repository
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Результат: прямой доступ к БД из application flow убран; проверка доступности БД вынесена в `health_repo`, `screen_sessions_repo` — в `screen_service`, а `game_map_repo` — в `map_service`. Handlers используют сервисные модели и больше не импортируют эти repositories.
- Проверки: целевые backend-пакеты компилируются; `internal/app` проходит тесты; `git diff --check` пройден. Полные gateway-тесты в sandbox заблокированы запретом на `listen` TCP-порта.
### ED-011 — Строгий стандарт написания Go-бэкенда
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Результат: добавлен обязательный стандарт `docs/GO_STANDARD.md` как
единственный источник правил Go-кода: слои, handlers, services, repositories,
modules с обязательными интерфейсами, mapping, protobuf, ошибки, SQL,
транзакции, тесты и именование. В backend `AGENTS.md` оставлены только ссылка
на стандарт, проектные ограничения и операционные команды.
- Проверки: `go test ./...` пройден; `git diff --check` пройден.
### ED-019 — Добавить кнопку экрана в меню организатора
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: в `HeaderMenu.vue` добавлен пункт `Экран` для пользователей с правом `games_page`; пункт ведёт на существующий маршрут `/screen`.
- Проверки: `npm run type-check`, `npm run lint`, `npm run lint:css` пройдены.
### ED-001 — Исправить `actions_count` в `GetGameAnswers`
- Статус: `DONE`
- Репозиторий: `evening_detective_server`
- Результат: `GetGameAnswers` теперь заполняет `Team.ActionsCount` через `GetActionsCountByTeamIDs`; контракт API не изменён.
- Проверки: `go test ./...` пройден; lifecycle-тест проверяет количество ходов в ответе для панели оценки.
### ED-011 — Считать сообщения без тригерной фразы продолжением диалога
- Статус: `DONE`
- Репозиторий: корневые правила агента
- Результат: удалено обязательное ожидание тригерной фразы перед продолжением диалога.
- Проверки: проверены `AGENTS.md` и `docs/agent/README.md`; продуктовый код не затрагивался.
### ED-005 — Исправить сброс настроек игры поллингом
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: настройки редактируются через локальный черновик и не перезаписываются поллингом.
- Проверки: type-check, lint и lint:css пройдены.
### ED-006 — Добавить страницу итогов игры
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: добавлена страница результатов, обработка ошибок и входы из админки и списка игр.
- Проверки: type-check, lint, lint:css и build пройдены.
### ED-007 — Добавить пьедестал победителя на странице итогов
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: добавлены баннер победителя, медали мест 1–3 и обработка ничьих.
- Проверки: type-check, lint, lint:css и build пройдены.
### ED-008 — Добавить создание игры из списка игр
- Статус: `DONE`
- Репозиторий: `evening_detective_frontend`
- Результат: добавлено создание игры из каталога сценариев, выбор даты и времени, отображение даты и исправлена передача RFC 3339 `startAt`.
- Проверки: type-check, lint и lint:css пройдены; build указан в отчёте плана.
### ED-024 — Общая дизайн-система фронтенда и библиотека компонентов
- Статус: `DONE`
- Дата: 14.10.2026
- Репозиторий: `evening_detective_frontend`
- Результат: формализована дизайн-система; по утверждённому плану выделены SiteThemeProvider, CaseFolder, CaseBoard, ObjectCover, StatusStamp, TextHighlight, SectionHeading и DossierFooter; сохранён общий DesignBrand. Образец сайта использует библиотеку, игровые компоненты включены без переработки. Добавлена dev-вкладка «Компоненты» с прямыми импортами, props, slots, событиями и локальными примерами Naive UI; сайт открывается первым, стрелки/Home/End работают для трёх вкладок.
- Поведение: данные обложек и доски передаются родителем; status необязателен и не управляет disabled. Цитаты повторных карточек получают уникальные useId и раскрываются независимо; open обрабатывается локально. Тема сайта изолирована от игры; основные цвета и reduced motion сохранены. В игровом образце добавлен отступ 6 px для выступающих металлических краёв панели.
- Документация: DESIGN_SYSTEM.md дополнен подключением provider и таблицей контрактов. Повторяемый smoke: tests/venue/design_system.py (Vite на 5198, Firefox), инструкция в tests/venue/README.md.
- Проверка: type-check, lint, lint:css, npm run build и git diff --check — успешно. Firefox: 375/768/1280 px, три вкладки, клавиатура, отсутствие переполнения внутренней прокрутки, разные данные, независимые цитаты, уникальность ID, optional status/disabled/loading, форма, окно и возврат фокуса, open, локальный игровой ход, темы, reduced motion. Просмотрены контрольные снимки и вручную проверен diff по FRONTEND_CODE_STANDARD.md. Проверены production-файлы: dev-маршрут и каталог исключены.
- Ограничения: рабочие страницы не мигрировали, игровые компоненты не унифицировали, зависимости не добавляли; commit/push не выполняли. Браузерные проверки выполнены в Firefox, другие браузеры не проверялись.
- Уточнение ED-024: каталог перестроен в последовательные секции «заголовок → живой компонент → описание → код использования» одной колонкой; игровые и Naive UI примеры расположены рядом со своим кодом. Сохранены изоляция тем и локальные действия. Повторно пройдены type-check, lint, lint:css, сборка и Firefox smoke на 375/768/1280 px; diff проверен по стандарту.