Решили: заведён скоуп Сессии — сеанса владения состоянием игры. SessionHost в корне открывает его от мира на старте (GameBootstrap, роль Owner) и переоткрывает при смене владельца. Внутрь уехали RunStateService и шина команд забега (RunCommandLog / Applier / Bus). Мероприятие теперь рождается ОТ сессии, а не от мира, поэтому и оно, и бой видят состояние и роль.

Почему роль решает состав, а не проверка: SessionInstaller ветвится по SessionRole один раз. У владельца есть держатель забега и шина; у гостя их нет в контейнере вовсе — он играет в чужом сейве, и «случайно записать» ему нечем. Это сильнее любого if (IsHost): проверку можно забыть, а отсутствующую регистрацию не позовёшь. Гостевая ветка сегодня пуста намеренно — класть в неё заглушку «как будто владелец» значило бы завести ровно тот обход, ради запрета которого сессия и делится по роли.

Читателям отдали только чтение. Долгожители (корневой UI, мир, показ карты) держали ссылку на RunStateService полем — она пережила бы своего владельца. Теперь у них IRunStateView с одним свойством Current, за которым стоит третий роутер того же образца, что StageFrameRouter и ActivityClockRouter. Писать через этот шов нельзя намеренно: запись в забег обязана попасть в лог команд. Верхняя петля (GameFlow) пишет и потому спрашивает держателя у хоста в момент использования — как уже делает с участниками занятия.

Грабли:

  • Правку .asmdef compile-check.ps1 не видит. Скрипт собирает по .rsp, которые генерирует редактор, а ссылки сборки живут именно там: новая ссылка на VContainer в тестовой сборке давала «не найден тип VContainer» до бесконечности, хотя файл на диске уже правильный. Проверять такие правки надо теневым прогоном (run-tests.ps1 -Where Shadow) — он импортирует проект сам.
  • Обоснование в комментарии пережило свою причину. В корне было записано, что роль нельзя решить регистрацией, «потому что боевой скоуп поднимается на буте». Скоуп перестал подниматься на буте ещё в фазе 1, а комментарий остался и продолжал оправдывать пять ветвлений вокруг IBattleAuthority. Записан долгом (tech-debt §3.23), комментарий исправлен.

Владелец правды: Game/Session/SessionHost.cs, Game/Session/SessionInstaller.cs, Game/Session/SessionRunRouter.cs, Guild/IRunStateView.cs, тест SessionScopeTests.