Решили: DeploymentController регистрируется только у владельца сеанса.
Почему: расстановку поднимает пресет боя, а у гостя пресета не бывает — бой приезжает лентой. То есть у гостя контроллер не мог сделать ничего полезного, но успевал сделать вредное: на старте перехватывал ключ гейта готовности и кнопку «Начать», а нажатие уводил в собственную проверку «мы вообще в расстановке?» и тихо выходил. Кнопка была живой на вид и мёртвой на деле.
Грабли — в очерёдности, и она же прятала баг. Обе привязки (моя, по фазе, и его, на старте) пишут в одно поле. В кампании последней ложилась моя, и готовность работала; на Ристалище последним вставал он, и та же кнопка умирала. Один и тот же код вёл себя по-разному в двух режимах, и это читалось как «на Ристалище что-то ещё сломано».
Нашлось только логом с двух машин: у гостя пять раз подряд «кнопка нажата → обработчик привязан» и ни одной строки «своё согласие». То есть обработчик был чужой. Три прогона вдвоём до этого искали причину рассуждением — и каждый раз мимо.
Правило, которое из этого стоит держать: если у объекта в чужой роли нет ни одной работы, он не должен создаваться. «Пусть висит, всё равно спит» — неверно: он не спит, он занимает общие точки привязки.
Отсюда же становится видно, что у гостя нет кругов-опор, драга бойцов и драга реликвии из инвентаря:
всё это ведёт тот же контроллер. Это одна незакрытая работа (гостевая расстановка), а не три бага —
и она записана в docs/player-capability-registry.md вместе с остальными пустыми клетками
синхронизации.
Владелец правды: Game/CombatLifetimeScope.cs (условие регистрации и комментарий при нём),
docs/player-capability-registry.md.