545 lines
172 KiB
Markdown
545 lines
172 KiB
Markdown
# Завершённые задачи
|
||
|
||
Архив задач, переведённых в статус `DONE`.
|
||
|
||
### ED-058 — Добавить карту и лист оплаты в материалы ведущего
|
||
|
||
- Статус: `DONE`
|
||
- Цель: добавить два согласованных исходных PNG в `Для ведущего/` каждого печатного ZIP.
|
||
- Решение: встроенные ассеты бэкенда, исходные имена и байты; существующие проверки отмены и размера архива.
|
||
- Критерии: оба файла есть в ZIP, в том числе без команд, без преобразования в PDF.
|
||
- Проверка: тесты наличия и точного совпадения байтов, `gofmt`, `go test ./...`, `git diff --check`, ревью Go-стандарта.
|
||
- Ограничения: без обработки изображений, изменений API/UI, физической печати, commit/push.
|
||
- Результат: оба исходных PNG добавляются в `Для ведущего/` с исходными именами для каждой игры. Тесты подтверждают наличие и точные байты файлов, включая игру без команд; копии ассетов сверены с исходниками. `gofmt`, `go test ./...` и `git diff --check` выполнены успешно; diff проверен по Go-стандарту.
|
||
- Ограничения проверки: физическая печать и рабочий сервер не проверялись. Commit/push не выполнялись.
|
||
|
||
|
||
### ED-057 — Заменить дипломы универсальным бланком
|
||
|
||
- Статус: `DONE`
|
||
- Цель: заменить три диплома одним пустым бланком из согласованного PNG.
|
||
- Решение: одностраничный A4 с исходной картинкой целиком, без обрезки и надписей; `Для ведущего/Дипломы/Диплом.pdf`.
|
||
- Критерии: один диплом в ZIP, включая игру без команд; все поля заполняются вручную.
|
||
- Проверка: тесты PDF и архива, визуальная проверка, `go test ./...`, Go-стандарт и `git diff --check`.
|
||
- Ограничения: без автозаполнения, новых зависимостей, изменений API/UI, физической печати, commit/push.
|
||
- Результат: три прежних диплома заменены одним пустым бланком; исходный PNG встроен без изменений. PDF визуально проверен: рамка целиком, поля пустые. `gofmt`, `go test ./...` и `git diff --check` выполнены успешно; diff проверен по Go-стандарту.
|
||
- Ограничения проверки: физическая печать и рабочий сервер не проверялись; исходник около 128 dpi на A4. Предпросмотр: `/tmp/ed057-diploma.pdf`. Commit/push не выполнялись.
|
||
|
||
|
||
### ED-056 — Редактор и офлайн-воспроизведение групп в screen
|
||
|
||
- Статус: `DONE`
|
||
- Репозиторий: `evening_detective_screen`.
|
||
- Цель: редактирование групп только в режиме редактирования, запуск групп в обычном режиме и полное воспроизведение подготовленных групп без сервера.
|
||
- Результат: в редактор добавлены создание, переименование, удаление без удаления треков, режим завершения, перестановка групп и треков внутри группы, перенос треков. Операции используют API ED-055; учитываются запреты активной/приостановленной группы. В обычном режиме — названия и режимы групп, текущая группа, «Играть группу» и возврат к целому плейлисту. Полей и кнопок изменения групп вне редактирования нет.
|
||
- Результат: черновики сохраняются при ошибках, потере связи, внешнем изменении и удалении группы; закрытие с изменениями требует явной отмены. Подтверждённое удаление собственной группы отменяет её черновик. Смена сервера сбрасывает контекст редактора.
|
||
- Результат: локальный пакет, каталог и IPC содержат группы и принадлежность треков; состояние канала хранит groupId. Формат пакета остаётся 1; отсутствующие новые поля не меняют старую форму данных и отпечатки. Метаданные групп входят в новые отпечатки и обнаружение обновлений материалов. Руководство пользователя обновлено.
|
||
- Результат: единая функция переходов используется контроллером, подготовкой следующего файла, командами и офлайн-продолжением. Поддержаны повтор одного/нескольких треков, остановка, следующая непустая группа и остановка в конце списка. При отсутствии файла или неподготовленной группе музыка безопасно останавливается с ошибкой; выход в общий список не выполняется. После восстановления связи применяется серверное состояние даже с прежней версией; офлайн-команды не отправляются задним числом.
|
||
- Результат: обработчики загрузки и завершения защищены от старых операций и сессий. Ожидающий ответ по старой группе не блокирует окончание новой короткой группы. Пауза, продолжение, громкость и ручной выбор сохраняют корректную группу и позицию.
|
||
- Проверено: `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm test` (все 241 тест), `npm run build`, `git diff --check`; после сохранения исходной проверки отмены загрузки дополнительно пройден финальный online.test.js. Проверены парсер, переходы, сохранение/чтение пакетов, отпечатки, API редактора, предзагрузка, ошибки файлов, восстановление связи, устаревшие ошибки и конкурентные окончания.
|
||
- Проверено: Electron — редактор на 1280/375 px, отсутствие элементов редактирования в обычном режиме, запуск, запреты активной группы, режимы, порядок, ошибка создания и повтор, перенос трека, удаление группы с сохранением треков, сохранение черновика офлайн и при удалении извне, подтверждение отмены, офлайн-запуск и отсутствие горизонтального переполнения. Реальный короткий WAV через Controller + MediaPlayer без сервера: повтор, остановка, переход через пустую группу и остановка последней группы. Стенды и снимки находятся в `/tmp/ed056-ui`, аудиостенд — `/tmp/ed056-audio.cjs`.
|
||
- Проверено: ручное ревью целевого diff по существующим паттернам screen, границам IPC/API, сохранению данных и совместимости; независимое статическое ревью ядра, редактора и обработчиков ошибок. Обнаруженные гонки исправлены и покрыты тестами; блокирующих замечаний не осталось.
|
||
- Ограничения: редактирование требует сервера с API ED-055; офлайн используются подготовленные группы и файлы. Новые зависимости, backend API и миграции не добавлялись.
|
||
- Не проверено: звук на физическом оборудовании площадки и установленный релизный пакет. Развёртывание, commit и push не выполнялись; для использования изменений требуется обновить screen.
|
||
|
||
### ED-055 — Группы музыкального плейлиста
|
||
|
||
- Статус: `DONE`
|
||
- Репозитории: `evening_detective_server`, `evening_detective_frontend`; совместимость `evening_detective_screen`.
|
||
- Цель: именованные группы внутри плейлиста с порядком групп и треков, режимами повтор / остановка / следующая группа.
|
||
- Результат: группы создаются, переименовываются, переставляются и удаляются без удаления их треков; треки назначаются группе или остаются без группы. Новая группа повторяется по умолчанию. «Играть группу» сразу запускает первый трек; переход пропускает пустые группы и останавливается в конце списка. Старое воспроизведение всего плейлиста сохранено.
|
||
- Результат: сервер защищает активные и приостановленные группы во всех использующих их играх. Перестановка групп заблокирована до остановки плейлиста; переименование доступно. Выбор следующего трека выполняется под блокировками плейлиста и состояния, запоздавшие/повторные события окончания не перезаписывают новую команду. Переупорядочивание и удаление других треков сохраняют текущий файл и позицию.
|
||
- Результат: редактор сохраняет черновики при обновлении и удалении группы извне; исправлено пересоздание редакторов позиционными обёртками NSpace. Строковые int64 из protobuf JSON учитываются при сравнении версий и вычислении позиции паузы. Добавлены protobuf API и миграция `20261027120000_playlist_groups.sql`; группы, режимы, порядок и переназначенные ID переносятся экспортом/импортом. Старые пакеты без групп поддерживаются.
|
||
- Результат: нативный плеер сохраняет выбранную группу при паузе, продолжении, громкости и повторном запуске трека; повтор единственного трека перезапускает аудио. Управление треками и режимом группы выполняется через сайт. При потере связи выбранная группа останавливается вместо перехода в общий список; отдельный нативный редактор и автономный каталог групп не добавлялись.
|
||
- Проверено: генерация protobuf в трёх репозиториях; `gofmt`; полный `go test ./...` с отдельной PostgreSQL через `TEST_DATABASE_URL`, включая конкурентные окончания, права/ошибки, защиту редактирования, экспорт/импорт и старые пакеты; frontend `type-check`, `lint`, `lint:css`, `build`; native `type-check`, `lint`, `lint:css` и все 218 тестов; `git diff --check`.
|
||
- Проверено: Firefox на 1280/375 px — режим по умолчанию, запуск/пауза/продолжение, запреты редактирования, порядок групп, ошибка создания и повтор, перенос трека, сохранение удалённого извне черновика и отсутствие горизонтального переполнения. Реальный короткий WAV в браузере — повтор одного трека, остановка, переход через пустую группу, повтор запроса после временной ошибки; строковые версии 9→10 и 9007199254740995 передаются точно. Скриншоты и временные стенды оставлены в `/tmp`.
|
||
- Проверено: ручное ревью diff по `GO_STANDARD.md` и `FRONTEND_CODE_STANDARD.md`; независимое статическое ревью блокировок, согласованности каталога и сохранения черновиков. Блокирующих замечаний не осталось.
|
||
- Не проверено: звук на физическом оборудовании площадки и развёртывание. Production-миграция не выполнялась; для включения функции нужны миграция БД и обновление сервера/клиентов. Commit/push не выполнялись.
|
||
|
||
### ED-053 — Инструкция перед QR команды
|
||
|
||
- Статус: `DONE`
|
||
- Цель: в PDF и чеках сначала краткая инструкция Wi-Fi, затем QR, ниже название команды; предпросмотр соответствует чеку.
|
||
- Критерии: текст помещается при предельных длинах, QR сохраняет размер и читаемость; без Wi-Fi печатаются QR и название. API и настройки не меняются.
|
||
- Проверка: тесты рендеринга, просмотр образцов и декодирование QR; `gofmt`, `go test ./...`, ручное ревью по GO_STANDARD.md.
|
||
- Результат: общий текст сокращён до подключения к сети, пароля, напоминания остаться без интернета и сканирования QR. В PDF, чеках и предпросмотре инструкция сверху, затем QR, ниже название команды. При пустой сети — QR и название; размеры QR сохранены.
|
||
- Проверено: `gofmt`, `go test ./...`, целевые тесты печати (включая предельные длины и регрессию порядка QR/названия), `git diff --check`; ручное ревью diff по GO_STANDARD.md. Образцы PDF и чека просмотрены; три QR из PDF/PNG декодированы `zbarimg`.
|
||
- Не проверено: физическая печать и сканирование телефоном на площадке. Commit/push не выполнялись.
|
||
|
||
|
||
### ED-052 — Печатать инструкцию подключения к Wi-Fi рядом с QR команды
|
||
|
||
- Статус: `DONE`
|
||
- Цель: название сети и пароль задаются в настройках каждой игры и печатаются в PDF и чеках, включая предпросмотр.
|
||
- Решение: при пустом названии сети инструкция отсутствует; пустой пароль означает открытую сеть. Печать доступна онлайн и на площадке. Настройки переносятся в пакете игры и доступны для редактирования только управляющим игрой.
|
||
- Критерии: настройки сохраняются и очищаются; старые клиенты не стирают их; старые пакеты импортируются; текст помещается, QR читается. PDF с Wi-Fi содержит шесть карточек на листе.
|
||
- Проверка: тесты хранения, прав, экспорта/импорта, валидации и рендеринга; `go test ./...`; генерация protobuf; frontend type-check, lint, lint:css и build; ручное ревью стандартов.
|
||
- Ограничения: без Wi-Fi QR, новых зависимостей, commit и push. Проверка физического принтера и телефонов отдельно на площадке.
|
||
- Результат: добавлены поля игры, миграция `20261023120000_game_wifi.sql`, optional-поля обновления и форма с маскированным паролем. Параметры возвращаются только управляющим игрой; игрокам и в списки не выдаются. Старый клиент сохраняет настройки, явные пустые значения очищают их.
|
||
- Результат: PDF содержит 6 карточек при заданной сети, чек и его предпросмотр включают одинаковую инструкцию. Текст переносится, длинное название команды на чеке уменьшается при необходимости; размер QR сохранён. Пустая сеть отключает инструкцию, пустой пароль обозначает открытую сеть. Экспорт/импорт переносит параметры без изменения версии пакета; старые пакеты совместимы.
|
||
- Проверено: ручное ревью всего diff по `GO_STANDARD.md` и `FRONTEND_CODE_STANDARD.md`, `gofmt`, `git diff --check`; `make generate`, `npm run proto:gen`; `go test ./...` с отдельной PostgreSQL (включая реальные миграции, сохранение/очистку, старых клиентов и экспорт→импорт); `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build` — успешно.
|
||
- Проверено: браузерный smoke на 390 и 1440 px — загрузка полей, маскировка пароля, валидация, сохранение пробелов пароля, ошибка сервера, защита от повторной отправки и очистка. Образцы PDF и чеков просмотрены, 8 QR из PDF и PNG успешно декодированы `zbarimg`; предельные длины покрыты тестами.
|
||
- Ограничения проверки: физический принтер, телефон и подключение к реальному Wi-Fi не проверялись. Рабочая БД и серверы не обновлялись; при запуске нужна миграция. Для изменения уже подготовленного офлайн-пакета требуется новый экспорт. Commit/push не выполнялись.
|
||
|
||
|
||
### ED-051 — Перенести идеи пульта во вкладку «Экраны»
|
||
|
||
- Статус: `DONE`
|
||
- Цель: перенести согласованные идеи `evening_detective_screen` на вкладку «Экраны» страницы игры.
|
||
- Результат: предпросмотр и подключение экранов расположены сверху; ниже адаптивные колонки плана экранов и музыки. Добавлены миниатюры всех шагов, выделение текущего шага, компактные кнопки и ползунки громкости; перемотка удалена.
|
||
- Результат: редактор музыки отделён от управления воспроизведением. Создание, переименование, загрузка MP3, удаление и перестановка треков используют ID редактируемого плейлиста. Назначение музыки игре выполняется явно; черновики сохраняются при поллинге и ошибках, конфликты внешних изменений показываются пользователю.
|
||
- Результат: пауза, продолжение и громкость основного медиа сохраняют позицию; повтор текущего музыкального трека обрабатывается проигрывателем. Устаревшие ответы поллинга музыки не перезаписывают команды. Добавлены проверки ввода таймера, текста и MP3, блокировка повторных запросов и сообщения об ошибках.
|
||
- Проверено: `node tests/screens-control.mjs`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build-only`, `git diff --check` — успешно. Diff вручную проверен по FRONTEND_CODE_STANDARD.md.
|
||
- Проверено: Firefox на 1280 и 375 px, отсутствие горизонтального переполнения и автозапуска медиа миниатюрами, таймер и музыка, громкость мышью и клавиатурой, черновик плана после поллинга, независимый выбор плейлиста, ошибка сохранения порядка и повтор, переименование, отключение экрана и ошибка API. Браузерные проверки выполнены на локальных синтетических ответах API.
|
||
- Ограничения: сервер, protobuf, Electron и зависимости не изменялись. Реальный внешний дисплей и production не проверялись; предпросмотр отражает данные API, без точного прогресса и подтверждённого состояния медиапроигрывателя. Commit/push не выполнялись.
|
||
|
||
### ED-049 — Оптимизировать медиа пакета локальной игры
|
||
|
||
- Статус: `DONE`
|
||
- Цель: уменьшать фото, аудио и видео при подготовке ZIP, сохраняя исходники в хранилище.
|
||
- Решение: WebP quality 85, MP3 128 кбит/с, MP4 H.264 CRF 23/AAC 128 кбит/с; фото и видео до 1920 пикселей по длинной стороне без увеличения. PDF и анимации не менять; при ошибке или увеличении веса брать исходник.
|
||
- Критерии: корректные ссылки, MIME и хеши, дедупликация, импорт версии 2, отмена и очистка временных файлов. FFmpeg установлен в серверных образах.
|
||
- Проверка: табличные тесты с реальным FFmpeg, `go test ./...`, ручное ревью по GO_STANDARD.md, проверка образов и браузерный smoke при доступности среды.
|
||
- Ограничения: API, БД, исходники и готовые ZIP не менять; текущие лимиты сохранить; commit/push не выполнять.
|
||
- Результат: преобразование выполняется последовательно во временной папке; до двух минут на файл и двух потоков FFmpeg. Сетевые протоколы запрещены; исходники, готовые ZIP и лимиты сохранены. Документация пакета обновлена.
|
||
- Проверено: `gofmt`, `go test ./...`, `git diff --check` в затронутых репозиториях — успешно. Diff вручную проверен по GO_STANDARD.md. Табличные тесты с реальным FFmpeg проверяют горизонтальные и вертикальные фото/видео, отсутствие увеличения, прозрачность, длительность, стерео, видео со звуком и без, PDF/GIF/APNG/анимированный WebP, fallback при ошибке/отсутствии утилит/увеличении размера, отмену процесса и очистку временных результатов. Pack/Unpack версии 2 проверяет ссылки и хеши.
|
||
- Проверено: собраны оба Docker-образа, доступны ffprobe и кодеки libwebp/libmp3lame/libx264/AAC. Firefox отобразил прозрачные WebP и воспроизвёл MP3/MP4, извлечённые из подготовленного пакета.
|
||
- Примеры на синтетических материалах: фото 8 371 804 → 1 265 320 байт; аудио 352 878 → 33 061 байт; видео 1 113 441 → 308 962 байта.
|
||
- Не проверено: production и реальные дела; DB-интеграционные тесты без TEST_DATABASE_URL пропущены штатно. FFmpeg увеличивает размер серверного образа; сжатие с потерями может ухудшить различимость мелких деталей. Commit/push не выполнялись; существовавший изменённый backend-бинарник не перезаписывался.
|
||
|
||
### ED-048 — Очистка локальной площадки
|
||
|
||
- Статус: `DONE`
|
||
- Репозиторий: корневой workspace.
|
||
- Цель и результат: добавлена `make venue-clean`; без подтверждения останавливает venue, удаляет внутренние и внешние тома данных и оставляет сервер остановленным. Повторная очистка допустима; ошибки Docker не скрываются.
|
||
- Сохраняются: `.env`, сертификаты, настройки Cudy, сборка, Docker-образы и окружение разработки. Следующий `make venue` создаёт пустую БД и организатора из `.env`.
|
||
- Проверки: `python3 tests/venue/clean.py`, `bash -n venue/clean.sh`, `make -n venue-clean`, `git diff --check` — успешно. Тест проверяет порядок команд, повторный вызов, ошибки Docker, сохранность файлов и посторонних томов. Ручное ревью diff выполнено; стандарты Go/Vue неприменимы, код дочерних репозиториев не изменён.
|
||
- Не проверено: удаление реальных Docker-томов; рабочие данные не затронуты. Commit/push не выполнялись.
|
||
|
||
### ED-047 — Сброс локального режима и повторная подготовка пакета
|
||
|
||
- Статус: `DONE`
|
||
- Репозитории: `evening_detective_server`, `evening_detective_frontend`.
|
||
- Цель: вернуть игру на prod из локального режима с подтверждением без загрузки результатов; разрешить новый пакет при любом статусе игры и экспорта.
|
||
- Решение: сохранять готовые экспорты для последующей загрузки результатов; новый пакет — актуальная подготовка к игре с нуля, без изменения исходного прогресса. Отменять устаревшую незавершённую подготовку.
|
||
- Критерии: подтверждение/отмена, исчезновение отметок и подсказки игроку, защита от устаревшего сброса, новый пакет для всех статусов и форматов, старые результаты принимаются.
|
||
- Проверка: PostgreSQL-тесты экспорта/возврата и миграции, `go test ./...`, генерация API, type-check, оба линтера, сборка фронтенда, браузерный smoke, ревью стандартов.
|
||
- Ограничения: без экспорта из venue, переноса прогресса, автоматической замены импортированной игры, commit/push.
|
||
- Результат: добавлены RPC/REST сброса с ожидаемым ID экспорта, модальное подтверждение и блокировка повторной отправки. Снятие режима сохраняется в `released_at`; карточка, страница управления и подсказка игрока обновляются через существующее чтение. Готовые архивы доступны для поздних результатов; незавершённые попытки отменяются с fencing worker-а. Каждая подготовка создаёт новый снимок при любом статусе/формате игры; пакет нормализуется в черновик без прогресса. Обновлены protobuf-клиенты, README и тестовые схемы.
|
||
- Проверено: `make generate`, `npm run proto:gen`, `go test ./...` с отдельным PostgreSQL на порту 55447, `go test -race ./internal/repos/game_exports_repo ./internal/services/game_export_service`, `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`, `git diff --check` — успешно. Миграция проверена вперёд/назад; откат с несовместимой историей готовых пакетов отказывает без потери данных. Diff вручную проверен по обоим стандартам; новые тесты используют публичные методы сервисов/репозиториев.
|
||
- Браузерный smoke Firefox с тестовым API: desktop/mobile, подтверждение/отмена, ошибка/повтор, блокировка кнопок, сохранение сброса после перезагрузки, новая подготовка для всех статусов игры и экспорта, список игр и обновление подсказки игрока поллингом, скрытие операций в venue — успешно. PostgreSQL-тесты подтверждают реальный импорт черновика, неизменность исходной игры, поздние результаты и конкуренцию сброса/замены/возврата.
|
||
- Не проверено: развёртывание и ручной сценарий на рабочей площадке. Перед запуском нового backend требуется миграция `20261017120000_release_game_exports.sql`. Commit/push не выполнялись.
|
||
|
||
### ED-046 — Подсказка игроку о локальной сети
|
||
|
||
- Статус: `DONE`
|
||
- Репозиторий: `evening_detective_frontend`
|
||
- Цель: на странице игрока показывать «Подключитесь к Wi-Fi организатора и обновите страницу.» при открытии онлайн-сервера для игры с готовым офлайн-пакетом.
|
||
- Критерии: подсказка сверху независимо от статуса игры; скрыта на локальном сервере, при отсутствии пакета или его подготовке; обновляется существующим поллингом.
|
||
- Ограничения: без изменений API, бэкенда и автоматического переключения сервера.
|
||
- Проверка: `npm run type-check`, `npm run lint`, `npm run lint:css`; ревью diff по стандарту фронтенда.
|
||
- Результат: при prod/ready страница игрока показывает только красный n-alert «Подключитесь к Wi-Fi организатора и обновите страницу.»; фон дела, ввод хода, игровые блоки, QR, панель автора и отзыв скрыты. Условие вынесено в computed; используются существующие uiStore и данные игры. API и бэкенд не менялись.
|
||
- Проверка отдельного экрана: `npm run type-check`, `npm run lint`, `npm run lint:css`, сборка в `/tmp/ed046-red-dist`, `git diff --check` — успешно; diff проверен по стандарту фронтенда. Браузерный smoke с тестовыми ответами API подтвердил красное оформление, отсутствие игрового содержимого и фона, единственный текст для draft/run/pause/finish, обычную страницу для venue и без готового пакета, обновление поллингом, desktop/mobile.
|
||
- Исправление: при прямом открытии страницы игрока uiStore.environment оставалась null, поскольку загрузка выполнялась только в отсутствующем здесь HeaderMenu. Добавлен вызов uiStore.load() с обработкой ошибки на странице игрока.
|
||
- Проверка исправления: `npm run type-check`, `npm run lint`, `npm run lint:css`, сборка в `/tmp/ed046-dist`, `git diff --check` — успешно; ручное ревью по стандарту фронтенда выполнено. Браузерный smoke с тестовыми ответами API подтвердил прямой вход без меню, показ для prod/ready, скрытие для venue, preparing и отсутствующего пакета, появление после поллинга; desktop и mobile.
|
||
- Проверено: `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 проверен по стандарту.
|
||
|
||
### ED-050 — Объединить текстовые типы экранов
|
||
|
||
- Статус: `DONE`
|
||
- Результат: «Успехов» и «Спасибо за игру» удалены из API, UI сайта и приложения экрана; остался общий режим «Текст». Номера и имена удалённых protobuf-значений зарезервированы, API перегенерирован штатными командами.
|
||
- Совместимость: миграция `20261019120000_merge_text_screen_modes.sql` переводит планы и состояния в режим 8 с прежними надписями; копия добавлена в `prod/migrations`. Старые скачанные пакеты проверяются по исходному хешу, затем шаги преобразуются при загрузке в каталог; локальные планы преобразуются при чтении. Новые команды с режимами 3 и 5 отклоняются.
|
||
- Проверка стандартов: весь diff вручную проверен по GO_STANDARD.md и FRONTEND_CODE_STANDARD.md; gofmt и git diff --check прошли.
|
||
- Автоматические проверки: `go test ./...`; фронтенд — `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`; приложение экрана — те же проверки, сборка и `npm test` (203/203). Миграция проверена дважды на временных таблицах PostgreSQL: надписи, порядок, текущий шаг, неизменность остальных шагов и повторный запуск корректны.
|
||
- GUI: целевой проход восьми шагов Electron завершился `ED050_TEXT_SCREENS_PASS [1,2,8,4,8,6,7,8]`; обе надписи проверены в DOM. Общий smoke не завершился: `Timeout: volume slider keyboard update`; устаревшие ожидания автопаузы музыки в нём исправлены, код проигрывателя не менялся.
|
||
- Ограничения: production-миграция не запускалась; сервер, сайт и приложение экрана требуют согласованного обновления. Коммиты и push не выполнялись.
|
||
|
||
### ED-054 — QR-экран, список команд и типы таймера
|
||
|
||
- Статус: `DONE`
|
||
- Результат: добавлены режимы QR (ссылка HTTP/HTTPS и необязательный текст) и списка команд; три типа таймера с исходной надписью и сохранением пользовательского текста при смене типа. Настройки доступны в веб-панели и приложении экрана, работают предпросмотры и браузерный вывод `/screen`.
|
||
- Команды: только названия активных регистраций, по русскому алфавиту; обновление каждые пять секунд, сохранение последнего снимка по ключу игры в приложении экрана, восстановление без сети после перезапуска. При ошибке предыдущий список сохраняется; при смене игры очищается.
|
||
- Совместимость: старые планы и хеши офлайн-пакетов сохранены, таймеры без типа означают «Перерыв» без замены собственного текста. Исправлена инициализация общего состояния таймера при первом подключении к шагу без длительности. Новый `GetScreenTeams` передаёт токен в теле POST; ответ содержит только ID и название.
|
||
- Миграция: `20261023130000_screen_qr_timer_type.sql` добавлена в сервер и `prod/migrations`; на рабочей БД не применялась.
|
||
- Проверки: штатная генерация protobuf во всех трёх приложениях; `go test ./...`; интеграционные тесты PostgreSQL для экранов, миграций и команд; 208 тестов приложения экрана; type-check, lint, lint:css и сборки обоих Vue-приложений; `node tests/screens-control.mjs`; Electron smoke предпросмотров 1280×720 / 1024×768 с QR и 32 длинными названиями; QR декодирован со снимка; Firefox smoke QR на ширинах 1280/375/160, списка и реального `/screen` с тестовыми API-ответами. Проверены ошибки сети, старые пакеты, сохранение снимка и изоляция игр. Diff вручную проверен по стандартам Go и фронтенда, `gofmt` и `git diff --check` — без замечаний.
|
||
- Ограничения: новые анимации отложены по согласованию; реальный проектор не проверялся. Публикация, commit и push не выполнялись.
|
||
|
||
### ED-059 — Отдельная страница плейлистов
|
||
|
||
- Статус: `DONE`
|
||
- Цель: `/playlists` для авторов и организаторов с текущими операциями; редактор в игре сохраняется и переиспользуется.
|
||
- Критерии: общий редактор и API-действия; защита черновиков; состояния загрузки, ошибки, пустого списка и отсутствия доступа; пункт меню.
|
||
- Проверка: type-check, lint, lint:css, build; smoke операций и регрессии музыки в игре.
|
||
- Ограничения: без новых зависимостей, API и предпросмотра звука; без commit/push.
|
||
- Результат: добавлены `/playlists` и пункт меню для авторов/организаторов; редактор и API-действия общие со страницей игры. Сохранены операции, MP3-валидация, блокировки, синхронизация и черновики; добавлено подтверждение ухода. API и зависимости не менялись.
|
||
- Проверено: `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`, `git diff --check`; ручное ревью diff по FRONTEND_CODE_STANDARD.md. `python3 tests/venue/playlists.py` прошёл: ошибка/повтор, пустой список, создание/выбор/переименование/удаление, пустой MP3 и загрузка, порядок и группы, отказ сохранения с сохранением черновика, роли, route guard, клавиатура, 1280/375 px. Отдельный браузерный smoke музыки в игре прошёл: play/pause/resume, активная группа, режимы, порядок, ошибки, черновик удалённой группы, 1280/375 px.
|
||
- Ограничения проверки: браузерные тесты используют изолированный тестовый API; рабочий сервер и реальное воспроизведение MP3 не проверялись. Commit/push не выполнялись.
|
||
|
||
### ED-060 — Загружать MP3 сразу в нужную группу
|
||
|
||
- Статус: `DONE`
|
||
- Цель: кнопка загрузки в каждой группе общего редактора; трек сразу сохраняется в выбранной группе.
|
||
- Критерии: единый запрос и транзакция вставки с groupID; проверка принадлежности и активности группы; совместимость старых запросов без groupID; обе страницы.
|
||
- Проверка: Go-тесты, интеграционная проверка PostgreSQL, генерация API, type-check, lint, lint:css, build и браузерный smoke.
|
||
- Ограничения: без новых зависимостей, миграций, пакетной загрузки и commit/push.
|
||
- Результат: «Добавить MP3» находится в каждой группе, включая «Без группы», на странице плейлистов и внутри игры. `groupID = 5` передаётся одним запросом; repository проверяет группу и её использование под существующей блокировкой и атомарно вставляет трек с группой. Запросы без поля сохраняют прежнюю загрузку без группы; очистка файла при отказе остаётся в существующем service flow. Обновлены все callers и generated API.
|
||
- Проверено: `make generate`, `npm run proto:gen`, `gofmt`, `go test ./...`; полный набор тестов `playlists_repo` с `TEST_DATABASE_URL` на отдельной локальной PostgreSQL прошёл, включая пустую/заполненную/чужую/удалённую/активную группу и отсутствие вставки при отказе. `npm run type-check`, `npm run lint`, `npm run lint:css`, `npm run build`, `git diff --check` прошли; diff проверен по Go- и frontend-стандартам.
|
||
- Браузер: `python3 tests/venue/playlists.py` — прямое назначение группы одним запросом, отказ сервера с сохранением черновика, операции редактора и 375/1280 px. Дополнительный игровой smoke `/tmp/ed060-game-upload-browser.py` — загрузка в группу через GameMusicPlanPanel, блокировка активной группы, доступность другой группы и регрессия воспроизведения/групп/черновиков.
|
||
- Ограничения проверки: браузер использует изолированный API; рабочее файловое хранилище и звучание MP3 не проверялись. Новому фронтенду для назначения группы нужен обновлённый бэкенд. Commit/push не выполнялись.
|