From 6706182a27030d48baa10f21e6f56a0b716c254f Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2026 18:25:53 +0000 Subject: [PATCH] docs: review document for #560 Issue: #560 User-Visible: no --- docs/reviews/CODE-REVIEW-560-r1.md | 154 +++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 docs/reviews/CODE-REVIEW-560-r1.md diff --git a/docs/reviews/CODE-REVIEW-560-r1.md b/docs/reviews/CODE-REVIEW-560-r1.md new file mode 100644 index 00000000..db77c621 --- /dev/null +++ b/docs/reviews/CODE-REVIEW-560-r1.md @@ -0,0 +1,154 @@ +# CODE-REVIEW-560-r1 + +Issue: #560 «Корпус геометрий, household-сценарии и аудит доступности View» +Материал: `db7eef530635b699a72c3cf978a7df79db99fcbd`, ветка `issue/560-quality-field-corpus` +на `dev` (`a03ccd65`), один коммит. +Заход: r1 · блокирующих циклов ревью 0 из 4 (лимит для инфраструктурного/полного трека — 4) + +## Скоуп + +Задача — прямое поручение владельца по оставшемуся пункту независимого аудита +(12.09.2026): усилить доказательства View household-сценариями и корпусом +пользовательских геометрий. Инфраструктурная постановка (`infra`, без +продуктовых `S*`-статусов до `S7-code-review`), явно **research/tests-only**: +диффу запрещено трогать `src/**` и `custom_components/**`, а находки — +заводиться отдельными issue, а не чиниться здесь. + +`git diff origin/dev...HEAD --stat` подтверждает границу: только +`demo/**`, `test/**`, `scripts/mutation-registry.mjs`, `docs/QUALITY-560.md` — +класс B/C, ни одного файла класса A. Трейлеры коммита: `Issue: #560`, +`User-Visible: no` — корректны, продуктового поведения нет. + +Три направления приёмки (SCOPE J1/J2/J3/J6): +1. household-сценарии View на двух ширинах карточки; +2. аудит доступности текущего View; +3. обезличенный geometry corpus (import → Optimize → Optimize → Resize → + save/reload → export) с численными оракулами. + +## Как проверялось + +Ревью независимое: сессия без контекста реализации, материал не редактировался. +Дешёвые гейты (`tsc`, `npm test`, `npm run build`) уже подтверждены зелёным +прогоном Validate на этом самом SHA — перепрогонять не стал, а сверил сам факт: + +| гейт | результат | +|---|---| +| Validate (CI) на `db7eef53` | `gh run view 34773796018` → `conclusion: success`, `headSha: db7eef53...` — совпадает | + +Что прогнал сам (соразмерно диффу и AC, не входит в «дешёвый» набор, зафиксированный Validate): + +| гейт | команда | результат | +|---|---|---| +| build (нужен как база для смоков) | `npm run build && npm run bundle:sync` | зелёный, дерево бандла не изменилось (`git status` чист после) | +| unit-тесты | `npm test` | `2679` тестов, `2678` pass, `0` fail, `1` skip — совпадает с заявленным «2678 / 0 / 1 skip (+35)» | +| новый браузерный смок 1 | `node demo/smoke_household_journeys.mjs` | `OK`, все числа (J4 15 остановок Tab, F1 390px владельцы `dense2,dense3,dense4,dense5,dense5`, J7 780px владельцы `dense1..dense5`) совпадают с `docs/QUALITY-560.md` | +| новый браузерный смок 2 | `node demo/smoke_geometry_corpus.mjs` | `OK`, числа (3 комнаты, толщины `20,20,20,20,20,20,20,22,33,33` до/после ресайза, 2 комнаты+1 проём для c4) совпадают с отчётом | +| mutation-gate — 4 новых мутанта, по одному | `node scripts/mutation-gate.mjs --id=` × 4 | все 4: «поймано 1 из 1» (см. таблицу ниже) | +| mutation-gate anchors | `node scripts/mutation-gate.mjs --check` | без нарушений | +| process-gate | `node scripts/process-gate.mjs --issues` | «гейт пройден», 1 WARN (см. находку Low ниже) | +| check-docs | `node scripts/check-docs.mjs` | passed (диффу не требовался — `src/**` не тронут) | +| smoke-select | `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | «исполняемого frontend-диффа нет, browser-smoke этим диффом не выбираются» — ожидаемо для инфра-трека без `src/**` | +| model-invariants CLI (сверка численных оракулов вручную) | `node scripts/model-invariants.mjs --config ... --layout ...` на `c6-stale-layout` | «Нарушений: 2» — `references/layout_space` × 2, совпадает с `expectedViolations` теста и находкой #566 | +| приватность фикстур | `grep` по `test/fixtures/560-corpus/*.json` на `sensor.\|light.\|binary_sensor.\|climate.\|lock.` | ничего не найдено; маркеры в геометрических фикстурах — пустые массивы | + +Не прогонял и почему: +- `golden:verify`, `performance_smoke`, `python -m pytest tests_backend` — diff не + трогает `src/**` (рендер и стили не менялись) и не трогает `custom_components/**/*.py`; + ни один AC не требует визуального или бэкенд-гейта. +- Полный набор `demo/smoke_*.mjs` — `smoke-select` прямо сообщил, что выбирать + нечего (frontend не менялся); два новых смока прогнаны напрямую целиком. + +## Находки + +### Low — `process-gate` даёт 1 предупреждение, а хендофф заявляет «предупреждений 0» + +`node scripts/process-gate.mjs --issues` на этом дереве печатает: +``` +WARN п.8 статус issue - инфраструктурный диапазон (#562): файлов класса A нет, +статусная метка не требуется до S7-code-review +гейт пройден, предупреждений 1 +``` +Это ожидаемое, безопасное предупреждение — оно печатается всегда для +инфраструктурного диапазона по дизайну (`scripts/process-gate.mjs:806-813`, +комментарий «пропуск обязан быть виден»), гейт всё равно зелёный. Расхождение +чисто в тексте хендоффа («предупреждений 0» вместо факта «1»), не в существе +проверки. Не блокирует; правится или снимается автором с примечанием. + +Третий столбец («чем краснеет») для этой находки не нужен — она не о защите, а +о точности отчётной цифры. + +## Что проверено и корректно + +- **Границы задачи соблюдены.** Ни одного файла класса A в диффе; все три + находки уровня High/Medium (F1 «390px — соседний маркер», F2 «контраст + подписей 2,01:1», F3 «активная вкладка без ARIA-состояния») и Low (F4, F5, + F6) заведены отдельными issue со ссылкой на #560 — проверил напрямую: + `#564` (High, bug, P1, S1-new), `#565` (Medium+Low, bug, P2, S1-new), `#566` + (Low, tech-debt, P3, S1-new) существуют, открыты, корректно размечены. + Ничего не оставлено как TODO внутри документа ревью/отчёта. +- **Приватность данных.** Реальный план владельца (5 пространств/37 комнат/121 + запись толщины и т.д.) в репозиторий не попал — фикстуры `test/fixtures/560-corpus/*.json` + синтетические, воспроизводят условия числами; маркеры пустые, ссылок на + реальные HA-сущности нет (проверено grep). +- **Каждый AC приёмки закрыт и доказан исполнением, не чтением:** + - «персона/вход/действие/независимый oracle» — семь J-путей в + `demo/smoke_household_journeys.mjs` прогнаны, оракулы независимые + (вызов `light.turn_off`, `aria-label`, `data-state`, а не факт наличия + класса) — подтверждено запуском, числа совпали. + - «geometry corpus не принимает рендер как эталон» — оракулы в + `test/geometry-corpus.test.mjs` численные (инварианты, immutability + Optimize, фикс-пойнт #477, сохранность записей толщины, независимый + пересчёт `wallKey`); браузерная половина проверяет только присутствие + узлов и попадание в `viewBox`, не пиксели — прочитано и прогнано. + - **Тест умеет падать.** Для двух product-facing защит (клавиатурная + доступность маркера, вызов действия по Enter/Space) и двух свойств самого + корпуса (фикстура несёт условие, `changed` не врёт) прогнаны названные + мутанты — все 4 «поймано 1 из 1» (перепроверено мной лично, не с чужих слов). + - «bounded corpus, без бесконтрольного роста» — 6 фикстур × (свой тест + условия + 3 теста цепочки) + 2 сквозных теста = 26, как заявлено; синтетика + (`c3-x-junction`) прямо помечена как таковая и в тесте, и в отчёте. + - «итог отделяет bugs от гипотез» — раздел 6 `docs/QUALITY-560.md` называет + U1–U3 гипотезами именно потому, что без людей (screen reader, + color-blindness sim, доброволец) не проверяются; это не притворство + решением, а честно обозначенная граница. +- **Числа отчёта воспроизводимы**, а не переписаны на веру: гоняя оба новых + смока и `npm test` заново, получил те же цифры, что в `docs/QUALITY-560.md` + (включая тонкие — 1,6 px запас на 780px, 15 остановок Tab, `rev`-независимые + толщины). Ни одного «verified» без названной команды в материале нет. +- **Единый источник числа.** Диф не вводит ни одной новой пользовательской + величины (не продуктовый код); дублирования вида «превью против записи» + не создаётся. + +## Чего не проверял и почему (сверх раздела «как проверялось») + +- Не проверял вручную полевую установку владельца — по постановке задачи это + read-only полевая часть текущего захода, она не воспроизводима вне сессии + автора и с чужой машины не перепроверяется; профиль (числа) сверен на + внутреннюю согласованность с корпусом, а не с самим домом. +- Не гонял скринридер/цветовую симуляцию — U1–U3 прямо помечены как гипотезы, + не как заявленные доказанные AC; требовать здесь исполнимый oracle было бы + спором с самой постановкой задачи (research/tests-only, без людей в этом заходе). + +## Вердикт + +Единственная находка — Low, редакционная неточность в тексте хендоффа +(«0» вместо фактических «1» предупреждения `process-gate`, само предупреждение +ожидаемо и не является нарушением). High/Medium в материале нет. Задача решает +заявленный сценарий (усиление evidence по трём направлениям аудита) без +деградации соседнего поведения — продуктовый код не тронут вовсе. + +**Зелёный.** + +--- + + + +## Материал раунда + +- Ветка: `issue/560-quality-field-corpus`, коммит `db7eef530635` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `eea41e91476fced5276e10601e5d29ad1bd6642b` + ``` + git log --all --format='%H %T' | grep eea41e91476f + ``` +- Тело issue: `0ab01902457f91e2bbe866f790b19fb58567ef790403214e6886dc7df209ac70` +- Вердикт конвейера: `green` · High 0