From 0e8e87303e0908c98d799fc65a75b38948cccccf Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 16:51:38 +0000 Subject: [PATCH] docs: review document for #649 Issue: #649 User-Visible: no --- docs/reviews/CODE-REVIEW-649-r2.md | 247 +++++++++++++++++++++++++++++ docs/reviews/INDEX.md | 3 +- 2 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/CODE-REVIEW-649-r2.md diff --git a/docs/reviews/CODE-REVIEW-649-r2.md b/docs/reviews/CODE-REVIEW-649-r2.md new file mode 100644 index 00000000..a02ac48f --- /dev/null +++ b/docs/reviews/CODE-REVIEW-649-r2.md @@ -0,0 +1,247 @@ +# CODE-REVIEW-649-r2 + +Issue: [#649](https://github.com/Matysh/houseplan-card/issues/649) · 2.5D, этап 6: +объёмные иконки-плитки с тенью, мягкий свет по солнцу, слой декора без +изменений, режим из experimental в General settings. + +Материал: `git log --oneline origin/dev..HEAD` / `git diff origin/dev...HEAD`, +ровно на SHA `106fdc096d5dd7de55d22a88c3a0a2b894b83b49` (рабочая копия уже на +нём; ветку не переключал, `git fetch`/`pull`/`checkout` на другой коммит не +выполнял). + +``` +106fdc09 fix(2.5D): prove the sun beam is cut by bodies; review r1 lows (#649) +e1f1c7d9 docs: review document for #649 +2ed05031 test(mutants): stage3-w12 guard follows the renamed #649 contract test +e5ab4659 feat: 2.5D stage 6 — public setting, raised tiles, soft sun, theme-free walls (#649) +``` + +164 файла в фиче + 73 файла в делте раунда. Трейлеры на всех трёх рабочих +коммитах корректны: `Issue: #649` везде; `User-Visible: yes` на `e5ab4659` +(оба changelog в том же коммите — `docs/CHANGELOG.md`/`.ru.md`, +12/+12 строк); +`User-Visible: no` на `2ed05031` (гейт мутанта) и на `106fdc09` (делта этого +раунда — см. ниже, почему верно). Заход r2 код-ревью; ТЗ (r2 в теле issue) уже +прошло зелёное SPEC-REVIEW-649-r2. + +**SHA материала r1 не резолвится.** `de4521823ba69c390fda4c0534e52e24a63cc66a` +(коммит) и дерево `571541905136a48c1729755f6d7877e5ac6aece4` из блока +«Материал раунда» документа r1 отсутствуют в `git log --all` этого клона (не +shallow — `git rev-parse --is-shallow-repository` → `false`, 3576 коммитов на +`origin/dev`). Это не находка (§2.10: «SHA не резолвится — обычное дело»): у +текущего `e5ab4659` тот же commit message, тот же автор/дата инструмента, тот +же родитель (`origin/dev` tip) и почти идентичная статистика диффа (164 файла, ++5569/−3766 против заявленных в r1 +5570/−3767 — расхождение в одну строку в +обе стороны, не содержательное). Это типичная механика конвейера: ветка +ребейзится на актуальный `origin/dev` перед каждым раундом, что меняет все SHA +ниже точки ребейза без изменения содержимого. Дельта раунда — ровно то, что +показывает `git diff e5ab4659..106fdc09` (коммит `2ed05031` между ними не +трогает продуктовый код, только чинит протухший guard мутанта — унаследован +как есть). Объём разбора: по дельте (§2.10), она полностью локальна — один +новый коммит `106fdc09`, который сам называет себя ответом на r1 («review r1 +lows»). + +## Скоуп + +Без изменений с r1 (см. `docs/reviews/CODE-REVIEW-649-r1.md` → «Скоуп»). +Предмет ЭТОГО раунда — единственный новый коммит `106fdc09`: закрывает +Medium-находку r1 (M1, обрезка 2.5D-луча барьерами не была доказана тестом) и +пять из шести Low (L1, L3, L4, L5, L6; L2 была снята самим r1 без правки кода +как опечатка хендоффа — здесь закрывать нечего). + +## Как проверялось (объём по дельте, §2.10) + +1. Прочитан документ и вердикт предыдущего раунда: + `docs/reviews/CODE-REVIEW-649-r1.md` — жёлтый, High 0, Medium 1 (M1), Low 6 + (L2 снята r1 сразу). +2. Объявлена дельта: `git diff e5ab4659..106fdc09` — 73 файла (в основном + пересобранный бандл), содержательно: `src/iso-sun.ts` не тронут (только + `test/`, `demo/`, `scripts/mutation-registry.mjs`, `src/iso-tiles.ts`, + `src/houseplan-card.ts` комментарий, `docs/DEVELOPMENT.md`, + `docs/ARCHITECTURE.md`, `demo/benchmark_large_house.mjs`). Полный текст + диффа коммита `106fdc09` прочитан построчно. +3. Для M1 — прочитан `src/iso-sun.ts:82-122` (`computeIsoSunBeams`), + подтверждено, что `directionalOccluders(input.occluders, away, travel)` + (строка 112) — ровно то место, которое M1 называл риском (перепутанный + знак направления/длина). Новый юнит + `test/iso-stage6.test.mjs` (тест «AC7 the 2.5D beam is cut…») ставит + колонну на пути луча и проверяет три точки (перед колонной светло, за + колонной темно, рядом с тенью снова светло) плюс площадь тени. +4. **Мутационное доказательство выполнено исполнением, не чтением.** Для всех + трёх новых мутантов (`iso-sun-occluders-toward-sun`, + `iso-sun-occluders-ignored`, `iso-sun-card-drops-occluders`) я вручную + применил патч из `scripts/mutation-registry.mjs`, прогнал именно тот guard, + что записан в реестре, убедился в красном результате, затем откатил файл и + для двух из них (те, что требуют бандл) пересобрал (`npm run bundle:sync`) + и подтвердил `git status` чист — см. таблицу ниже, результаты все реальные + прогоны этой сессии. +5. Для L3 (`src/iso-tiles.ts:109-117`, `isoTileStateCss`) вручную пересчитана + специфичность CSS: новые правила `.dev.theme-dark.${state}` (3 класса) и + `.dev.theme-dark.${state}.iso-floor-light` (4 класса) перебивают старые + `.dev.${state}` (2) / `.dev.${state}.iso-floor-light` (3) по специфичности + независимо от порядка — правки корректны структурно, не только текстуально. + Также перепроверено (как и в r1), что для всех 6 `ISO_STATE_BODIES` + `isoEdgeColor` сегодня возвращает одно и то же значение независимо от + `theme`, потому что ни один не тёмный (`luma·255<70`) и ни один не + «near-white» в 0..1-шкале (`luma>0.98`) — значит фикс сегодня не меняет + видимый результат ни для одного реального состояния, что и объясняет + `User-Visible: no`. +6. Для L1 прочитаны все 4 места, названные в r1 (`docs/DEVELOPMENT.md:231`, + `docs/ARCHITECTURE.md:31`, `src/houseplan-card.ts:627`, + `demo/benchmark_large_house.mjs:145`) — все четыре переписаны, проверено, + что переписанный текст не противоречит соседним абзацам того же файла + (`docs/DEVELOPMENT.md:249-251`, `docs/ARCHITECTURE.md:86-88`, + `src/houseplan-card.ts:~2305`), и что не осталось других вхождений + «experimental/alpha-only/opt-in alpha» применительно именно к 2.5D/Stage 4 + (`grep -n alpha` по трём файлам — только легитимные несвязанные + употребления: общий `hp_alpha`/Labs-инфраструктура и цветовая альфа). +7. Для L4/L5/L6 прочитаны новые ассерты `demo/smoke_iso_tiles.mjs` и сверены с + CSS-правилами, на которые они опираются (специфичность + `.dev.theme-dark`/`.oplock`/`.virtual .device-shell-frame`, + `iso-overlays?.devices.get(d.id)` опциональная цепочка для L6) — все три + были задокументированы в r1 как «проверено чтением, корректно, но без + теста»; теперь тест есть и я лично прогнал его (все ассерты `true`). +8. Прогнаны реально (не приняты по Validate) — таблица ниже. + +### Гейты — что прогнано и с каким результатом + +| Гейт | Прогнан | Результат | +|---|---|---| +| `Validate` на `106fdc09` | нет, зачтён по ссылке (условие задачи) | success, https://github.com/Matysh/houseplan-card/actions/runs/36161723663 | +| `npx tsc -p tsconfig.test.json` + `node scripts/fix-test-build.mjs` | да | 0 ошибок | +| `npm run bundle:sync` (`tsc --noEmit && rollup -c` + bundle-tree sync) | да, дважды (baseline и после отката мутанта) | чисто оба раза, `git status --porcelain` пуст после отката — закоммиченные `dist/**`, `custom_components/.../frontend`, `demo/srv/assets` побайтово совпадают со свежей сборкой на этом SHA | +| `node --test test/iso-stage6.test.mjs` (весь файл, 10 тестов) | да | **OK**, 10/10 `pass` | +| `node --test --test-name-pattern="AC7 the 2.5D beam is cut" test/iso-stage6.test.mjs` на немутированном коде | да | **OK** | +| Мутант `iso-sun-occluders-toward-sun` (`away`→`toSun`) применён к `src/iso-sun.ts`, тот же guard | да | **красный** — `AssertionError: between the window and the body the floor stays lit`, ожидалось `true`, получено `false` | +| Мутант `iso-sun-occluders-ignored` (доп. условие `elevation > 90`) применён, тот же guard | да | **красный** — `AssertionError: behind the body, away from the sun, the floor is in shadow` | +| Мутант `iso-sun-card-drops-occluders` (`occluders: []` в `houseplan-card.ts`) применён, пересобран, `node demo/smoke_iso_sun.mjs` | да | **красный** — `bodyCutsTheBeam: expected true, got false`; после отката и пересборки `git status` снова чист | +| `node demo/smoke_iso_sun.mjs` на немутированном коде | да | **OK**, все 20 проверок `true`, включая новые `bodyCutsTheBeam`, `beamBackWithoutBody` | +| `node demo/smoke_iso_tiles.mjs` на немутированном коде | да | **OK**, все 39 проверок `true`, включая новые `alarmBeatsHover`, `alarmBeatsSelected`, `virtualNoDashedRing`, `noBordersKeepsTiles`, `noBordersKeepsShadows` | +| `node scripts/check-docs.mjs --external --screenshots=warn` (режим обычного пуша, `classify-changes.mjs`/`validate.yml`) | да | **OK**, 7 файлов, 12 внешних ссылок; один `WARN` про устаревший фингерпринт скриншотов — унаследован, предрелизный гейт (#479), делта его не касается | +| `node scripts/smoke-select.mjs --base 2ed05031 --head HEAD` (скоуп ровно делты раунда) | да | `НЕОПРЕДЕЛЁННОСТЬ` — дифф исполняемый, но инструмент не находит символьной связи (делта — 2 файла `src/**`, изменения в основном текстовые/CSS-generation внутри уже покрытых функций); решение — см. ниже | +| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` (полный охват фичи, как в r1) | да | те же 78 прямых совпадений, что в r1 (делта раунда их не меняет) — решение r1 унаследовано без повтора | +| `python -m pytest tests_backend` | нет | делта раунда не трогает ни одного `.py`-файла (`git show 106fdc09 --stat` — 0 совпадений `custom_components/.*\.py`); гейт неприменим к этой делте | +| `npm run golden:verify` | нет | делта `User-Visible: no`, ни одна золотая сцена не задета | +| `npm run invariants` | нет | делта не меняет каноническую геометрию (только презентационные occluders/CSS-эмиссию) | +| Полный `npm test` | нет, принят по Validate на этом SHA | — | + +**Решение по `smoke-select --base 2ed05031 --head HEAD` (НЕОПРЕДЕЛЁННОСТЬ).** +Инструмент не связал делту ни с одним смоком символьно (изменения в +`iso-sun.ts` не тронуты вовсе — только новый юнит-тест их покрывает; изменения +в `iso-tiles.ts` — две дополнительные CSS-строки внутри уже существующей +функции). Это не разрешение ничего не прогонять (по инструкции промпта): я сам +выбрал и прогнал `smoke_iso_sun.mjs` и `smoke_iso_tiles.mjs` — ровно те смоки, +что физически упражняют изменённые функции (`computeIsoSunBeams`, +`isoTileStateCss`) через реальный рендер в браузере, и лично воспроизвёл +падение всех трёх новых мутантов на них. Остальные ~275 смоков матрицы не +запускал: делта не трогает ничего вне `iso-sun.ts`/`iso-tiles.ts`/тестов/доков. + +## Находки + +Нет ни High, ни Medium, ни Low. Делта раунда полностью и по существу +закрывает M1 (доказано исполнением: тест и три мутанта, все три реально +покраснели) и пять Low из шести (L1, L3, L4, L5, L6); L2 была снята ещё в r1. + +## Закрытие раунда r1 + +| Находка | Чем закрыта | Где это видно | +|---|---|---| +| **M1** (Medium) — обрезка 2.5D-луча барьерами (физические тела, Solid-перегородки) нигде не доказана тестом; названный риск — перепутанный знак направления или длина экструзии в `directionalOccluders(input.occluders, away, travel)` | Новый юнит `test/iso-stage6.test.mjs` («AC7 the 2.5D beam is cut…», колонна на пути луча: лит перед ней, тень за ней, лит рядом) + новые ассерты `demo/smoke_iso_sun.mjs` (`bodyCutsTheBeam`, `beamBackWithoutBody`, Solid-перегородка в реальном рендере) + три мутанта реестра (`iso-sun-occluders-toward-sun`, `iso-sun-occluders-ignored`, `iso-sun-card-drops-occluders`). Все три лично применены и подтверждены красными в этой сессии (см. таблицу гейтов) | `test/iso-stage6.test.mjs:151-179`; `demo/smoke_iso_sun.mjs:99-130`; `scripts/mutation-registry.mjs:3526-3546`; код неизменён — `src/iso-sun.ts:111-114` | +| **L1** — устаревшие «alpha/hidden»-формулировки рядом с исправленным текстом | Переписаны все 4 места, проверено на противоречие соседним абзацам | `docs/DEVELOPMENT.md:231-232`, `docs/ARCHITECTURE.md:31`, `src/houseplan-card.ts:627`, `demo/benchmark_large_house.mjs:145` | +| **L2** — опечатка числа в хендоффе (не код) | Была снята уже в r1 без правки; в этом раунде править нечего | — | +| **L3** — `isoTileStateCss()` не различал тему для торца состояний | Добавлены `.dev.theme-dark.${state}` / `...iso-floor-light` со своим вызовом `edge(body,'dark',...)`, специфичность выше старых правил (проверено пересчётом), покрыто новым ассертом юнита | `src/iso-tiles.ts:113-116`; `test/iso-stage6.test.mjs:68-70` | +| **L4** — «Alert > чистый Hover» и «Alert > чистый Selected» не проверялись отдельно | Два новых прогона: реальный `mouse.move` + `alarm` без селекта/фокуса; `sel`+`alarm` без hover/focus | `demo/smoke_iso_tiles.mjs:197-200,207-221` | +| **L5** — нет теста на `.dev.virtual` (Q1: без пунктира) | Новый ассерт `virtualNoDashedRing` на `.device-shell-frame` с классом `.virtual` | `demo/smoke_iso_tiles.mjs:201-203,222` | +| **L6** — плитки/тени без стен (`show_borders:false`) не покрыты тестом | Новые ассерты `noBordersKeepsTiles`/`noBordersKeepsShadows` через реальный `setServerConfig` | `demo/smoke_iso_tiles.mjs:224-238` | + +## Унаследовано из r1 + +Без повторной проверки, документ `docs/reviews/CODE-REVIEW-649-r1.md`, +материал — фактическое содержимое `e5ab4659`/`2ed05031` (идентично по +существу тому, что рецензировалось в r1 под старыми SHA `e59c89df`/`de452182`, +см. обоснование выше — ребейз без изменения содержимого): + +- AC1 (Flat неизменен, `test/styles-split.test.mjs`, единственный вызов + `furniturePlanScreenScale`), AC2 (геометрия/торец плитки), AC3 (коллизии + ×1.12), AC4 (тень, таблица параметров), AC5 (рамки/приоритет — базовая + часть, за вычетом закрытых сейчас L4-пар), AC6 (forced-colors), AC7 (формула + луча, градиенты, стопы, ворота видимости — за вычетом закрытого сейчас M1), + AC8 (мебель, `stroke-width`), AC9 (тема не красит стены), AC10/AC11 + (`settings.volumetric_view`, alpha-вход убран, backend-валидация), AC12 + (макеты, side-by-side), Golden/матрица, мутационный реестр (16 старых + мутантов), бюджет бандла — все приняты по документу r1 без повторного + прогона в этом раунде, т.к. делта `106fdc09` их не касается. +- `python -m pytest tests_backend` не прогонялся ни в r1 (нет `pytest` в + песочнице), ни сейчас (делта не трогает Python) — тот же непокрытый гейт, + не расширившийся. +- ~70 «слабых» совпадений `smoke-select --base origin/dev` — решение r1 не + прогонять сохраняется без изменений (делта их не касается). + +## Проверено и корректно + +- M1 закрыта доказательством через исполнение, а не только чтением: юнит и + смок падают именно там, где ожидается (перед барьером — светло, за ним — + тень, рядом — снова светло; площадь луча уменьшается минимум на 20×50 + плановых единиц), и все три мутанта реестра лично воспроизведены красными, + затем код и бандл возвращены в состояние `HEAD` (`git status` чист). +- L3 — фикс специфичностно корректен (новые селекторы объективно перебивают + старые) и сегодня не меняет видимый результат ни для одного из 6 + `ISO_STATE_BODIES` (пересчитано вручную по порогам `luma<70`/`luma>0.98`), + что подтверждает трейлер `User-Visible: no`. +- L1 — все 4 места переписаны без противоречий с соседним текстом; других + вхождений «2.5D как alpha/hidden/opt-in» в кодовой базе не осталось + (`grep` по изменённым и смежным файлам). +- L4/L5/L6 — только новые тесты поверх неизменного, уже корректного (по + выводу r1) поведения; лично прогнаны, все зелёные. +- Три-way синхронизация бандла (`dist/**`, `custom_components/.../frontend`, + `demo/srv/assets`) чиста на `106fdc09` — подтверждено дважды: один раз как + есть, один раз после применения и отката мутанта `iso-sun-card-drops-occluders`. +- Монолит `src/houseplan-card.ts` — 12880 строк, без изменений (правка L1 в + нём — замена текста комментария в тех же строках, не добавление). +- Трейлеры всех трёх коммитов раунда корректны; `User-Visible: no` на + `106fdc09` обоснован построчно (доп. тесты + одна текстуально верная, но + сегодня недостижимая ветка CSS). + +## Чего не проверял + +- `python -m pytest tests_backend` — делта не трогает `custom_components/**/*.py` + (0 совпадений в статистике коммита); не гейт этой делты. +- `npm run golden:verify` / `npm run invariants` — делта `User-Visible: no`, + не меняет золотые сцены и не трогает каноническую геометрию модели. +- Полный `npm test` и полный `Validate` (мутанты) — приняты по зелёному + прогону на этом самом SHA (ссылка в задаче); перегонял только те тесты и + мутанты, что относятся к делте раунда. +- ~275 смоков вне `smoke_iso_sun.mjs`/`smoke_iso_tiles.mjs` — `smoke-select` + с базой ровно на делту (`2ed05031..HEAD`) не нашёл символьной связи + (НЕОПРЕДЕЛЁННОСТЬ) ни с одним из них, и содержательно делта не выходит за + пределы `iso-sun.ts`/`iso-tiles.ts`/тестов/документации; полный прогон + матрицы против всей фичи (78 прямых совпадений `origin/dev..HEAD`) унаследован + из r1 без повтора. +- Реальный экран/планшет, Safari — как и в r1, недоступны в песочнице. + +## Вывод + +High: 0. Medium: 0. Low: 0. Делта раунда (`106fdc09`) полностью закрывает +единственную блокирующую находку r1 (M1) доказательством через исполнение — я +лично применил все три новых мутанта реестра и подтвердил, что юнит и смок +падают именно так, как заявлено в `because`, а не просто прочитал код на +доверие. Пять Low из шести получили тесты или точечные правки без побочных +эффектов (L3 пересчитан на отсутствие видимого изменения сегодня — трейлер +`User-Visible: no` корректен); L2 была снята ещё в r1. Дельта локальна и +изолирована (`src/iso-sun.ts` не изменён вовсе, `src/iso-tiles.ts` — 2 строки, +остальное — тесты/доки/бандл), новых находок не внесла. + +Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0 + +--- + + + +## Материал раунда + +- Ветка: `issue/649-25d-stage6`, коммит `106fdc096d5d` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `77286175d538a146863d0b2f80a63e9ffa20af96` + ``` + git log --all --format='%H %T' | grep 77286175d538 + ``` +- Тело issue: `e7d94f185bc9a5d2d7e168933579903e54c88a9819347cb49f0f7c35db60a9e7` +- Вердикт конвейера: `green` · High 0 diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 5d49b822..415fd0d2 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,6 +1,6 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1063, issue: 375. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1064, issue: 375. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| @@ -8,6 +8,7 @@ | #649 | [SPEC-REVIEW-649-r1.md](SPEC-REVIEW-649-r1.md) | spec · r1 | 🟡 жёлтый | 0 | 1 | в скоупе задачи (возвращается автору); принято ревьюером с записью, правки не требует | `lab.js` `houseplan-card.ts` | | #649 | [SPEC-REVIEW-649-r2.md](SPEC-REVIEW-649-r2.md) | spec · r2 | 🟢 зелёный | 0 | 0 | — | — | | #649 | [CODE-REVIEW-649-r1.md](CODE-REVIEW-649-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | AC7: обрезка барьерами (физические тела и Solid-перегородки) луча света в 2.5D нигде не…; Устаревшие «alpha/hidden»-формулировки, оставшиеся рядом с уже исправленным текстом в т…; Число в хендоффе не совпадает с фактическим значением в диффе. Комментарий автора в iss…; isoTileStateCss() жёстко считает торец состояний в theme: 'light' без ветки .theme-dark…; AC5: явно не проверены «Alert > чистый Hover» и «Alert > чистый Selected» по отдельност…; Нет отдельного теста на виртуальные устройства (Q1: «без пунктира, как обычные»). noRin… | `src/iso-sun.ts` `physical-geometry.ts` `houseplan-card.ts` `test/iso-stage6.test.mjs` `demo/smoke_iso_sun.mjs` `docs/DEVELOPMENT.md` `docs/ARCHITECTURE.md` `iso-scene-render.ts` | +| #649 | [CODE-REVIEW-649-r2.md](CODE-REVIEW-649-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — | | #648 | [SPEC-REVIEW-648-r1.md](SPEC-REVIEW-648-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | «Сценарий» не называет персону и; AC10 называет provenance-gate | `docs/SCOPE.md` `scripts/validate-commit-provenance.mjs` `validate.yml` | | #648 | [CODE-REVIEW-648-r1.md](CODE-REVIEW-648-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | AC3 документально обещает browser smoke | `demo/smoke_sections_resize.mjs` `docs/TESTING.md` `smoke_sections_resize.mjs` | | #648 | [CODE-REVIEW-648-r3.md](CODE-REVIEW-648-r3.md) | code · r3 | 🟢 зелёный | 0 | 0 | — | — |