Решили: проход блинков в AutoAttackSystem считает точки назначения ВСЕХ блинкующих от одного снимка мира и только потом записывает позиции — тем же приёмом, что CombatSimulation.ApplyPendingTeleports.

Почему: прежде CombatPositioning.TeleportBehind вызывался прямо в обходе и писал позицию немедленно. Два Убийцы в стелсе бьют друг друга в одном тике, оба блинкуют: левый прыгает за спину правому, пока тот на месте, а правый целится за спину телу, которое уже уехало. Порядок обхода _hits у отражённых сторон одинаковый, а не зеркальный, поэтому сторона, идущая первой, выигрывала половину радиуса атаки. Mirror_SquadSeries_NeverDiverges(0) краснел на CI ровно этим: расхождение 0.5 на тике 450, в момент, когда оба Убийцы умирали.

Это четвёртый случай того же класса, что описан в remarks MirrorMatchTests: система читает мир и пишет в него внутри одного обхода. Лекарство в проекте уже было написано — в ApplyPendingTeleports, с комментарием «иначе второй телепорт целился бы за спину тела, которое только что уехало». Один путь знал про грабли, второй на них наступал.

Грабли:

  1. Комментарий над циклом был правдой и обманом одновременно: «все перемещения происходят ДО того, как хоть один удар начнёт мерить дистанции». До УДАРОВ — да. До других ТЕЛЕПОРТОВ — нет. Читается как гарантия порядка, а гарантирует только половину.
  2. Метод стоит удержаться от удаления: CombatPositioning.TeleportBehind после правки выглядит осиротевшим, но его зовут тесты и мок боевого контекста (EffectTestSupport), а CombatPositioningTests проверяет его напрямую. Одиночный телепорт законен — незеркальным его делала пачка.

Как нашли — метод, который стоит повторять. Сужение составом: прогнать все пары и тройки из расходящейся четвёрки [Antimage, Arcanist, Assassin, BaseRelic]. Все десять подмножеств оказались зелёными — расходится только полный состав, потому что в меньшем бою Убийцы не сходятся в центре к 450-му тику. Это сразу сняло подозрение с одиночных механик и указало на взаимодействие. Дальше хватило полного отчёта MirrorFixture: он печатает слепок обеих сторон и журнал ударов тика, и в нём было видно, что все, кроме Убийц, зеркальны идеально, а Убийцы разошлись ровно на AttackRange * 0.5 — то есть на offset из BehindPosition.

Две гипотезы до этого были отвергнуты замером, и обе выглядели убедительно: кувырок уклонения (Vector2.right в вырожденной ветке) отпал, потому что уклонение срабатывает только от автоатак, а effect.discord оказался дебаффом магической брони, а не DoT.

Владелец правды: Combat/Systems/AutoAttackSystem.cs (проход 2a и _blinkDestinations), Combat/CombatSimulation.cs (ApplyPendingTeleports — образец приёма); тест MirrorMatchTests.