docs: review document for #741

Issue: #741
User-Visible: no
This commit is contained in:
claude[bot]
2026-10-01 05:59:54 +00:00
parent d5bdfde919
commit d87f834448
+116
View File
@@ -0,0 +1,116 @@
# CODE-REVIEW-741-r1
**Issue:** #741 «2.5D: неиспользуемое поле stageSize в IsoOverlayFitEnvelopeInput»
**Материал раунда:** `a8c8f1d68aa7b42a51b67630a0adb69188213459` (ветка `issue/741-drop-stage-size`, поверх `dev@76558bf2`)
**Трек:** `track:show` (поднят с `track:ship` владельцем — риск по участку `iso-scene-render`, #707)
**Заход:** r1 · блокирующих циклов 0/2
## Скоуп
ТЗ (тело issue): удалить неиспользуемое необязательное поле `stageSize` из
`IsoOverlayFitEnvelopeInput` (`src/iso-scene-render.ts`) вместе с обоими местами
передачи (`_isoScene` и обработчик фокуса комнаты, `src/houseplan-card.ts`);
переписать юнит `#725 AC3`, который сравнивал `bounds` при `stageSize: null` и
`{1000, 500}` — после удаления поля сравнение теряет предмет.
Диф: `src/houseplan-card.ts` (−2 строки), `src/iso-scene-render.ts` (−1 строка
типа), `test/iso-scene-render.test.mjs` (тест переписан). Класс A (`src/**`) +
класс B (тест). Один коммит, трейлеры `Issue: #741` / `User-Visible: no` —
верно: изменение не видимо пользователю, changelog не тронут и не должен быть.
## Как проверялось
| Гейт | Статус | Как |
|---|---|---|
| `tsc --noEmit` | ✅ подтверждён | Validate на `a8c8f1d6`: https://github.com/Matysh/houseplan-card/actions/runs/36821143516 — не перегонял отдельно |
| `npm test` (3410 тестов) | ✅ сам перегнал | `npm test` → `pass 3431, fail 0, skipped 1`; дополнительно `node --test test/iso-scene-render.test.mjs` отдельно → `31/31 pass` |
| `npm run build` + сверка бандла | ✅ подтверждён Validate | не перегонял — дешёвый гейт уже зелёный на этом SHA |
| «Тест умеет падать» (`#725 AC3/#741`) | ✅ проверено исполнением | временно мутировал `resolveIsoOverlayFitEnvelope` (внёс в `base` зависимость от `targetView`/aspect, имитируя регрессию «stage просочился в bounds»); пересобрал `test-build`, прогнал файл — упало 2 из 31 (`the overlay fit bounds depend only on scene.frame…`, `the view fits the bounds`); откатил файл, пересобрал, снова 31/31. Тест чувствителен к ровно тому регрессу, который он называет |
| `node scripts/smoke-select.mjs --base 76558bf2 --head a8c8f1d6` | выполнено | **НЕОПРЕДЕЛЁННОСТЬ**: 0 символов проекта на изменённых строках (чистое удаление мёртвого поля типа), ни один смок не связан доказуемо. Автор дополнительно прогнал `smoke_room_fit`, `smoke_isometric_contract`, `smoke_iso_flat_parity` (все три существуют в `demo/`, по названию относятся к затронутой функции) — разумный выбор поверх визуального минимума; браузерные смоки сам не перегонял (AC их не называет, Chromium не поднимал) |
| `npm run golden:verify` | не требуется | метки `ci:golden` нет, рендер пикселей не меняется (ниже) |
| `pytest tests_backend` | не требуется | Python не тронут |
| `npm run invariants` | не требуется | геометрия и ссылки на неё не меняются — меняется только форма входного объекта функции разметки, не геометрическая модель |
## Риск по изменённым участкам (#707)
- **perf — `src/iso-scene-render.ts:651` (удалена), участок `iso-scene-render`.**
Поведение уже зафиксировано: читал тело `resolveIsoOverlayFitEnvelope`
(`src/iso-scene-render.ts:658-668`) и в версии до диффа, и после — `input.stageSize`
нигде не читается, функция использует только `baseBounds`, `entries`,
`ownerId`, `targetView`. Удаление поля из интерфейса и обоих мест передачи —
изменение только по типам, ни одного пути исполнения не задевает. Документ
`docs/ISOMETRIC.md` (раздел «Fit», строки ~245-263) фиксирует контракт прямо:
«Neither zoom nor a stage resize is a layout event… the fit envelope reserves
no nudge budget» — т.е. stage/aspect и до этой задачи не должны были влиять на
раскладку. route: `fix` (критерий не нарушен — `perf-touch`: изменения
производительности нет, т.к. убираемый путь не исполнялся).
- **visual (render) — `src/iso-scene-render.ts:651` (удалена), участок `iso-*` (render).**
То же: поле не читалось, значит удаление не может изменить картинку. Плюс
переписанный юнит `#725 AC3/#741` это утверждает явно и проверяемо: `bounds`
идентичны для пяти разных aspect (0.5, 1, 1000/500, 320/180, собственный aspect
кадра), различается только `view`; я подтвердил мутационным прогоном (таблица
выше), что тест ловит регресс, где это переставало бы быть так. Визуальный
минимум прогоняется `gate:small` (автор) — отдельного `ci:golden` для
переноса/удаления неиспользуемого поля типа не требуется: рендер-путь не
меняется ни на один пиксель, доказательство — отсутствие чтения поля в коде
плюс тест. route: `fix`.
## Находки
Нет. Диф — корректное удаление мёртвого поля, оба места передачи вычищены
полностью (`grep -rn stageSize src/` — пусто), заменяющий тест по существу
эквивалентен старому AC и доказуемо чувствителен к регрессу (проверено
мутацией, не только чтением). Якорь мутационного реестра `#725 AC5`
(`scripts/mutation-registry.mjs:13846-13857`, строка
`const aspect = scene.frame.w / scene.frame.h; // #713/#725: …`) не тронут
диффом — заявление автора «якорь #725 на месте» подтверждено чтением.
Побочный файл `test/iso-overlay-fixture-types.test.mjs` тоже содержит
`DEAD_SCENE_FIELDS` со строкой `'stageSize'` — проверил: это другой тип,
`OverlaySceneFixture` входа `buildIsoOverlayRenderScene`/`overlayScene`
(#714/#724/#732), не `IsoOverlayFitEnvelopeInput`. Задача #741 его не задевает
и трогать не должна была.
## Что проверено и корректно
- Оба места передачи `stageSize` удалены полностью, без мёртвых остатков
(переменная `stage` в обработчике фокуса комнаты продолжает использоваться
для `baseFit`/`targetOf` — не осиротела).
- Трейлеры коммита корректны: `Issue: #741`, `User-Visible: no`, changelog не
тронут — согласуется (невидимое изменение).
- Диф в пределах заявленных ship-лимитов по `src/**` (+2/−4), новых файлов,
i18n, полей конфига нет — но ревью идёт по треку `show`, как и требует метка.
- `npm test` зелёный целиком (3431 pass / 0 fail / 1 skip), не только
затронутый файл.
## Чего не проверял
- Полный `tsc --noEmit` и `npm run build` с сверкой трёх копий бандла —
перегонять не стал, взял зелёный Validate на этом же SHA (дешёвые гейты
параграф §8).
- Браузерные смоки (`smoke_room_fit`, `smoke_isometric_contract`,
`smoke_iso_flat_parity`) сам не выполнял — `smoke-select` вернул
НЕОПРЕДЕЛЁННОСТЬ (связь не доказана), AC их не называет, Chromium не
поднимал; полагаюсь на заявленный автором зелёный прогон.
- `npm run golden:verify`, `pytest tests_backend`, `npm run invariants` —
не запускал, т.к. не применимы к этому диффу (см. таблицу гейтов).
## Вердикт
Зелёный. AC выполнены полностью, класс риска `perf`/`visual` закрыт документом
`docs/ISOMETRIC.md` и подтверждён чтением кода и мутационной проверкой теста;
находок нет.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/741-drop-stage-size`, коммит `a8c8f1d68aa7` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `84476d1a976435349921933a39178f4d2989d75f`
```
git log --all --format='%H %T' | grep 84476d1a9764
```
- Тело issue: `2ca2e0ad99b76c735fed07cd61d7ee08f1a58d6a9a6365322540273eb3d0c794`
- Вердикт конвейера: `green` · High 0 · маршрут `fix`