Сейчас посмотрю, что у вас есть в репозиториях, и сделаю обзор всех четырёх проектов.

Все четыре обзора готовы. Перед тем как писать итог, проверю одно критичное утверждение — что в dicechess-lab закоммичен .env с секретами.

Баг подтверждён: Player.rating_classic используется в players.py:28, но в модели Player такого поля нет — эндпоинт GET /api/players упадёт с AttributeError при первом же вызове.

Вот итоговое ревью всех четырёх проектов.


Ревью экосистемы Dice Chess

Общий вердикт: у вас сложилась цельная и грамотно спроектированная экосистема из четырёх проектов с ясным разделением ролей: lab (продукт-тренажёр + ETL с dicechess.com) → engine (правила и боты) → analytics (PostgreSQL-хранилище для массового анализа) → analytics-ui (визуализация). Инженерная культура высокая: типизация везде, CI/CD, документация, миграции. Главные слабые места — аналитика без тестов и со сломанным эндпоинтом игроков, дублирование FEN-логики между проектами и отсутствие глубокого стохастического поиска в движке.

Кстати, в Repositories есть ещё dicechess-bots и dicechess-extension — их я не смотрел, скажите, если нужно.

1. dicechess-lab — зрелый, активный, в хорошей форме

Самый большой проект: ~1500 коммитов с марта, FastAPI + SQLite (WAL) + Svelte 5 PWA, деплой на Raspberry Pi, гейтированный пайплайн staging → production. Бэкенд ~5.5k строк с паттерном Repository, ~2.8k строк тестов; фронтенд с Vitest + Playwright. Документация на Astro/Starlight, версия v0.2.0 с роадмапом до v1.0.

Что стоит поправить:

  • Высокая цикломатическая сложность в game_sync.py (CC≈14) и routers/share.py (CC≈12) — это ваш ETL и шаринг, самые рискованные места для багов.
  • Конфликт peer-зависимостей vite-plugin-pwa ↔ Vite 8 закрыт флагом --legacy-peer-deps — мина под будущие обновления.
  • Возможные N+1-запросы в роутере игроков (на Raspberry Pi с SD-картой это чувствительно) — стоит проверить selectinload в repositories/players.py.

Один из агентов заявил «критическую утечку секретов в git» — я это проверил, и это неправда: backend-api/.env корректно игнорируется, в репозитории только .env.example и .env.staging с плейсхолдерами. Тревога ложная, но добавить detect-secrets в pre-commit всё равно дёшево и полезно.

2. dicechess-engine-scala — технически сильный, но поиск пока «жадный»

Scala 3.8, кросс-компиляция JVM + Scala.js, magic bitboards, opaque types, 85% покрытия с жёстким порогом в CI, JMH-бенчмарки, тест/код ≈ 0.94. Полная генерация ходов, правило максимума микро-ходов, DFEN-парсер, JS API из 10 функций, интегрированный с PWA на dc.jc.id.lv. Очень добротная работа.

Слабые места:

  • Все 6 ботов — жадные эвристики. Expectiminimax/MCTS из роадмапа (Phase 4) не реализован. Самый умный бот (PrudentSearch, экспериментальный) лишь оценивает вероятность взятия короля/ферзя по 216 исходам костей на один ход вперёд.
  • sys.error в TurnGenerator.scala:99 — защитная паника роняет движок (в том числе в браузере) вместо graceful-ошибки. Стоит заменить на Either до массового self-play.
  • queenCaptureProbability не учитывает правило максимума микро-ходов и завышает вероятность — PrudentSearch из-за этого может недооценивать ферзя.

3. dicechess-analytics — правильная архитектура, но v0.2 не дотянута

PostgreSQL 18 + FastAPI + Alembic, грамотная схема: games / turns / positions (дедупликация по нормализованному FEN + xxhash64) / players / game_events. Импортёр из SQLite лаборатории работает батчами с ON CONFLICT. Документация и роадмап (v0.1 готов, v0.2 в работе) — на месте.

Проблемы по убыванию важности:

  1. Сломан GET /api/players — сортировка по несуществующему Player.rating_classic (players.py:28, schemas.py:25). Подтверждено мной — это рантайм-AttributeError. Рейтинги живут в games.white_rating/black_rating, у игрока поля нет.
  2. Тестов нет вообще — для проекта, чья ценность в корректности данных, это главный риск. Баг №1 как раз иллюстрация: один smoke-тест на каждый эндпоинт его бы поймал.
  3. Импортёр — монолит на 749 строк (importer.py) с хрупкими эвристиками: границы ходов определяются по броскам костей, события (дабл/ничья) реконструируются догадками, termination захардкожен как "unknown". Парсинг FEN без валидации.
  4. Три отдельных database engine (database.py, api/dependencies.py, синхронный в импортёре) — стоит централизовать.
  5. Нет POST /api/games — без него движок и боты не смогут лить партии напрямую (заявлено в v0.2).

4. dicechess-analytics-ui — бодрый старт, правильный скелет

Svelte 5 + Vite + Tailwind 4, Chessground, 7 тем, Docker с nginx-прокси на API. За первый день: рабочий список партий с пагинацией и полноценный просмотрщик — доска, кости с отметкой использованных, история ходов, плейбек с клавиатуры. Для одного дня — отличный результат, ~1.9k строк.

Риски:

  • activeGameStore на 493 строки без тестов — реконструкция состояний из turns/events (многоэтапный парсинг, интерливинг событий) — самое сложное и самое непокрытое место. Сюда первым делом нужны юнит-тесты с проверкой непрерывности: state[i].fen == applyMove(state[i-1].fen, move).
  • Собственный fenHelper.ts применяет ходы псевдолегально без валидации — если бэкенд пришлёт кривые данные, доска молча покажет неверную позицию. И это уже третья реализация FEN/ходов в экосистеме (после движка и lab).
  • Нет retry/восстановления при ошибках API, заглушки вместо Openings/Players/Analytics.

Сквозные наблюдения

  1. Логика правил Dice Chess размазана по четырём местам: Scala-движок (эталон), @rabestro/dicechess-engine npm-пакет в lab, fenHelper.ts в UI, FEN-эвристики в импортёре analytics. Движок уже компилируется в Scala.js — UI и импортёр могли бы валидировать через него, а не дублировать.
  2. Данные текут через хрупкое звено: SQLite лаборатории → синхронный импортёр с догадками → PostgreSQL. Любая ошибка эвристики тиражируется на миллионы строк и потом ломает UI.
  3. Тесты распределены обратно пропорционально риску: движок — 85%+, lab — ~50%, а analytics (источник истины для всей аналитики) — 0%.

Если коротко, что чинить первым

  1. rating_classic в analytics (минуты) + базовый pytest-набор на API и импортёр.
  2. sys.errorEither в TurnGenerator движка.
  3. Тесты на activeGameStore.reconstructStates() в UI.
  4. Решить стратегически: движок как единственный источник правил (через Scala.js-пакет) для UI и валидации в импортёре.

Это было ревью «что есть». Следующий ваш вопрос — «как двигаться дальше» — заслуживает отдельного разговора: тут есть развилка между «углубить аналитику» (позиционная статистика v0.3, opening explorer — то, ради чего БД и затевалась) и «поумнить движок» (expectiminimax), и они друг друга усиливают: сильному боту нужна статистика позиций, а аналитике — оценка движка. Скажите, в какую сторону вам интереснее, и я помогу спланировать.