Files
houseplan-card/docs/reviews/SPEC-REVIEW-476-r2.md
T
2026-09-06 12:56:13 +00:00

14 KiB
Raw Blame History

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