# SPEC-REVIEW-476-r2 - **Issue:** https://github.com/Matysh/houseplan-card/issues/476 - **Этап:** ТЗ на ревью (PROCESS.md §2.4), заход r2, блокирующих циклов израсходовано 1/4 - **Артефакт ТЗ:** `docs/specs/476-color-picker-ok.md` (ветка `issue/476-color-picker-ok`, HEAD `a29c854f`) - **Предыдущий раунд:** SPEC-REVIEW-476-r1.md, вердикт жёлтый, ревью получено на `acd28558` (SHA восстановлен из `Материал раунда` того же документа — в тексте вердикта issue-комментария SHA не назван, это отдельная находка процесса, см. ниже) - **Трек:** полный (не пересматривался — установлен в r1, дельта его не касается) - **Ревьюер:** Claude (роль «ревьюер ТЗ», отдельная от автора — Codex) ## Дельта r1 → r2 ``` git diff acd28558..a29c854f -- docs/specs/476-color-picker-ok.md ``` Один коммит автора: `a29c854f docs: clarify color picker invalid confirmation` (13 строк, только `docs/specs/476-color-picker-ok.md`, +11/-2). Никакой другой файл дельтой не тронут — продуктовый код, i18n, тесты, changelog не менялись (и не должны были: ТЗ ещё не перешло в код). Правка — только §7.3 «Невалидный HEX» и §18 «Принятые предположения». Изменение локальное и не является ни ребейзом на ушедший вперёд `dev`, ни сменой контракта поведения, ни новой подсистемой: это точечное уточнение механизма против ровно одной r1-находки. Объём разбора этого раунда сведён к дельте и её последствиям (AC4, §7.3, §18, §13 п.2), остальное наследуется из r1. ## Закрытие раунда r1 | Находка r1 | Чем закрыта | Где это видно | |---|---|---| | Medium: §18 предполагал, что confirm вызывает существующий `_commitHex()` и использует его результат — буквальная реализация ломает AC4, потому что повторный `_commitHex()` над уже нормализованным (сброшенным к последнему валидному) `_hexDraft` пройдёт валидацию и снимет `_hexInvalid`, закрыв picker без нового пользовательского ввода | §18 переформулирован: confirm может переиспользовать commit helper, но решение о закрытии выводится не только из нормализованного `_hexDraft`, а из отдельного признака «был ли новый `input` с валидным HEX после неуспешного commit»; признак не сбрасывается нормализацией draft, повторным confirm, blur или переводом фокуса — только новым валидным `input` | `docs/specs/476-color-picker-ok.md` §18, абзац 2 (diff `a29c854f`, +5 строк); идентичная формулировка продублирована в §7.3, последний абзац (+4 строки того же коммита) — обе секции синхронны, не разошлись | | Low: §7.2 шаг 3 («возвращает фокус на trigger») читается как безусловный вне контекста §7.3 | Не правилась — r1 сам снял находку с записью («§7.3 имеет приоритет по построению документа, смысловой неоднозначности, влияющей на AC, нет»), автор не обязан был её чинить | `docs/reviews/SPEC-REVIEW-476-r1.md`, раздел «Low» | Обе строки таблицы содержат конкретную строку текста, а не заявление автора «исправлено» — я прочитал диф и сверил формулировку со сценарием, который сломал бы AC4. ## Проверка дельты по существу Проверил, что новая формулировка §18/§7.3 действительно устраняет математическое противоречие с AC4, а не маскирует его другой недосказанностью: 1. **Логика непротиворечива.** Новый признак — отдельная переменная состояния, не производная от `_hexDraft`/`_hexInvalid`. Она устанавливается неуспешным commit'ом и снимается только `input`-событием с валидным HEX. Blur, повторный confirm и внутренняя нормализация draft внутри commit helper явно перечислены как НЕ снимающие признак — то есть сценарий из r1 («второй confirm над уже-нормализованным draft закрывает picker») больше не проходит: второй confirm видит признак всё ещё установленным и обязан отказать в закрытии. 2. **Технически осуществимо, не только текст.** Сверил с реальным кодом `src/hp-color-opacity.ts`: `_hexInput` (строка 649, обработчик `@input`) и `_commitHex` (строка 663, вызывается по `@blur`/`Enter`/по новому confirm) — уже два разных обработчика, один привязан именно к `input`-событию поля. Новый признак естественно вешается в `_hexInput`, не требуя изобретать несуществующий hook. §18 прямо помечен как «предположения, свободно изменяемые ревьюером» — я не требую от автора большей технической детализации, чем нужно, чтобы AC4 не ломался буквальным прочтением; этого условия текст теперь достигает. 3. **AC4 и план теста (§13 п.2, защитный мутант в §13 п.5 «закрыть surface при invalid HEX») не менялись дельтой и не нуждаются в правке** — они уже требовали ровно то поведение, которое §18 теперь корректно описывает. До правки была нестыковка между «что доказывает тест» и «что предполагает механизм»; после правки оба говорят одно и то же. 4. Не нашёл новой находки, которую внесла бы сама правка (флип в другую сторону, новая недосказанность, рассинхрон между §7.3 и §18) — тексты двух секций идентичны по формулировке, не только по смыслу. Отдельная процессная находка (не по задаче, а по r1-вердикту): SHA, на котором был получен вердикт r1, не назван в тексте issue-комментария с вердиктом («Вердикт: жёлтый · заход r1 …»); я восстановил его из раздела «Материал раунда» документа `SPEC-REVIEW-476-r1.md` (`HEAD acd28558`) и перепроверил по времени коммитов (`acd28558` 13:59:20+03:00 — до `972ef72b` 14:05:47+03:00 публикации r1-документа — до `a29c854f` 14:06:31+03:00 фикса). Это не блокирует данный раунд — документ r1 SHA всё-таки содержал, только не сам комментарий-вердикт. ## Унаследовано из r1 (без повторной проверки) Все пункты ниже не пересматривались: дельта их не касается (правка ограничена §7.3/§18/AC4-механизмом), а источник вывода — `docs/reviews/SPEC-REVIEW-476-r1.md`, получен на `acd28558`: - Сверка фактических утверждений ТЗ о текущем коде/API с исходником (`_emit`, `_closePicker`, `_toggle`, `_outsidePointerDown`, `_keyDown`, disconnect-путь, `ColorPickerLabels` без поля `confirm`, 5 потребителей `showOpacity=false`, плоский формат i18n-ключей в 4 языках, существование и состав пяти golden-сцен, `docs/specs/README.md`) — ни одна не оказалась догадкой, выданной за факт. - Продуктовые вопросы Q1–Q4 закрыты решением владельца без новых открытых пунктов. - Полный трек обоснован (новый наблюдаемый UX-контракт завершения). - §5/§6 скоуп и не-скоуп разделены чётко, граница «расширение контракта → возврат в S3-spec» присутствует. - AC1–AC3, AC5–AC8 сформулированы однозначно, у каждого назван способ доказательства (unit/smoke/golden/docs gate) — дельта их текст не меняла и доказательная база (существующий код/тесты) не менялась тоже. - §9 i18n, §10 модель данных/совместимость/downgrade, §8 touch/a11y, §14 release-артефакты, §16 риски, §17 откат — приняты без повторной проверки, содержимое этих секций дельтой не тронуто. - Роли соблюдены: автор ТЗ (Codex) не рецензирует своё же ТЗ. ## Что проверено и корректно (специфично для r2) - §7.3 и §18 после правки говорят об одном и том же механизме одними словами — не разошлись при редактировании двух мест сразу. - Новый признак технически привязываем к существующему разделению `_hexInput`/`_commitHex` в коде — предположение не голословно. - AC4 и защитный мутант §13 п.5 остаются достижимыми буквальным прочтением исправленного §18 (в r1 буквальное прочтение делало их недостижимыми — сейчас нет). ## Чего не проверял - Не гонял `typecheck`/`test`/`build`/`golden:verify` и `check-docs.mjs` — диф r2 (13 строк одного .md) класса C, продуктовый код не менялся; `check-docs.mjs` для этого коммита уже гонялся автором и указан «passed» в хендофф-комментарии, повторный прогон не добавляет информации к тексту-ревью. - Не пересматривал ничего вне §7.3/§18/AC4 — см. раздел «Унаследовано из r1» с обоснованием, что дельта туда не дотягивается. - Не связывался с владельцем — новых продуктовых вопросов дельта не создала, различие «поле не менялось» vs «новое валидное значение» техническое, не продуктовое. ## Вывод Единственная Medium-находка r1 закрыта точной, синхронной правкой двух секций, логически устраняющей противоречие с AC4, и технически реализуемой на существующей структуре кода. Новых находок дельта не внесла. Вердикт зелёный; бюджет блокирующих циклов не расходуется (израсходовано 1/4, без изменений). --- ## Материал раунда - Ветка: `issue/476-color-picker-ok`, коммит `a29c854f9904` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала: `fa031b74f2bfc5cd4b1eb39cf8e77b6a76386284` ``` git log --all --format='%H %T' | grep fa031b74f2bf ``` - ТЗ `docs/specs/476-color-picker-ok.md`, блоб `d21066d56e69c35fe7d0b40d9f965968dac9f803` ``` git log --all --find-object=d21066d56e69c35fe7d0b40d9f965968dac9f803 -- docs/specs/476-color-picker-ok.md ```