Решили: решения про кооп-сессию, дисконнект и реконнект приняты заранее, до кода. В одиночке швы закрыты заглушками (Game/Flow/RunFlowSeams.cs: IReadyGate, SoloReadyGate, SoloPlayerIntentSource), поэтому решения нужно было где-то держать — из заглушки их не прочесть.

  • Ready-gate — переходы, которые ждут всех игроков (все закончили расстановку). Пауза в макро-флоу тогда не отдельный механизм: флоу просто ждёт на гейте.
  • Состав фиксирован в лобби по SteamID, но реконнект поддержан: хост резервирует слот ушедшего и стримит вернувшемуся текущий RunState.
  • Сосуды ушедшего продолжают драться по своему AI-профилю.
  • Автопауза при дисконнекте в бою останавливает тиковый цикл, не макро-флоу. Резолюция на выбор: подождать / продолжить без игрока / выйти в меню.
  • Пауза — это ещё и окно синка: пока она стоит, вернувшегося подтягивают снапшотом RunState плюс сим-снапшотом либо переигровкой лога команд от старта боя.
  • Возобновление — синхронный отсчёт «3…2…1»: хост назначает общий тик старта.

Почему: дисконнект в автобатлере деградирует мягко, и это причина, по которой жанр вообще удобен для кооператива — при прямом управлении юнитами уход игрока даёт паралич, а здесь его Сосуды просто доигрывают на AI. Пауза выбрана окном синка потому, что она уже останавливает тик: другого момента, в котором состояние гарантированно не меняется, в бою нет.

Грабли: два места, где «очевидное» решение ломается. Пауза при дисконнекте обязана иметь опциональный авто-таймаут — иначе бесконечная пауза становится инструментом грифа. И возобновление обязано идти от общего тика старта, назначенного хостом: без него клиенты возобновляются вразнобой, что и есть рассинхрон, которого мы избегали выбором host-authoritative.

Владелец правды: заглушки швов — Assets/_Project/Scripts/Game/Flow/RunFlowSeams.cs; состав работы Фазы MP — Meta - Tech Debt §4; модель — Journal - Host-Authoritative, Not Lockstep.