From 5021c484461879599ab4aad4aefdb3889282cc26 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 20:33:15 +0000 Subject: [PATCH] docs: review document for #662 Issue: #662 User-Visible: no --- docs/reviews/INDEX.md | 3 +- docs/reviews/SPEC-REVIEW-662-r3.md | 243 +++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/SPEC-REVIEW-662-r3.md diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 73670cf6..0fab439a 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,6 +1,6 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 274, issue: 139. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 275, issue: 139. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| @@ -157,6 +157,7 @@ | #663 | [CODE-REVIEW-663-r3.md](CODE-REVIEW-663-r3.md) | code · r3 | 🟢 зелёный | 0 | 0 | — | — | | #662 | [SPEC-REVIEW-662-r1.md](SPEC-REVIEW-662-r1.md) | spec · r1 | 🟡 жёлтый | 0 | 1 | «Входящие» не существует в UI, и текущая классификация каталога кладёт неразмещённую ле…; «Не скоуп» отсутствует внутри формального ## ТЗ | `src/device-inbox.ts` `USER-GUIDE.ru.md` `docs/USER-GUIDE.ru.md` `demo/smoke_led_strip_bind.mjs` `device-inbox.ts` `SPEC-REVIEW-661-r1.md` | | #662 | [SPEC-REVIEW-662-r2.md](SPEC-REVIEW-662-r2.md) | spec · r2 | 🟢 зелёный | 0 | 0 | — | — | +| #662 | [SPEC-REVIEW-662-r3.md](SPEC-REVIEW-662-r3.md) | spec · r3 | 🟢 зелёный | 0 | 0 | — | — | | #661 | [SPEC-REVIEW-661-r1.md](SPEC-REVIEW-661-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | | #661 | [CODE-REVIEW-661-r1.md](CODE-REVIEW-661-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #660 | [SPEC-REVIEW-660-r1.md](SPEC-REVIEW-660-r1.md) | spec · r1 | 🔴 красный | 2 | 1 | Раздел ## ТЗ в теле issue отсутствует целиком; Изменение прямо противоречит двум местам; AC «расстояние уменьшено ровно вдвое» не | `docs/process/AUTHOR.md` `REVIEWER.md` `test/core-file-budget.test.mjs` `scripts/smoke-select.mjs` `demo/helpers/hp-test.mjs` `docs/UX-MODES.md` `docs/reviews/SPEC-REVIEW-647-r1.md` | diff --git a/docs/reviews/SPEC-REVIEW-662-r3.md b/docs/reviews/SPEC-REVIEW-662-r3.md new file mode 100644 index 00000000..7c469e48 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-662-r3.md @@ -0,0 +1,243 @@ +# SPEC-REVIEW-662-r3 + +- **Issue:** https://github.com/Matysh/houseplan-card/issues/662 +- **Этап:** `S4-spec-review` (ревью ТЗ, PROCESS.md §2.4) +- **Трек:** `ask`, подтверждено в r1 и не пересматривается (новый UX-контракт, + более одной поверхности, влияние на touch и на перф — критерии §5). +- **Материал:** + - тело issue #662 в текущей редакции — последняя правка комментарием + Matysh в 2026-10-01T20:22:58Z («Правки ТЗ по материалам дизайнера»); + более новых правок тела на момент ревью нет; + - архив дизайнера `Issue-662-LED-light-spec-2026-10-01.zip`, вложенный + комментарием nikitaevfz-commits в 2026-10-01T15:47:33Z — скачан, + SHA-256 всех 6 файлов сверен с его собственным `MANIFEST-SHA256.txt` и + совпал (`README.md`, `TZ-issue-662-LED-strips.md`, `FIGMA-LINK.url`, + `ISSUE-LINK.url`, `previews/Led-Off.png`, `previews/Led-On.png`); + - оба кадра `Led-Off.png`/`Led-On.png` открыты и просмотрены визуально; + - `docs/reviews/SPEC-REVIEW-662-r1.md`, `-r2.md` — вердикты и материал + прошлых заходов; + - `docs/reviews/CODE-REVIEW-679-r1.md`, `git log` по #679 — проверка + актуальности путей документации, названных в AC14. +- **Заход:** r3 · блокирующих циклов израсходовано 1 из 4 (потрачен r1; r2 — + зелёный, бюджет не увеличивает, PROCESS.md §4) +- **Роль:** ревьюер ТЗ (не автор) + +## Скоуп ревью + +Без изменений по существу с r2: протяжённый источник света (LED-лента) — +ломаная вдоль стен вместо значка в точке, рисуется в редакторе плана +инструментом «LED-лента» (контракт цепочки стен), привязывается к обычному +`light.*` маркеру через диалог «Добавить устройство»; во View/киоске/ +`houseplan-space-card` — капсульная полоса on/off/unavailable с хит-тестом по +всей длине, линейный источник в fill «Свечение», поднята в 2.5D; бэкенд — +схема `led_strips`, инвариант «один маркер — не более одной ленты», per-space +export/import, support package. + +Правка 01.10 добавляет новый слой требований поверх этого контракта: +**визуальный эталон** — макеты дизайнера, которым обязана соответствовать +реализация (решение 11, AC20), фиксированный радиус свечения по умолчанию +50 см вместо «половины общего» (решение 12, заменяет решение 3), точный цвет +ядра в заливке «Свечение» и вне её (решения 13–14), путь материалов +(решение 15). + +SCOPE-проверка не переоткрывается: r1 уже сверил задачу с J1/J7 и «никогда не +строить» — правка 01.10 ничего не меняет в том, какую работу закрывает +задача, только в том, как придирчиво сверяется её внешний вид. + +## Закрытие раунда r2 + +Вердикт r2 — зелёный, находок не было (High: 0, Medium: 0). Закрывать нечего; +раздел ведётся для формы требования §2.10. + +## Унаследовано из r2 (не проверялось повторно) + +Контракт **C1–C5, C8–C12** без изменений текста с r2; **C13** (стены) — также +без изменений текста, полный разбор был выполнен в r2 по правилу «дельта не +локальна». AC1, AC2, AC5, AC7–AC19 (кроме точечных уточнений, разобранных +ниже), UX-тексты, модель данных/миграция, i18n, риски и откат, относящиеся к +этим пунктам, — приняты без повторной проверки на основании +`docs/reviews/SPEC-REVIEW-662-r2.md` (зелёный, материал — тело issue после +комментария 6, закрывшего Medium-1/Low-1 из r1). + +## Разбор по дельте (правки 01.10) + +Проверены все места, изменённые комментарием Matysh 2026-10-01T20:22:58Z: +решения 11–15, раздел «Визуальный эталон», C3 (замыкание ленты по клику в +первую точку), C6 (два штриха V1, сдвиг t/2 у грани V2), C7 (радиус по +умолчанию 50 см), AC3/AC4/AC6 (уточнения), новый AC20, обновлённый список +мутантов, дополнения в «Риски» и «Release-артефакты». + +- Четыре сцены кадров в «Визуальном эталоне» (прямая на полу / прямая у стены + / Г-образная / замкнутый прямоугольник) и их цвета (`#80D5FF`, `#E680FF`, + `#FFEA80`, `#58FF58`) дословно совпадают с перечнем и порядком в + `TZ-issue-662-LED-strips.md` §2.1–§2.2 — сверено построчно, расхождений нет. +- Замеры (ядро 6 px / обводка 3 px, линейное поле ≈100 px, D ≈ 68 px) в + issue совпадают с `TZ-issue-662-LED-strips.md` §2.1/§3 («номинальная высота + белого ядра — 6 px, внешняя обводка — 3 px», «линейное поле — ориентировочная + глубина 86–102 px») — сверено, совпадает в пределах уже заявленной + погрешности. +- Оба кадра открыты визуально: включённая прямая лента на свободном участке + пола (кадр `Led-On.png`) действительно рендерится белым тонким ядром внутри + голубого ореола — подтверждает решение 13 («белое ядро» в заливке + «Свечение») как прочтение именно кадра, а не текста ТЗ дизайнера (см. находку + Medium-1 ниже о его тексте). +- Мутанты `strip-glow-default-radius`, `strip-on-core-colored-in-glow`, + `strip-face-render-offset-off` целятся ровно в новые нормы решений 12/13/V2 — + соответствие есть. +- Нумерация golden-кадров сходится: AC9 даёт 3 сцены, AC20 — ещё 2 + (`led-strip-design-reference-{off,on}-light`), итого 5 — ровно столько, + сколько обещано в «Release-артефакты» («golden: +5 кадров»). + +### Находка Medium-1 — радиус по умолчанию: ТЗ дизайнера противоречит решению 12, расхождение не названо + +Решение 12 (01.10) заменяет прежнее «половина общего радиуса» на +**фиксированные 50 см**, explicitly обосновывая это тем, что «при общих 3 м +половина дала бы поле втрое глубже макета» — то есть решение принято по +изображению кадра, а не по тексту дизайнера. Но committed-архив (который по +решению 15 целиком ляжет в `docs/design/662-led-strips/` под лицензией +репозитория как материал постоянного хранения) в своём собственном +`TZ-issue-662-LED-strips.md` §9 говорит буквально обратное: + +> «Световой источник линейный: по сегментам строятся капсулы радиуса +> `glow_radius_cm`, **а при отсутствии персонального значения — половины +> общего радиуса**.» + +Это дословно формула решения 3, которое решение 12 отменяет +(«~~Радиус свечения без персональной настройки — половина общего.~~ Заменено +решением 12»). Иными словами, письменное ТЗ дизайнера, которое вот-вот +ляжет в репозиторий как канонический референс (и на которое прямо ссылается +AC20 — «таблица… по V1–V6 и критериям 1–10 §11 ТЗ дизайнера»), содержит +значение по умолчанию, прямо противоречащее действующему контракту C7/AC4. + +Ни в разделе «Визуальный эталон» (где перечислены «В продукт не переносятся: +поле поверх значков и подписей (V4), пик ≈0,95… (V5), шов… (V3), толщина +0,18 D… (C6)»), ни в AC14 (`docs/design/662-led-strips/README.md — +происхождение материалов`), ни где-либо ещё в issue это конкретное +расхождение не названо и не объяснено. AC20 требует сравнения с «V1–V6 и +критериями 1–10 §11» дизайнерского документа — а §9 (формула радиуса) не +входит ни в V1–V6, ни в перечисленные 10 критериев §11, то есть у этого +конкретного, уже случившегося расхождения в принципе нет места в +деливерablз, где оно было бы зафиксировано. + +**Почему это находка, а не придирка:** материал, который ляжет в репозиторий +как справочный документ происхождения дизайна, будет без всякой пометки +утверждать значение по умолчанию, обратное тому, что реализует код. Будущий +читатель `docs/design/662-led-strips/TZ-issue-662-LED-strips.md` (включая +код-ревьюера AC14) увидит «половина общего радиуса» рядом с кодом, который +делает «50 см, от общего не зависит», и не найдёт объяснения — ни в этом +файле, ни в README архива, ни в issue. + +**Что нужно:** добавить одну строку — либо к решению 12/C7 в теле issue +(«ТЗ дизайнера §9 здесь заменено решением 12 по причине, см. «Риски»»), либо +явно поручить `docs/design/662-led-strips/README.md` (AC14) аннотировать это +расхождение при коммите архива. Любой из двух вариантов закрывает находку. + +### Находка Medium-2 — AC14 и раздел «Скоуп» называют документы, удалённые #679 + +AC14 требует правок документов «…LIGHT («Linear sources», «Strips and +walls»), **DEVICE-LIGHT-SETTINGS-MATRIX**, USER-GUIDE…, **TESTING-DEMO** +(сущность стенда)…». Та же ссылка на `docs/TESTING-DEMO.md` повторена в +`### Скоуп`: «сущность `light.demo_led_strip`… в seed стенда (`demo/stand`, +`docs/TESTING-DEMO.md`)». + +Оба файла физически отсутствуют в репозитории: + +``` +$ find . -iname "DEVICE-LIGHT-SETTINGS-MATRIX*" -o -iname "TESTING-DEMO.md" +(пусто) +``` + +Оба удалены коммитами #679 (`5a258f31`, `03078038`, смержено 2026-09-27, +**после** r1/r2 этой задачи, выполненных 26.09, — отсюда расхождение не +поймано раньше) и прочитаны/подтверждены в `docs/reviews/CODE-REVIEW-679-r1.md`: +«`LIGHT.md` ← `DEVICE-LIGHT-SETTINGS-MATRIX.ru.md` | файл удалён (-122 +строки), прочитан перенесённый раздел… 36-строчная матрица» и «`TESTING-DEMO.md` +→ `demo/stand/README.md` | файл удалён (-469 строк)…». Содержимое матрицы +сейчас — раздел в `docs/LIGHT.md` (36-кейсовая таблица, тест +`test/devices.test.mjs:1981` подтверждён в том же документе), содержимое про +демо-стенд — `demo/stand/README.md` (прочитан, актуален). + +Правка AC14 на «DEVICE-LIGHT-SETTINGS-MATRIX» избыточна и невыполнима в +буквальном смысле: такого файла для правки не существует, а задача правки +матрицы уже покрыта соседним пунктом «LIGHT («Linear sources», «Strips and +walls»)» — после #679 это один и тот же файл. Для стенда правка должна +указывать на `demo/stand/README.md`, а не на `docs/TESTING-DEMO.md`. + +**Что нужно:** убрать отдельный пункт «DEVICE-LIGHT-SETTINGS-MATRIX» из AC14 +(поглощается пунктом «LIGHT»); заменить `docs/TESTING-DEMO.md` на +`demo/stand/README.md` в AC14 и в «### Скоуп». + +## Проверено и корректно + +- Решения 11–15 внутренне согласованы друг с другом и с контрактом C6/C7/AC3/ + AC4/AC20 (см. «Разбор по дельте» выше) — кроме двух находок. +- Нормы V1–V6 в «Визуальном эталоне» (толщина/цвет/поле/слои/интенсивность/ + переключение) корректно ссылаются на существующие механизмы + (`resolveGlowAppearance`, `GLOW_FALLOFF`, `glowAlpha`, `GLOW_FADE_MS`, + `clipCache`, `mix-blend-mode: lighten`/`screen`) — все эти идентификаторы + существуют в `src/glow-scene.ts`, `src/logic.ts`, `src/glow-blend.ts` + (`find`/`grep` подтверждают присутствие). +- Четыре геометрии и их цвета в описании кадров дословно совпадают между + issue и `TZ-issue-662-LED-strips.md` — сверено построчно. +- AC20 количественно проверяем: пороги названы числом (10 % на углу/стыке, + r/2, r + перо) и методом (смок, golden, ACCEPTANCE.md) — не голословное + «похоже на макет». +- Нумерация golden-кадров (3 из AC9 + 2 из AC20 = 5) сходится с «Release- + артефакты». +- Ссылки `ARCHITECTURE.md` «§Device markers» и «§Markup editor» (AC14) + существуют как заголовки (`docs/ARCHITECTURE.md:209,292`) — не стале. +- `docs/LIGHT.md` «What stops light» существует (используется C13, + унаследовано из r2, перепроверено заодно) — `docs/LIGHT.md:20`. +- Путь материалов `docs/design/662-led-strips/` следует соглашению + `NNN-slug`, уже занятому `600-settings-dialogs`, `649-25d-stage6`; имя + скрипта `capture_design_pairs_662.mjs` в «Плане автотестов» соответствует + прецеденту `demo/capture_design_pairs_600.mjs` — не придумано с нуля. + +## Чего не проверял + +- **Скриншоты/golden не существуют до реализации** — машинные проверки V1–V4 + в `smoke_led_strip_glow.mjs`, сцены `led-strip-design-reference-*` и + `ACCEPTANCE.md` не запускались и не могли: кода нет, это ревью ТЗ. Проверена + только формулируемость и численная проверяемость критериев, не их + фактическое исполнение. +- **Figma-макет напрямую** не открывался (ссылка в архиве недоступна без + логина, как и указано в issue) — нормы сверены только с растровыми кадрами + и письменным ТЗ дизайнера, как и сам автор issue. +- **Пиксельная точность** радиуса 50 см (≈100 px при зуме 202 %, ±10 см + погрешность) не перемерялась линейкой по кадру — проверено на глаз по + открытым изображениям, цифра правдоподобна, но не промерена заново. +- **Гейты кода** (`tsc`, `npm test`, `npm run build`, смоки, golden, мутанты, + pytest) не прогонялись: на этапе `spec` кода нет, зависимости и Chromium не + ставились (#696, см. также AGENTS.md). Это не пропуск гейта, а отсутствие + предмета для него на этом этапе. +- Содержимое `FIGMA-LINK.url`/`ISSUE-LINK.url` не открывалось — чисто + навигационные файлы, не несущие норм. + +## Вывод + +Два Medium **в скоупе задачи**, без отдельного issue (чинятся правкой тела +issue): контракт радиуса по умолчанию расходится с письменным ТЗ дизайнера, +которое вот-вот станет частью репозитория, без единого слова объяснения; +AC14 и раздел «Скоуп» указывают на два документа, которых физически не +существует с 27.09 (#679). Оба — находки о точности и исполнимости ТЗ, а не +о скоупе или ценности задачи: редактор, бэкенд, визуальная механика и план +автотестов по существу не меняются. + +High: 0 · Medium: 2 (обе в скоупе) · Low: 0. + +**Вердикт: жёлтый.** + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `8a3bf71ef19e` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `a76aefce86b8d8f7f8fff9dc26aff23eda74148b` + ``` + git log --all --format='%H %T' | grep a76aefce86b8 + ``` +- Тело issue: `126b0769cbcb4646a96257374bbb4e3a0ad5c64cf6db577a0360e76833e115b4` +- Вердикт конвейера: `yellow` · High 0 · маршрут `fix` +