Решили: паспорт юнита («кто это, какой арт, чья команда») показ спрашивает у того же роутера, что даёт кадр, — через шов IUnitDirectory. Своего словаря паспортов CombatPresenter больше не держит.

Почему: тела вне боя выходят на арену мимо симуляции, а словарь наполнялся ровно одним событием — спавном в симуляции. Альтернатива «мир регистрирует свои паспорта в презентере отдельным вызовом» отвергнута: она заводит второго владельца одного факта и требует от мира знать про показ. Директория переключается вместе с источником кадра и только вместе с ним — кадр от боя с паспортами двора нарисовал бы бой людьми из хаба.

Грабли:

  • Гость в коопе всё это время оставался без видов. Паспорта у него приезжают по сети в BattleUnitRegistry, а презентер смотрел в свой словарь, который у гостя не наполняется ничем: симуляции нет, события спавна нет. CreateView тихо возвращал null. Починилось попутно — единственным источником паспорта.
  • Каскад статов был переписан дважды. EffectiveStats объявлен единственным владельцем ещё аудитом 2026-07-26, но RuntimeUnitFactory его не звал: у него лежала своя копия тех же четырёх шагов плюс Судьба сосуда и предметы. Свели: перегрузка Build знает про сосуд и предметы, фабрика зовёт её. Иначе тела мира стали бы третьей переписью.
  • Привязку показа к границе боя перенести пока нельзя. Казалось естественным, чтобы BattleBootstrap подключал ленту в LaunchBattle и отпускал в ResetToWorld — точки границы у него уже есть. Но dev-бои грузятся из консоли прямо в EncounterLoader, мимо него, и остались бы без показа. Привязка живёт на всю сессию, как в шаге 1а, до рождения боевого скоупа (шаг 1б, коммит 4).
  • Отряд теперь материализуется в симуляции на входе в бой, а не на старте акта. Ветка if (!HasLivingParty()) DeployParty() в LaunchBattle из запасной стала основной. Пока показ привязан к ленте на всю сессию, арена под картой акта пуста — тела уже лежат в держателе, но их никто не спрашивает.

Владелец правды: Combat/Tape/UnitIdentity.cs, Combat/Tape/StageFrameRouter.cs, Combat/Units/WorldBodyBuilder.cs; тесты StageFrameRouterTests.Directory_FollowsTheFrameSource, WorldBodyBuilderTests.WorldBody_ShowsTheSameNumbersAsTheBattleUnit.