Решили: система повторов боя — это запись ВЫХОДА (боевая лента BattleTape), положенная на диск, а не «сид + пересимуляция». Файл повтора — заголовок-конверт плюс поток записей (паспорта состава и чанки ленты), тем же кодеком, которым кооп раздаёт бой по сети. Воспроизведение — третий наполнитель той же ленты после живого сима и гостя по сети: ReplayFilePlayer кормит ленту из файла, показ рисует, ничего не зная об источнике.

Почему: реплей обязан пережить балансные правки — иначе заготовки боёв за меню (и будущее «посмотреть бой») ломались бы каждым тюнингом чисел. Пересим даёт тот же бой ТОЛЬКО на той же версии: правка баланса, порядка RNG или обхода систем — рассинхрон, и вся RTS-индустрия версионно замыкает такие реплеи. Лента же держит разрешённые факты (позиции, HP, урон, смерти), а не рецепт их вывода, поэтому правка чисел в новой версии старую запись не касается — стойкость к балансу выходит даром. Цена — файл толще (десятки КБ на бой), принята. Отвергнут и промежуточный «запечь арт в файл, чтобы пережить удаление контента»: состав едет id-строкой и резолвится реестром, удаление id пропускает бойца (деградация), а не рушит бой — этого достаточно, запекать тяжёлый арт не стоит.

Сказано: «Давай не будем делать костыли а сделаем норм реализацию “повторов”, ибо это нам понадобится в будущем» и «Показываем только реальный баланс в бою. Не страшно если потом поедет» (04.08.2026, сессия 0768278b). Отменяет прежнее «записи боя нет и не будет: ядро детерминировано, пресет плюс сид дают тот же бой покадрово» — оно было верно для «дешёвого фона на текущей версии» и неверно для повторов как фичи.

Грабли:

  • Резолв скоупа не проверяет ни один тест. CoopBattleWiringTests собирает компоненты руками, минуя VContainer, поэтому DI-ошибка в CombatLifetimeScope.Configure всплывает только в play mode (та же природа, что у саги с IReadyGate). Компонентную связку реплея покрывают ReplayFileTests; сборку роли Replay доказывает лишь редактор.
  • Кольцо снимков ленты — 12 секунд. Влить весь бой из файла разом нельзя: начало вытеснится раньше, чем показ до него дойдёт. Плеер кормит потоково, держа фронт ленты на опережение впереди ViewTick — тот же лаг, что у хоста и гостя.
  • Нарезка чанков была прибита к транспорту. Правило «сколько тиков в чанк, как делить при переполнении» жило в TapeStreamer; файловому писателю оно нужно то же. Дублировать — завести второго владельца (тихо битый чанк вместо ошибки). Вынесено в TapeChunkPump (sink и предел параметром); стример на нём, поведение байт-в-байт (93/93 Net-тестов).
  • BattleUnitRegistry требовал CombatSimulation только ради подписки на спавн. Реплею сим не нужен вовсе — сделан необязательным (null → состав только через RegisterRemote), иначе реплей- скоуп таскал бы бесполезную симуляцию.

Владелец правды: Net/Tape/ReplayFile.cs, ReplayFileWriter.cs, ReplayFilePlayer.cs, TapeChunkPump.cs, тесты ReplayFileTests, TapeChunkCodecTests, CoopBattleWiringTests.