ADR-0014 · Каталог ботов «сыграть с человеком» — ленивое создание игры по клику

Статус: предложено · 2026-07-23 (эпик play-api + SPA, issue TBD). Развивает ADR-0009 (Bot-API), опирается на ADR-0013 (webhook) и ADR-0010 (тиры идентичности).

Контекст. Serverless/webhook-боты на Cloud Run со scale-to-zero (gcp/expectimax-onnx-3, gcp/scala-monte-carlo, cloudflare) не могут держать постоянный лоббийный seek: у seek’а TTL (~2 мин, Lobby), его надо поллить и перевыставлять, а у scale-to-zero процесса нет фонового цикла — он просыпается только на входящий вебхук. House-боты держат стендинг-сики только потому, что это всегда-живые процессы. При этом play-api уже доставляет ходы на вебхук для любой игры, где место занял бот (Webhooks-deliverer), независимо от того, как игра создана. Значит «организатор игры» существует — не хватает лишь ленивого триггера от человека, дружащего со scale-to-zero.

Решение. Каталог доступных ботов + ленивое создание игры по клику. Бот помечается флагом open_to_humans (независим от on_ladder); каталог = выборка по флагу, живой seek не держим. Человек кликает бота → play-api будит его handshake’ом (scale-to-zero просыпается) и проверяет живость → человек конфигурирует игру → play-bot сажает игру гость+бот через существующую GameRegistry.create; вебхук-deliverer дальше гоняет ходы сам. Keeper’ы/стендинг-сики для этих ботов не нужны.

Детали:

  • Флаг open_to_humans (миграция + store). Ставится и ботским токеном (POST /bot/open-to-humans, как ladder-join), и админ-путём — админ-путь обязателен: покрывает ботов без сохранённого токена (напр. expectimax-onnx-3).
  • Поле description у бота — для карточки каталога (алгоритм/платформа).
  • Эндпоинты: GET /lobby/bots (каталог: team/name/rating/rd/provisional/description); POST /lobby/bots/{team}/{name}/wake (handshake → {alive}, кэш ~30–60 c, щедрый таймаут под cold start); POST /lobby/play-bot {team,name,timeControl,color} (гостевой; timeControl обязателен, Unlimited отклоняется).
  • Конфиг игры: время (обязательно) — пресеты 1m+1s, 3m+3s, 5m, 5m+5s (дефолт), 10m, 10m+10s (микс Fischer/SuddenDeath); цвет Random (деф.) / White / Black; стартовый DFEN — форвард-совместимый параметр на будущее (нужна поддержка старта комнаты из произвольного DFEN — вне MVP).
  • UX: панель конфига показываем сразу (с дефолтами), кнопку «Старт» активируем по alive — человек выбирает опции, пока бот холодно стартует (JVM+ONNX ~секунды); задержку 1-го хода прячем pre-warm’ом (handshake на клике) и статусом «бот просыпается…».
  • Лимит: 1 живая human-vs-bot игра на гостя (bounds Cloud Run от спама).

Границы MVP. House-ботов не мигрируем — их open-tables/сики оставляем как есть, пока нет живого трафика (так проще; объединение с каталогом — позже). Каталог наполняем вебхук-ботами (у них сейчас вообще нет способа звать людей). DFEN-старт — позже. Переключение >1 игры у гостя — позже (пока лимит 1; понадобится список «мои активные игры» + навигация).

Последствия.

  • Ноль работы в простое для serverless-ботов: бот молчит, пока не кликнули; cold start на 1-м ходу поглощают часы. Без keeper’а/Scheduler’а и без per-op токен-возни (у стендинг-сика токен нужен на каждый перевыпуск).
  • Liveness-по-клику: игру против уснувшего/мёртвого бота не сажаем (нет форфейтов на старте).
  • Масштабируется: каталог из N ботов в простое = $0; N стендинг-сиков требовали бы N keeper’ов.
  • Цена: продуктовая фича play-api + SPA (сервер + фронт), не правка ботов — боты уже готовы (вебхук играет любую игру). Разбиваем на маленькие PR-ы.
  • Двойной способ выставить флаг оставляет админ-путь как обязательный (решает кейс expectimax-onnx-3 с утерянным токеном).

Альтернативы (отклонены).

  • Стендинг-сик + Cloud Scheduler keeper на каждого serverless-бота — работает и play-api не трогает (быстрый тактический шаг), но: платный per-op токен, фантомные столы против уснувших ботов, N keeper’ов + N Scheduler-джоб на N ботов. Годится как временная мера, не как модель.
  • --min-instances 1 + in-process keeper (как house-боты) — простой код, но выходит из always-free: инстанс крутится 24/7 и тарифицируется.
  • Не звать людей вовсе (только ладдер) — теряем human-vs-bot для serverless-ботов; те же веса человек может сыграть лишь через house-стол (oracle v3).

🔗 08-Reyting-botov-i-webhook-plan-vypolneniya · ADR-0009-Bot-API-i-turniry · ADR-0010-Anonimnye-self-service-boty · ADR-0013-Sinhronnyy-webhook-dlya-botov · 00-Zhurnal-resheniy-ADR