diff --git a/applications/PoP/roomtest/bug_closed.md b/applications/PoP/roomtest/bug_closed.md
index 9e6dd7e..2316914 100644
--- a/applications/PoP/roomtest/bug_closed.md
+++ b/applications/PoP/roomtest/bug_closed.md
@@ -11,6 +11,152 @@
---
+## BUG-GRAB-1. Прыжок с места через провал в 3 тайла: зацепа нет — **ЗАКРЫТ 2026-08-05**
+
+**Проверено в игре (пользователь):** «зацеп работает». Физика была верна с
+самого начала, чинить пришлось клавиатуру — [BUG-KBD-5](#bug-kbd-5).
+
+> **Итог 2026-08-05.** Физика тут ни при чём — виновата клавиатура.
+> Зажатый Shift снимался автоповтором зажатой стрелки, поэтому к кадрам
+> 102…106 (окно зацепа) движок видел Shift отпущенным. Полный разбор и
+> фикс — [BUG-KBD-5](bug_closed.md#bug-kbd-5); поведение Shift в MAME
+> проверено замером карты `_kbdraw_down`. Осталось подтвердить сам зацеп
+> живой игрой; версии 2 и 3 ниже проверять только если он всё ещё не выйдет.
+
+
+**Симптом.** Уровень 2, комната 9. Перепрыгнув на (1,1), Кид должен
+вернуться обратно: разбегаться негде, поэтому он встаёт на самый край
+плиты, прыгает с места и **цепляется руками за (1,5)**, после чего
+подтягивается. У нас Кид с зажатым Shift всё равно срывается.
+
+**Что уже точно известно (и не надо перепроверять).**
+
+1. **Физика прыжка у нас совпадает с оригиналом кадр в кадр.** Сверено по
+ логу SDLPoP против трассы харнесса при одинаковом старте `x=95`:
+
+ ```
+ кадр 16 18 22 23 24 25 102 103 104 105
+ SDLPoP 95 97 105 112 121 126 128 130 131 133
+ наш 95 97 105 112 121 126 128 130 131 133
+ ```
+ Совпадает и по `y`, и по колонке/ряду, и по приземлению на 107–108.
+
+2. **В оригинале зацеп срабатывает на кадре 106, а не 102..105.**
+ `check_grab` зовётся из ДВУХ мест: ветка «в воздухе» в `check_action`
+ (кадры 102..105) и `do_fall` (seg005) для `actions_4_in_freefall`.
+ Успешная попытка из лога:
+
+ ```
+ GRAB try f=106 x=135 y=166 col=4 row=2 fall_y=18
+ GRAB probe x=127 col=4 through=0 front_above=3 modif=0
+ GRAB can_grab=1
+ GRAB OK dist=9
+ -> f=91 x=136 y=181 col=5 row=2 act=2 (повис)
+ ```
+ Наш `do_fall` (`pop_map.c`) `check_grab()` из этой ветки тоже зовёт —
+ то есть структура на месте, расходится что-то внутри.
+
+3. **По харнессу зацеп у нас РАБОТАЕТ**: окно стартовых `x = 91…95`, и
+ короткий шаг ставит Кида ровно туда (91 после первого нажатия, 95 после
+ второго). Зафиксировано тестом `t_grab`.
+
+**Отсюда главный вопрос был: почему харнесс говорит «работает», а живая
+машина — «нет».** Расхождение между ними и оказалось уликой; версии
+выдвигались по убыванию правдоподобия, и сработала первая:
+
+- **Shift не доезжает до движка — ПОДТВЕРЖДЕНО, это и была причина.**
+ Харнесс подменяет клавиатуру и потому этот путь не проверяет вовсе, а у
+ нас есть история проблем ровно с «Shift + стрелки» (KBD-1, BUG-KBD-3/4).
+ Замер в MAME: при зажатом Shift и зажатой стрелке бит `LSh` в
+ `_kbdraw_down` стоял в нуле. Разбор — [BUG-KBD-5](bug_closed.md#bug-kbd-5).
+- **Сцена харнесса не равна комнате 9.** Там изолированная комната
+ (соседи — стена), а в игре слева комната 8; кромки шва участвуют в
+ `get_tile`. Проверять чтением `Kid.x` в момент прыжка: попал ли он в
+ окно 91…95 вообще.
+- **Расхождение в `check_grab`.** Наш вариант зовёт `determine_col()`
+ там, где оригинал зовёт `load_fram_det_col()` (перезагрузка кадра +
+ колонка). Для Кида это обычно одно и то же (`cur_frame` в фазе физики
+ принадлежит ему), но проверить стоит.
+
+**Инструменты готовы.** В SDLPoP включена отладка (пометка `DBG-GRAB`):
+`JMP` — покадровая трасса прыжка/падения/виса, `GRAB try|probe|fail|OK` —
+вход в `check_grab` и причина отказа. Снимается поиском по `DBG-GRAB`.
+
+**Найдено попутно, отдельным наблюдением.** После касания площадки на
+кадрах 107–108 (x=140) оба движка снова падают, но X расходится: SDLPoP
+уводит Кида на 134 (колонка 4), мы — на 141 (колонка 5). Похоже на разную
+отработку `in_wall()` у стены (2,7). На зацеп не влияет.
+
+---
+
+---
+
+## BUG-GATEMOD-1. Ворота стартуют закрытыми, хотя в уровне открыты — **ЗАКРЫТ 2026-08-05**
+
+**Проверено в игре (пользователь).**
+
+**Симптом (пользователь, 2026-08-04).** Уровень 2, комната 13: решётка
+между (2,5) и (2,6) обязана быть ОТКРЫТА в начале и захлопнуться, когда Кид
+нажмёт кнопку (2,4) — после этого назад дороги нет. У нас она закрыта
+сразу, кнопка бессмысленна, проход не работает.
+
+**Корень.** Модификатор тайла в ФАЙЛЕ уровня и модификатор в РАНТАЙМЕ —
+разные величины; оригинал переводит их при загрузке в `load_alter_mod`
+(seg008:198E), которую зовёт `alter_mods_allrm` из `load_level`:
+
+```c
+case tiles_4_gate: *modif = (*modif == 1) ? 188 : 0; break;
+case tiles_11_loose:*modif = 0; break;
+case tiles_10_potion:*modif <<= 3; break;
+```
+
+Наш `pop_trob_modif` портировал из неё **только зелье**. Для ворот
+`bg = 1` — это «открыты» (Table 8 спецификации DAT), а в рантайме открытость
+измеряется высотой подъёма 0..188; мы клали в рантайм-модификатор сырую
+единицу, то есть «закрыты на 1/188».
+
+**Фикс.** Ветки ворот и loose дописаны в ленивую инициализацию
+`pop_trob_modif` (`pop_trob.c`). Ветка СТЕН не портируется намеренно: у нас
+`pop_bg` считает связи кладки по типам соседей прямо при отрисовке
+(`wall_modifier`), сохранённый модификатор стены не читается.
+
+**Что это ещё задевает.** Решётка (0,9) комнаты 5 уровня 1 тоже имеет
+`bg = 1`, то есть обязана стартовать открытой — Кид сваливается в комнату 1
+именно через неё, и она захлопывается у него за спиной. Закрывает её
+стартовый триггер `do_startpos` (seg003:167): для уровней с
+`tbl_entry_pose == 1` оригинал ВИРТУАЛЬНО ЖМЁТ кнопку комнаты 5 (0,2) —
+
+```c
+// Special event: press button + falling entry
+get_tile(5, 2, 0); trigger_button(0, 0, -1); seqtbl_offset_char(seq_7_fall);
+```
+
+Замер в SDLPoP (лог по кадрам): `gate(5,0,9)` идёт `188 → 148 → 88 → 8 → 0`,
+шаги 40/60/80 — это `gate_close_speeds`, то есть быстрое закрытие
+(`trigger_gate` вернул тип 3). У нас этот триггер портирован, и закрытие
+работает.
+
+Полный список ворот с `bg = 1`: ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5).
+Остальные ворота уровней 1–3 имеют `bg = 2` → 0, и для них ничего не
+меняется (при модификаторе 2 и 0 и отрисовка, и `can_bump_into_gate` дают
+одно и то же).
+
+**Побочная находка: чит обхода комнат отматывал мир.** После фикса
+пользователь увидел «ворота снова открылись», пройдя `+` в комнату 2 и `-`
+обратно. Причина не в воротах: `ROOMNAV` звал `pop_trob_reset()` перед
+`enter_room`, тот обнулял `room_seen[]`, и `pop_trob_modif()` перечитывал
+модификаторы из уровня заново — то есть чит откатывал открытые/закрытые
+ворота, выдвинутые пики и нажатые кнопки. Пока ворота с `bg=1` ошибочно
+стартовали закрытыми, откат был не виден. `pop_trob_reset()` из навигации
+убран: она обязана только телепортировать, исходное состояние даёт
+перезапуск уровня. Замер, который это показал: `room_modif` комнаты 5
+после `+`/`-` = `00 00 0B 00 09 00 08 01 00 BC` — последний байт 0xBC = 188,
+файловое значение.
+
+---
+
+---
+
## BUG-GUARD-DEAF-1. Страж не оборачивался на вернувшегося Кида — **ЗАКРЫТ 2026-08-05**
**Наблюдение (пользователь, 2026-08-05).** Уровень 2, комната 11, идёт бой
diff --git a/applications/PoP/roomtest/bug_list.md b/applications/PoP/roomtest/bug_list.md
index 8d383ef..d0f8257 100644
--- a/applications/PoP/roomtest/bug_list.md
+++ b/applications/PoP/roomtest/bug_list.md
@@ -27,14 +27,12 @@ BUG-GATE-PASS-1 — однократное наблюдение прохода
| ID | что | тип | статус |
|----|-----|-----|--------|
-| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом (h=1 → пробег безвреден, острия видны на экране) | Minor | **не воспроизводится по требованию; смертельность подтверждена замером** |
-| [BUG-GRAB-1](#bug-grab-1) | ур. 2 комн. 9: прыжок с места через 3 тайла — нет зацепа за кромку | Major | **причина найдена (клавиатура, BUG-KBD-5), фикс есть, ждёт игровой проверки** |
-| [BUG-GATEMOD-1](#bug-gatemod-1) | ворота стартуют закрытыми, хотя в уровне открыты | Major | **фикс есть, ждёт проверки** |
| [Уровень 2](#уровень-2) | остальные баги с приёмки | — | принимаются по ходу |
-| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **перепроверить после [BUG-GATEMOD-1](#bug-gatemod-1)** — та же решётка стартовала не в том состоянии |
+| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **ждёт сценария** (BUG-GATEMOD-1, из-за которого решётка стартовала не в том состоянии, закрыт — перепроверить) |
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
| [T-2](#t-2) | Кид перерисовывается в покое | оптимизация | открыт |
| [обход 24 комнат](#обход-всех-24-комнат-уровня-1) | таблица заполнена на 5 строк из 24 | ревизия | открыт |
+| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом | **низкий** | маловоспроизводимый: ни сценарием, ни попиксельной подгонкой X не поднимается |
---
@@ -84,7 +82,7 @@ Smoke-прогон уровня 3 (пользователь, 2026-08-05) дал
стеной).
-## BUG-SPIKE-1. Пики не убивают бегущего Кида — НЕ ВОСПРОИЗВОДИТСЯ, ЖДЁТ СЦЕНАРИЯ
+## BUG-SPIKE-1. Пики залипают выдвинутыми — НИЗКИЙ ПРИОРИТЕТ, МАЛОВОСПРОИЗВОДИМ
> **Статус 2026-08-05, вечер.** Пользователь **повторить не смог**, а замер
> (ниже) показал, что чистый пробег по убранным пикам убивает штатно. То
@@ -186,145 +184,6 @@ check_spiked (seg006:0658): убивает при h>=2 на кадрах б
---
-
-## BUG-GRAB-1. Прыжок с места через провал в 3 тайла: зацепа нет — **ПРИЧИНА НАЙДЕНА, ФИКС ЕСТЬ, ЖДЁТ ИГРОВОЙ ПРОВЕРКИ**
-
-> **Итог 2026-08-05.** Физика тут ни при чём — виновата клавиатура.
-> Зажатый Shift снимался автоповтором зажатой стрелки, поэтому к кадрам
-> 102…106 (окно зацепа) движок видел Shift отпущенным. Полный разбор и
-> фикс — [BUG-KBD-5](bug_closed.md#bug-kbd-5); поведение Shift в MAME
-> проверено замером карты `_kbdraw_down`. Осталось подтвердить сам зацеп
-> живой игрой; версии 2 и 3 ниже проверять только если он всё ещё не выйдет.
-
-
-**Симптом.** Уровень 2, комната 9. Перепрыгнув на (1,1), Кид должен
-вернуться обратно: разбегаться негде, поэтому он встаёт на самый край
-плиты, прыгает с места и **цепляется руками за (1,5)**, после чего
-подтягивается. У нас Кид с зажатым Shift всё равно срывается.
-
-**Что уже точно известно (и не надо перепроверять).**
-
-1. **Физика прыжка у нас совпадает с оригиналом кадр в кадр.** Сверено по
- логу SDLPoP против трассы харнесса при одинаковом старте `x=95`:
-
- ```
- кадр 16 18 22 23 24 25 102 103 104 105
- SDLPoP 95 97 105 112 121 126 128 130 131 133
- наш 95 97 105 112 121 126 128 130 131 133
- ```
- Совпадает и по `y`, и по колонке/ряду, и по приземлению на 107–108.
-
-2. **В оригинале зацеп срабатывает на кадре 106, а не 102..105.**
- `check_grab` зовётся из ДВУХ мест: ветка «в воздухе» в `check_action`
- (кадры 102..105) и `do_fall` (seg005) для `actions_4_in_freefall`.
- Успешная попытка из лога:
-
- ```
- GRAB try f=106 x=135 y=166 col=4 row=2 fall_y=18
- GRAB probe x=127 col=4 through=0 front_above=3 modif=0
- GRAB can_grab=1
- GRAB OK dist=9
- -> f=91 x=136 y=181 col=5 row=2 act=2 (повис)
- ```
- Наш `do_fall` (`pop_map.c`) `check_grab()` из этой ветки тоже зовёт —
- то есть структура на месте, расходится что-то внутри.
-
-3. **По харнессу зацеп у нас РАБОТАЕТ**: окно стартовых `x = 91…95`, и
- короткий шаг ставит Кида ровно туда (91 после первого нажатия, 95 после
- второго). Зафиксировано тестом `t_grab`.
-
-**Отсюда главный вопрос был: почему харнесс говорит «работает», а живая
-машина — «нет».** Расхождение между ними и оказалось уликой; версии
-выдвигались по убыванию правдоподобия, и сработала первая:
-
-- **Shift не доезжает до движка — ПОДТВЕРЖДЕНО, это и была причина.**
- Харнесс подменяет клавиатуру и потому этот путь не проверяет вовсе, а у
- нас есть история проблем ровно с «Shift + стрелки» (KBD-1, BUG-KBD-3/4).
- Замер в MAME: при зажатом Shift и зажатой стрелке бит `LSh` в
- `_kbdraw_down` стоял в нуле. Разбор — [BUG-KBD-5](bug_closed.md#bug-kbd-5).
-- **Сцена харнесса не равна комнате 9.** Там изолированная комната
- (соседи — стена), а в игре слева комната 8; кромки шва участвуют в
- `get_tile`. Проверять чтением `Kid.x` в момент прыжка: попал ли он в
- окно 91…95 вообще.
-- **Расхождение в `check_grab`.** Наш вариант зовёт `determine_col()`
- там, где оригинал зовёт `load_fram_det_col()` (перезагрузка кадра +
- колонка). Для Кида это обычно одно и то же (`cur_frame` в фазе физики
- принадлежит ему), но проверить стоит.
-
-**Инструменты готовы.** В SDLPoP включена отладка (пометка `DBG-GRAB`):
-`JMP` — покадровая трасса прыжка/падения/виса, `GRAB try|probe|fail|OK` —
-вход в `check_grab` и причина отказа. Снимается поиском по `DBG-GRAB`.
-
-**Найдено попутно, отдельным наблюдением.** После касания площадки на
-кадрах 107–108 (x=140) оба движка снова падают, но X расходится: SDLPoP
-уводит Кида на 134 (колонка 4), мы — на 141 (колонка 5). Похоже на разную
-отработку `in_wall()` у стены (2,7). На зацеп не влияет.
-
----
-
-
-## BUG-GATEMOD-1. Ворота стартуют закрытыми, хотя в уровне открыты — **ФИКС ЕСТЬ, ЖДЁТ ПРОВЕРКИ**
-
-**Симптом (пользователь, 2026-08-04).** Уровень 2, комната 13: решётка
-между (2,5) и (2,6) обязана быть ОТКРЫТА в начале и захлопнуться, когда Кид
-нажмёт кнопку (2,4) — после этого назад дороги нет. У нас она закрыта
-сразу, кнопка бессмысленна, проход не работает.
-
-**Корень.** Модификатор тайла в ФАЙЛЕ уровня и модификатор в РАНТАЙМЕ —
-разные величины; оригинал переводит их при загрузке в `load_alter_mod`
-(seg008:198E), которую зовёт `alter_mods_allrm` из `load_level`:
-
-```c
-case tiles_4_gate: *modif = (*modif == 1) ? 188 : 0; break;
-case tiles_11_loose:*modif = 0; break;
-case tiles_10_potion:*modif <<= 3; break;
-```
-
-Наш `pop_trob_modif` портировал из неё **только зелье**. Для ворот
-`bg = 1` — это «открыты» (Table 8 спецификации DAT), а в рантайме открытость
-измеряется высотой подъёма 0..188; мы клали в рантайм-модификатор сырую
-единицу, то есть «закрыты на 1/188».
-
-**Фикс.** Ветки ворот и loose дописаны в ленивую инициализацию
-`pop_trob_modif` (`pop_trob.c`). Ветка СТЕН не портируется намеренно: у нас
-`pop_bg` считает связи кладки по типам соседей прямо при отрисовке
-(`wall_modifier`), сохранённый модификатор стены не читается.
-
-**Что это ещё задевает.** Решётка (0,9) комнаты 5 уровня 1 тоже имеет
-`bg = 1`, то есть обязана стартовать открытой — Кид сваливается в комнату 1
-именно через неё, и она захлопывается у него за спиной. Закрывает её
-стартовый триггер `do_startpos` (seg003:167): для уровней с
-`tbl_entry_pose == 1` оригинал ВИРТУАЛЬНО ЖМЁТ кнопку комнаты 5 (0,2) —
-
-```c
-// Special event: press button + falling entry
-get_tile(5, 2, 0); trigger_button(0, 0, -1); seqtbl_offset_char(seq_7_fall);
-```
-
-Замер в SDLPoP (лог по кадрам): `gate(5,0,9)` идёт `188 → 148 → 88 → 8 → 0`,
-шаги 40/60/80 — это `gate_close_speeds`, то есть быстрое закрытие
-(`trigger_gate` вернул тип 3). У нас этот триггер портирован, и закрытие
-работает.
-
-Полный список ворот с `bg = 1`: ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5).
-Остальные ворота уровней 1–3 имеют `bg = 2` → 0, и для них ничего не
-меняется (при модификаторе 2 и 0 и отрисовка, и `can_bump_into_gate` дают
-одно и то же).
-
-**Побочная находка: чит обхода комнат отматывал мир.** После фикса
-пользователь увидел «ворота снова открылись», пройдя `+` в комнату 2 и `-`
-обратно. Причина не в воротах: `ROOMNAV` звал `pop_trob_reset()` перед
-`enter_room`, тот обнулял `room_seen[]`, и `pop_trob_modif()` перечитывал
-модификаторы из уровня заново — то есть чит откатывал открытые/закрытые
-ворота, выдвинутые пики и нажатые кнопки. Пока ворота с `bg=1` ошибочно
-стартовали закрытыми, откат был не виден. `pop_trob_reset()` из навигации
-убран: она обязана только телепортировать, исходное состояние даёт
-перезапуск уровня. Замер, который это показал: `room_modif` комнаты 5
-после `+`/`-` = `00 00 0B 00 09 00 08 01 00 BC` — последний байт 0xBC = 188,
-файловое значение.
-
----
-
# Ручная перепроверка фиксов (2026-08-03)