mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,323 @@
|
|||||||
|
# CODE-REVIEW-649-r1
|
||||||
|
|
||||||
|
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 `de4521823ba69c390fda4c0534e52e24a63cc66a` (рабочая копия уже на
|
||||||
|
нём; ветку не переключал, `git fetch`/`pull`/`checkout` не выполнял).
|
||||||
|
|
||||||
|
```
|
||||||
|
de452182 test(mutants): stage3-w12 guard follows the renamed #649 contract test
|
||||||
|
e59c89df feat: 2.5D stage 6 — public setting, raised tiles, soft sun, theme-free walls (#649)
|
||||||
|
```
|
||||||
|
|
||||||
|
164 файла, +5570/−3767. Трейлеры на обоих коммитах корректны: `Issue: #649`,
|
||||||
|
`User-Visible: yes` на `e59c89df` (оба changelog в том же коммите), `User-Visible:
|
||||||
|
no` на `de452182` (гейт мутанта, без поведенческих изменений). Заход r1
|
||||||
|
код-ревью, ТЗ (r2 в теле issue) уже прошло зелёное SPEC-REVIEW.
|
||||||
|
|
||||||
|
## Скоуп
|
||||||
|
|
||||||
|
Реализация всех 4 пунктов ТЗ: (1) объёмные плитки-маркеры с торцом, тенью и
|
||||||
|
рамками только в 2.5D; (2) мягкий свет по солнцу в 2.5D вместо проекции
|
||||||
|
Flat-клиньев; (3) фикс толщины линий мебели + стены/проёмы/подписи не зависят от
|
||||||
|
темы; (4) `settings.volumetric_view` — публичная установка в General settings,
|
||||||
|
удаление alpha-входа, кнопки шапки и пункта меню телефона. AC1–AC13 таблицы
|
||||||
|
приёмки соответствуют этим пунктам; AC13 (перформанс) и часть AC1/AC12 (Linux
|
||||||
|
golden) по тексту ТЗ — предрелизные гейты.
|
||||||
|
|
||||||
|
## Как проверялось
|
||||||
|
|
||||||
|
Ревью велось параллельно пятью под-агентами (каждый — отдельная нить чтения
|
||||||
|
кода/тестов по разделу ТЗ) плюс моя собственная проверка: process-документы,
|
||||||
|
трейлеры, docs-дифф, golden/mutation-реестр, числовые пересчёты, и **реальный
|
||||||
|
прогон гейтов** в песочнице (см. таблицу ниже). Каждое утверждение AC
|
||||||
|
сверялось построчно с кодом; для тестов/смоков проверялось, может ли
|
||||||
|
конкретная проверка реально упасть (не просто «элемент существует»), и что
|
||||||
|
парные мутанты реестра патчат существующие, не протухшие строки.
|
||||||
|
|
||||||
|
### Гейты — что прогнано и с каким результатом
|
||||||
|
|
||||||
|
| Гейт | Прогнан | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| `Validate` (мутанты) на `de452182` | нет, зачтён по ссылке (условие задачи) | success, https://github.com/Matysh/houseplan-card/actions/runs/36153319135 |
|
||||||
|
| `npx tsc --noEmit` (через `npm run build`) | да | 0 ошибок |
|
||||||
|
| `npm run build` | да | чисто, дифф `dist/**` после `bundle:sync` — **нулевой** (`git status` пуст), т.е. закоммиченные `dist/`, `custom_components/houseplan/frontend/`, `demo/srv/assets` побайтово совпадают со свежей сборкой |
|
||||||
|
| `npm test` | нет (принято по Validate) | — |
|
||||||
|
| `python -m pytest tests_backend` | **нет** — в песочнице нет модуля `pytest` (`pip show pytest` → not found) | не прогнан; см. «Чего не проверял» |
|
||||||
|
| `node demo/smoke_iso_tiles.mjs` (AC2–AC6) | да | **OK**, все 33 проверки `true` |
|
||||||
|
| `node demo/smoke_iso_sun.mjs` (AC7) | да | **OK**, все 18 проверок `true` |
|
||||||
|
| `node demo/smoke_iso_theme_walls.mjs` (AC8, AC9) | да | **OK**, все проверки `true`, включая `prismOpaque`, `furnitureSameWidth` |
|
||||||
|
| `node demo/smoke_volumetric_setting.mjs` (AC10, AC11) | да | **OK**, все 18 проверок `true` |
|
||||||
|
| `node demo/smoke_isometric_contract.mjs` | да (прямое совпадение smoke-select) | **OK** |
|
||||||
|
| `node demo/smoke_isometric_live_touch.mjs` | да (прямое совпадение) | **OK**, включая `noBordersHasNoRaisedOrVolumeLayers`, `kioskReadsSetting`, `kioskSettingOffIsFlat` |
|
||||||
|
| `node demo/smoke_room_fit.mjs` | да (прямое совпадение, `_effectiveProjection`) | **OK** |
|
||||||
|
| `node demo/smoke_grid_scale_invariance.mjs` | да (прямое совпадение) | **OK**, включая `isoHasNoCardToggle` |
|
||||||
|
| `node demo/smoke_live_pan_coverage.mjs` | да (прямое совпадение) | **OK** |
|
||||||
|
| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | да | 78 прямых совпадений, множество «слабых связей» — решение по строкам ниже |
|
||||||
|
| `node scripts/model-invariants.mjs` | нет, признано неприменимым | задача не меняет каноническую геометрию (стены/комнаты/layout); только презентационные множители 2.5D и новые рендер-модули — см. обоснование ниже |
|
||||||
|
| `npm run golden:verify` | нет | Flat golden — предрелизный гейт по тексту самого AC1; iso-сцены Stage 6 сознательно не в матрице (см. «Проверено и корректно») |
|
||||||
|
|
||||||
|
**Решение по `smoke-select` (78 прямых совпадений).** Ядро (`_effectiveProjection`,
|
||||||
|
`_ensureIsoSceneRuntime`, `_isoSceneRuntime`, `_kiosk` в связке с проекцией) —
|
||||||
|
прогнано выше (5 смоков). Остальные ~70 совпадений держатся на широко
|
||||||
|
встречающихся символах (`_spaceModel`, `_mode`, `_openSettingsDialog`,
|
||||||
|
`_wallUnionGeometry`, `_physicalBodiesR`, `_spaceWalls`), которые задача не
|
||||||
|
меняет по существу (её дифф не трогает работу стен/junction/диалогов — только
|
||||||
|
использует их выход для 2.5D-презентации и упомянутые символы совпадают, потому
|
||||||
|
что строки диффа их вызывают, а не потому что их поведение изменилось). Не
|
||||||
|
прогонял: риск регресса в этих смоках от данной задачи оцениваю как
|
||||||
|
пренебрежимо малый (сами эти системы не тронуты); при необходимости — решение
|
||||||
|
ревьюера, зафиксированное здесь.
|
||||||
|
|
||||||
|
## Находки
|
||||||
|
|
||||||
|
### Medium (в скоупе — правится в этой же задаче)
|
||||||
|
|
||||||
|
**M1. AC7: обрезка барьерами (физические тела и Solid-перегородки) луча света
|
||||||
|
в 2.5D нигде не доказана тестом.**
|
||||||
|
|
||||||
|
`src/iso-sun.ts:111-114` (`computeIsoSunBeams`) корректно переиспользует
|
||||||
|
`directionalOccluders`/`floorMinusBodies` из `physical-geometry.ts` — тот же
|
||||||
|
приём, что и Flat в `houseplan-card.ts:9961-9971` (`_sunInputs()` строит общий
|
||||||
|
`occluders` для обоих рендеров, `houseplan-card.ts:9889-9894`). Формула,
|
||||||
|
градиент, стопы, лучики, длина от elevation, подоконник — всё это доказано
|
||||||
|
`test/iso-stage6.test.mjs` и `demo/smoke_iso_sun.mjs` (я прогнал последний —
|
||||||
|
все 18 проверок `true`). Но ни один юнит, ни смок, ни одна из
|
||||||
|
`STAGE6_ACCEPTANCE_SCENARIOS`/`GOLDEN_SCENARIOS` не ставит физическое тело или
|
||||||
|
Solid-перегородку на пути 2.5D-луча и не проверяет, что часть параллелограмма
|
||||||
|
действительно вырезается.
|
||||||
|
|
||||||
|
Конкретный сценарий отказа: если строка `directionalOccluders(input.occluders,
|
||||||
|
away, travel)` (`src/iso-sun.ts:112`) получит перепутанный знак направления
|
||||||
|
(`away` вместо вектора к солнцу) или неверную длину экструзии (`travel` вместо
|
||||||
|
`depth`), луч в 2.5D будет либо не обрезаться преградами вовсе, либо
|
||||||
|
обрезаться неправильной стороной — а обрезка контуром комнаты по-прежнему даст
|
||||||
|
непустой результат, так что ни один текущий тест не покраснеет. Это ровно тот
|
||||||
|
защитный элемент AC, который ТЗ называет прямо («Обрезка... теми же
|
||||||
|
барьерами, что у Flat: физические тела и Solid-перегородки») и который не
|
||||||
|
входит ни в один из трёх названных в таблице приёмки мутантов («длина без
|
||||||
|
elevation», «лучики на тёмном полу», «Flat-клинья остались»).
|
||||||
|
|
||||||
|
**Требуется:** один юнит (или расширение `demo/smoke_iso_sun.mjs`) со сценой,
|
||||||
|
где физическое тело/Solid-перегородка стоит на пути луча, и явная проверка,
|
||||||
|
что часть полигона вырезана (например, площадь `polys` меньше площади без
|
||||||
|
преграды, либо конкретная точка за преградой не в `polys`).
|
||||||
|
|
||||||
|
### Low (правлю запись/снимаю с примечанием, отдельного цикла не требуют)
|
||||||
|
|
||||||
|
**L1. Устаревшие «alpha/hidden»-формулировки, оставшиеся рядом с уже
|
||||||
|
исправленным текстом в тех же файлах.**
|
||||||
|
- `docs/DEVELOPMENT.md:231-234` — «Hidden Stage 3 rendering is a separate
|
||||||
|
`iso-scene-render-*` chunk. An alpha-off View must not request it» —
|
||||||
|
противоречит исправленному абзацу пятью строками ниже (249-251) того же
|
||||||
|
файла: «Since #649 the registry is empty: 2.5D left alpha for the General
|
||||||
|
settings switch `settings.volumetric_view`».
|
||||||
|
- `docs/ARCHITECTURE.md:31` — таблица модулей всё ещё называет
|
||||||
|
`iso-scene-render.ts` «hidden alpha-only Stage 4 scene/runtime boundary»,
|
||||||
|
хотя абзац на строках ~86-88 того же файла уже описывает гейт как
|
||||||
|
`settings.volumetric_view` (#649).
|
||||||
|
- `src/houseplan-card.ts:627-628` — комментарий над `_isoSceneRuntimeLoader`:
|
||||||
|
«Stage 4 is an opt-in alpha surface» — противоречит корректному соседнему
|
||||||
|
комментарию (~2305) «one installation-wide switch… no alpha».
|
||||||
|
- `demo/benchmark_large_house.mjs:145` — «experimental Iso runtime»,
|
||||||
|
косметика.
|
||||||
|
|
||||||
|
Ни на поведение, ни на один тест не влияет — только вводит в заблуждение
|
||||||
|
читателя кода/доков. Не блокирует; правится по усмотрению автора либо снимается.
|
||||||
|
|
||||||
|
**L2. Число в хендоффе не совпадает с фактическим значением в диффе.**
|
||||||
|
Комментарий автора в issue: «`monolith-baseline.json`: `bundleBytes` 2 528 415
|
||||||
|
→ 2 540 748»; фактический дифф — `2528415` → `2540346` (разница 402 Б).
|
||||||
|
Артефакт сам по себе непротиворечив (утверждение «монолит 12 880 строк
|
||||||
|
(потолок 12 889)» подтверждено — `wc -l src/houseplan-card.ts` = 12880); это
|
||||||
|
опечатка в тексте хендоффа, не в коде. Снимаю как не влияющую на решение.
|
||||||
|
|
||||||
|
**L3. `isoTileStateCss()` жёстко считает торец состояний в `theme: 'light'`
|
||||||
|
без ветки `.theme-dark.<state>`.**
|
||||||
|
`src/iso-tiles.ts:109-115` — для всех шести состояний (`on/open/lock-locked/
|
||||||
|
lock-unlocked/unavail/alarm`) правило `--iso-edge` не различает тему. Сейчас
|
||||||
|
безопасно: ни один из цветов `ISO_STATE_BODIES` не проходит порог luma<70 и не
|
||||||
|
близок к белому (минимум — `#F0410C`, luma ≈ 98.4), так что смена темы
|
||||||
|
результата не меняет. Если в будущем добавят тёмное состояние, тёмная тема
|
||||||
|
получит светлотемный торец `#5b5e5a` вместо `#4a4a4a` — ни юнит, ни смок этого
|
||||||
|
не поймают. Не требует правки сейчас; фиксирую для следующей задачи, которая
|
||||||
|
тронет `ISO_STATE_BODIES`.
|
||||||
|
|
||||||
|
**L4. AC5: явно не проверены «Alert > чистый Hover» и «Alert > чистый
|
||||||
|
Selected» по отдельности.** `demo/smoke_iso_tiles.mjs` проверяет alarm поверх
|
||||||
|
уже активной комбинации `sel + focus-visible`, а не поверх изолированного
|
||||||
|
hover или изолированного selected. По специфичности CSS-селекторов
|
||||||
|
(`iso-tiles.styles.ts:61-68`) приоритет должен сохраниться и в этих парах —
|
||||||
|
проверено чтением, не исполнением.
|
||||||
|
|
||||||
|
**L5. Нет отдельного теста на виртуальные устройства (Q1: «без пунктира, как
|
||||||
|
обычные»).** `noRing` в `smoke_iso_tiles.mjs` проверяется на обычных
|
||||||
|
маркерах; для `.dev.virtual` полагаюсь на специфичность правил (5 классов
|
||||||
|
`.stage.projection-iso.mode-view .dev...` против 2 у `.virtual .device-shell-
|
||||||
|
frame{border-style:dashed}`) — проверено чтением.
|
||||||
|
|
||||||
|
**L6. Тени и плитки продолжают рисоваться при `show_borders: false`, хотя
|
||||||
|
SVG-слой raised-overlay корректно не строится (это отдельный, уже
|
||||||
|
существующий и по-прежнему проходящий тест `noBordersHasNoRaisedOrVolumeLayers`
|
||||||
|
в `demo/smoke_isometric_live_touch.mjs`).** Автор сам называет это решением,
|
||||||
|
которое стоит проверить ревьюеру. Прочитал код: `isoOverlays?.devices.get(d.id)`
|
||||||
|
(`houseplan-card.ts:11167`) через опциональную цепочку не роняет рендер плиток
|
||||||
|
и их теней, когда оверлей-сцена не построена — поведение соответствует
|
||||||
|
намерению (плитки/тени — независимый HTML/CSS слой, не завязанный на SVG
|
||||||
|
raised-overlay). Автоматической проверки именно этого поведения (ни в одну,
|
||||||
|
ни в другую сторону) нет ни в одном тесте. Не входит ни в один AC таблицы
|
||||||
|
приёмки; фиксирую как задокументированный пробел покрытия, не как дефект.
|
||||||
|
|
||||||
|
## Проверено и корректно (доказано; для геометрии/формул — построчным
|
||||||
|
пересчётом, не «на глаз»)
|
||||||
|
|
||||||
|
- **AC1 (Flat неизменен).** Структурно исключено смешение: все правила
|
||||||
|
`iso-tiles.styles.ts` и добавленные материалы стен скопированы под
|
||||||
|
`.stage.projection-iso.mode-view` (проверено юнит-тестом
|
||||||
|
`test/styles-split.test.mjs`, который парсит CSS AST и требует префикс на
|
||||||
|
КАЖДОМ селекторе, кроме `@media`-обёрток) — Flat-каскад физически не может
|
||||||
|
задеть ни одно правило. Мебель теперь использует ОДИН вызов
|
||||||
|
`furniturePlanScreenScale(...)` для обеих проекций (ветка `iso ? 1 : …`
|
||||||
|
убрана целиком, второго места с иной логикой нет — grep подтвердил
|
||||||
|
единственность). Смоки `flatWedgesUnchanged`, `flatBack`, `offRestoresFlat`,
|
||||||
|
`editorFlat` — прогнаны, все `true`. Байт-в-байт Flat golden — предрелизный
|
||||||
|
гейт по тексту самого AC1, вне обязанностей код-ревью.
|
||||||
|
- **AC2 (плитка/торец/×1.12/бейдж).** Все числа (`radius=22/80`, `depth=8/80`,
|
||||||
|
`lift=6/80`, `badgeGap=6/80`) и формула торца с тремя особыми случаями
|
||||||
|
(luma<70 → `#5b5e5a`/`#4a4a4a`, near-white в тёмной теме → `#4a4a4a`,
|
||||||
|
светлый пол → `brightness(.82) saturate(.8)`) сверены построчно с
|
||||||
|
`src/iso-tiles.ts` и ТЗ; юнит `test/iso-stage6.test.mjs` и `smoke_iso_tiles.mjs`
|
||||||
|
(прогнан, `true`) снимают реальный `getComputedStyle`/`getBoundingClientRect`,
|
||||||
|
а не факт существования DOM-узла.
|
||||||
|
- **AC3 (коллизии ×1.12, touch ≥44×44).** `iso-scene-render.ts:896,947`
|
||||||
|
прокидывают `ISO_ICON_SCALE` в `isoRaisedOverlayHalfSize`; юнит строит
|
||||||
|
реальную сцену через `buildIsoOverlayRenderScene` и алгебраически сверяет
|
||||||
|
половину footprint. Мутант `iso-collision-without-icon-scale` бьёт именно
|
||||||
|
эту строку.
|
||||||
|
- **AC4 (один слой теней, таблица параметров, не поверх соседа).** Таблица
|
||||||
|
4×(сдвиг, размытие, opacity) в `isoTileShadow()` пересчитана и совпадает с
|
||||||
|
ТЗ построчно (например, светлая·светлый пол: `dx=8/80=0.1D`, `dy=34/80=
|
||||||
|
0.425D`, `sigma=11/80=0.1375D`). `shadowNeverOnNeighbourTile` — не
|
||||||
|
поверхностная проверка: маркер намеренно ставится над соседним по вертикали,
|
||||||
|
сравнивается внутренность нижней плитки побайтово со включённым/выключенным
|
||||||
|
слоем теней. `z-index:-1` внутри stacking context `.devlayer` даёт
|
||||||
|
гарантию сильнее буквы ТЗ (тень всегда под ВСЕМИ маркерами, а не только под
|
||||||
|
соседним).
|
||||||
|
- **AC5 (рамки, приоритет, тело не перекрашено).** Приоритет
|
||||||
|
`Alert > Focus > Selected > Hover` реализован специфичностью и порядком
|
||||||
|
правил; смок реально включает классы/фокус и сравнивает `border-top-color` и
|
||||||
|
геометрию рамки. (См. L4 про неполный перебор пар.)
|
||||||
|
- **AC6 (forced-colors/no-filter).** Оба медиа-блока синхронно гасят тень и
|
||||||
|
торец, не трогая размер/рамки; смок эмулирует `forcedColors:'active'` и
|
||||||
|
реально это проверяет.
|
||||||
|
- **AC7 (свет).** Формула длины, параллелограмм (`s = n·L +
|
||||||
|
t·L·(dir·t)/(dir·n)`), градиенты, лучики (только светлый пол), подоконник —
|
||||||
|
все числа совпадают с ТЗ и `docs/SUN.md` дословно; ворота видимости
|
||||||
|
(elevation, fade, редактор, `sun_rays`) реализованы ОДИН раз и лишь
|
||||||
|
переключают геометрию по проекции, так что Flat-код не тронут. Три названных
|
||||||
|
в таблице приёмки мутанта — реальны и указывают на существующие строки. (См.
|
||||||
|
M1 про пробел в барьерах.)
|
||||||
|
- **AC8 (мебель).** `stroke-width` идентичен в Flat и 2.5D (смок:
|
||||||
|
1.1818 px = 1.1818 px, прогнан лично — `true`); юнит `furniture-stroke-
|
||||||
|
contract` матчит новую строку кода регулярным выражением, которое ловит и
|
||||||
|
старую (мутант «`iso ? 1 :` возвращён»).
|
||||||
|
- **AC9 (тема не красит стены).** Пересчитал вручную: `#ffffff` × 0.77 →
|
||||||
|
`#c4c4c4`, × 0.68 → `#adadad`, × 0.60 → `#999999` — совпадает с ТЗ и
|
||||||
|
лабораторией. `.theme-dark .iso-*`/`prefers-color-scheme` правила
|
||||||
|
физически удалены (не ослаблены — `grep` не находит), кроме разрешённого
|
||||||
|
исключения (`iso-ambient-shadow`, внешняя тень здания). Смок
|
||||||
|
`themeKeepsWalls`/`colourSchemeKeepsWalls` (прогнан, `true`) снимает
|
||||||
|
`getComputedStyle` в трёх режимах (light/dark/system) и требует побайтового
|
||||||
|
совпадения.
|
||||||
|
- **AC10/AC11 (настройка, alpha-вход убран).** Поле сериализуется только при
|
||||||
|
`true` (`delete settings.volumetric_view` иначе — `houseplan-editor-
|
||||||
|
runtime.ts:9512-9513`); единое правило вида для карточки/страницы/киоска
|
||||||
|
через `_isoEnabled` = `volumetricViewOf(this._settings)`; редакторы и
|
||||||
|
`houseplan-space-card` структурно без iso-кода (не флаг — код физически
|
||||||
|
отсутствует); ленивая загрузка `iso-scene-render` условна на `_isoEnabled`;
|
||||||
|
`LABS_FLAGS` пуст, кнопка и пункт меню физически вырезаны из шаблона (не
|
||||||
|
CSS-скрытие); `houseplan_card_view_v1` не читается. `validation.py` —
|
||||||
|
строгий `bool` (тест бьёт `None, 0, 1, "true", "iso", [], {}`).
|
||||||
|
`config-schema.json`, `support_package.py` синхронны. i18n en/ru/de/fr —
|
||||||
|
текст совпадает с ТЗ дословно; `view.volumetric`/`view.flat` освобождены и
|
||||||
|
нигде не используются (grep пуст). Смок `smoke_volumetric_setting.mjs`
|
||||||
|
(прогнан лично, все 18 `true`) включает нетривиальные детали: превью не
|
||||||
|
переключает вид до сохранения (`previewDoesNotSwitch`), `false` не
|
||||||
|
сериализуется (`falseNotStored`).
|
||||||
|
- **AC12 (макеты).** Прочитал `docs/design/649-25d-stage6/ACCEPTANCE.md`
|
||||||
|
целиком и все 7 PNG кадров. Единственное осознанное расхождение (цвет рамки
|
||||||
|
hover — `#0C82F0` продукта против янтарного в лабе для светильников)
|
||||||
|
объяснено ссылкой на ТЗ и подтверждено кадром. Мебель, стены, тени, свет,
|
||||||
|
плитки — визуально соответствуют описанию таблицы «элемент · эталон ·
|
||||||
|
продукт»; необъяснённых расхождений не нашёл.
|
||||||
|
- **Golden/матрица.** `STAGE6_ACCEPTANCE_SCENARIOS` намеренно отделены от
|
||||||
|
`GOLDEN_SCENARIOS` (не имеют эталона — по правилу #641 каждая сцена матрицы
|
||||||
|
обязана иметь принятый baseline, а baseline не может существовать раньше
|
||||||
|
сцены); `test/golden-matrix.test.mjs` обновлён на модель активации через
|
||||||
|
`settings.volumetric_view` вместо `alpha`. Корректное, задокументированное
|
||||||
|
решение, не находка.
|
||||||
|
- **Мутационный реестр.** 16 новых мутантов (`iso-tile-ring-visible` …
|
||||||
|
`labs-iso-returns`) — патчи адресуют существующие строки (проверено сверкой
|
||||||
|
`find`-строк с текущим кодом), guard-команды осмысленны и соответствуют
|
||||||
|
названным в таблице приёмки красным сценариям. `de452182` чинит один
|
||||||
|
протухший guard (`stage3-w12-separate-alpha-url-key-restored`) после
|
||||||
|
переименования теста в `e59c89df` — сам факт находки и починки говорит о
|
||||||
|
добросовестной проверке автора (обнаружено собственным Validate, не мной).
|
||||||
|
- **Бюджет бандла.** `INITIAL_VIEW_GZIP_CEILING` 292 600 → 294 900,
|
||||||
|
обоснование (CSS плиток/материалов не может ждать ленивый граф) правдоподобно
|
||||||
|
и арифметически сходится (294 004 замер + 896 Б запаса = 294 900).
|
||||||
|
|
||||||
|
## Чего не проверял
|
||||||
|
|
||||||
|
- `python -m pytest tests_backend` — в песочнице ревью нет модуля `pytest`
|
||||||
|
(`pip show pytest` → not found); полагаюсь на чтение
|
||||||
|
`custom_components/houseplan/validation.py`/`support_package.py` и
|
||||||
|
`tests_backend/test_validation.py`/`test_support_package.py` (проверено
|
||||||
|
построчно одним из под-агентов) плюс на то, что Validate на этом SHA
|
||||||
|
включает backend-джобу по стандартному пайплайну push (`AGENTS.md`,
|
||||||
|
«Gates»). Если backend-джоба Validate не входила в засчитанный success —
|
||||||
|
это стоит явно подтвердить отдельно.
|
||||||
|
- `npm run golden:verify` / `npm run golden:capture` — по тексту AC1/AC12 это
|
||||||
|
предрелизный гейт (iso Stage 6 сцены сознательно не в матрице, baseline
|
||||||
|
ещё не снят на Linux CI); не гейт код-ревью.
|
||||||
|
- Полный `npm test` — принят по зелёному Validate на этом SHA, не перегонял.
|
||||||
|
- Full Performance (AC13) — по тексту AC13 сама предрелизный гейт.
|
||||||
|
- ~70 «слабых» смоков из `smoke-select` (см. таблицу гейтов) — решение по
|
||||||
|
каждому: не запускал, риск для не тронутых по существу систем (стены/
|
||||||
|
диалоги/junction) от этой задачи оцениваю как минимальный.
|
||||||
|
- Настоящий планшет/телефон, Safari, `@supports not (filter)` — эмулировать
|
||||||
|
нечем в песочнице; отмечено и автором.
|
||||||
|
- Наведение мышью в живой лаборатории дизайнера (эталон вложения 11) —
|
||||||
|
недоступно из песочницы; полагаюсь на приложенный кадр `pair-hover.png` и
|
||||||
|
форму рамки, подтверждённую тестами.
|
||||||
|
|
||||||
|
## Вывод
|
||||||
|
|
||||||
|
High: 0. Medium: 1, в скоупе задачи (M1 — обрезка барьерами 2.5D-луча
|
||||||
|
непроверена автотестом, конкретный сценарий регрессии описан выше). Low: 6,
|
||||||
|
правятся по усмотрению автора или сняты с примечанием (L2 снята — опечатка
|
||||||
|
хендоффа, не влияет на решение). Реализация в остальном очень плотная:
|
||||||
|
все числовые формулы (радиус, торец, тень, стены, свет) пересчитаны вручную и
|
||||||
|
совпадают с ТЗ и лабораторией; 9 браузерных смоков прогнаны лично в песочнице
|
||||||
|
и все зелёные; `tsc`/`build`/three-way bundle sync — чисто; docs согласованы
|
||||||
|
с кодом почти везде (кроме отмеченного в L1). Единственная причина жёлтого
|
||||||
|
вердикта — M1: узкий, дёшево устранимый пробел защитного покрытия одного
|
||||||
|
конкретно названного в ТЗ поведения (обрезка барьерами), не общая проблема
|
||||||
|
реализации.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||||
|
|
||||||
|
## Материал раунда
|
||||||
|
|
||||||
|
- Ветка: `issue/649-25d-stage6`, коммит `de4521823ba6` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||||
|
- Дерево материала: `571541905136a48c1729755f6d7877e5ac6aece4`
|
||||||
|
```
|
||||||
|
git log --all --format='%H %T' | grep 571541905136
|
||||||
|
```
|
||||||
|
- Тело issue: `e7d94f185bc9a5d2d7e168933579903e54c88a9819347cb49f0f7c35db60a9e7`
|
||||||
|
- Вердикт конвейера: `yellow` · High 0
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
# Индекс ревью
|
# Индекс ревью
|
||||||
|
|
||||||
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1062, issue: 375. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
|
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1063, issue: 375. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
|
||||||
|
|
||||||
| Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы |
|
| Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы |
|
||||||
|---|---|---|---|---:|---:|---|---|
|
|---|---|---|---|---:|---:|---|---|
|
||||||
| #650 | [CODE-REVIEW-650-r1.md](CODE-REVIEW-650-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
|
| #650 | [CODE-REVIEW-650-r1.md](CODE-REVIEW-650-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
|
||||||
| #649 | [SPEC-REVIEW-649-r1.md](SPEC-REVIEW-649-r1.md) | spec · r1 | 🟡 жёлтый | 0 | 1 | в скоупе задачи (возвращается автору); принято ревьюером с записью, правки не требует | `lab.js` `houseplan-card.ts` |
|
| #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 | [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` |
|
||||||
| #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 | [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-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 | — | — |
|
| #648 | [CODE-REVIEW-648-r3.md](CODE-REVIEW-648-r3.md) | code · r3 | 🟢 зелёный | 0 | 0 | — | — |
|
||||||
|
|||||||
Reference in New Issue
Block a user