Решили: слепота считает взмахи носителя (RuntimeUnit.AttacksMade), а не попадания; счётчик живёт на юните, не в эффекте; глубина берётся числом порций; промах подаётся показу тем же сигналом, что уклонение. Заодно порция без силы стала законной (RuntimeEffect.AddPortion).

Почему: счётчик в эффекте не годится, потому что стаки слепоты — порции, у каждой свой срок и свой Counter, и «каждая четвёртая» отмерялась бы от четырёх разных начал. Считать попадания вместо взмахов нельзя: первый же промах отодвигал бы следующий на четыре УДАЧНЫХ удара, и обещанная лестница поехала бы в пользу слепого. Опрос вынесен отдельным швом (IAttackMissComponent), а не приписан к pre-damage-негейту: негейт — дело ЦЕЛИ и тратит её заряды, промах — дело атакующего и не тратит ничего, кроме взмаха. Второй канал показа не заводили: для игрока это одна и та же цифра «мимо».

Грабли: три подряд, и все — про замер, а не про механику. Первый тест ронял слепого: безоружного манекена ему не дали, и тот добивал носителя на пятом обмене, поэтому взмахов не хватало. Второй считал промахи потиково — но цифры снимаются на замахе, а исход приходит позже, и «в этот тик урона нет» означало «ещё летит». Третий сделал слепоту бессрочной, чтобы она не гасла, — а порция по определению имеет срок, и при baseDuration = -1 не создавалась вовсе: порционный эффект без порций копился как один стак. Проверять надо было не догадкой, а прямым опросом шва — он дал ответ за один заход.

Владелец правды: BlindComponent (лестница и Depth), RuntimeUnit.AttacksMade, RuntimeEffect.AddPortion (remarks про порцию без силы), тест BlindTests.