Files
houseplan-card/docs/reviews/SPEC-REVIEW-615-r2.md
2026-09-24 02:31:24 +00:00

19 KiB
Raw Permalink Blame History

SPEC-REVIEW — issue #615 · заход r2

Задача: «Плитки палитры после #605 всегда сплошные: «No lights» с прозрачностью 0 % выглядит насыщенным цветом» Этап: ТЗ на ревью (S4-spec-review) · трек small · лимит циклов ревью ТЗ — 2 Заход: r2 · блокирующих циклов израсходовано 1/2 до этого вердикта

Скоуп разбора

Второй раунд — разбор по дельте (PROCESS.md §2.9, issue #214), не заново. Причина сужения: единственная находка r1 (Medium M1, PROCESS.md §2.7) касалась ровно одного столбца одной строки таблицы AC (AC3, «чем краснеет»/«чем доказан»), не задевала контракт поведения как целое, не переоткрывала выбор между шахматкой/полосой альфы и не меняла ни продуктовую рамку (сценарий, персона, поверхность), ни AC1/AC2/AC4. Владелец подтвердил в комментарии r2 («Остальное ТЗ ревью r1 признало корректным, там ничего не менялось»), что правка точечная. Дельта не подпадает ни под одно условие полного разбора из брифинга (ребейз, смена контракта поведения, новая подсистема, объём дельты ≈ объёму задачи): правка — это разбитая на (а)/(б)/(в) формулировка AC3 плюс её эхо в скоупе, п.7 контракта, плане автотестов и рисках. Поэтому разбор ограничен тем, что задевает эта дельта, остальное унаследовано (см. раздел ниже) без повторной проверки.

Как найден заход r1 и материал этого раунда

  • Вердикт r1 найден в комментарии issue от 2026-09-24T00:55:49Z (github-actions): жёлтый, High 0, Medium 1 в задаче. Документ: docs/reviews/SPEC-REVIEW-615-r1.md (файл присутствует в рабочей копии).
  • SHA материала r1 в вердикте не назван отдельной строкой в issue-комментарии, но документ r1 сам несёт якорь: ветка dev на коммите 9d1d27325d7f, дерево материала 2b3f9bb13865aa81206dba3cd06f7b1cf151dd93, тело issue на тот момент — хеш 160aa133569bbc2145349668472db875bb0326975c789bd2b48b76511222101f. Для спек-этапа код не менялся между r1 и r2 (обе редакции — правка текста issue), это подтверждает независимая сверка: git log --oneline -- docs/reviews/SPEC-REVIEW-615* и git branch -a не показывают отдельной ветки/PR для #615 — задача ещё не вышла из этапа ТЗ.
  • Дельта текста issue не доступна как git-diff (GitHub не версионирует тело issue через API этого токена: gh api repos/.../issues/615/timeline не вернул событий edited с содержимым правки). Источник дельты — комментарий владельца 2026-09-24T02:23:00Z («ТЗ r2 — ответ на SPEC-REVIEW-615-r1»), который прямо перечисляет, что изменилось, и текущее тело issue (## ТЗ с явной пометкой «Редакция r2»). Оба сверены построчно с находкой M1 из r1 (см. ниже) — расхождений с заявленным перечнем правок не найдено.

Что проверено в этом раунде (дельта)

Находка M1 указывала: AC3 утверждает, что защита от расползания режима на плашки цвета (Wall fill, фон General и т. д.) «уже существует и остаётся» — а на деле такой проверки нет ни в одном demo/smoke_*.mjs, ни в test/.

Правка r2 заменяет это на явную новую проверку AC3(б). Я перепроверил каждую техническую деталь новой формулировки против реального кода (не веря заявлению «исправлено», а проверяя названные объекты):

  • .hpf-colorfield — существующий класс, colorField() в src/editors/form-kit.ts:275.
  • .hpf-opacity input — существующий узел внутри colorField(), src/editors/form-kit.ts:278-284.
  • data-card="plan" — существующий id секции Wall fill, src/editors/general-settings-dialog.ts:140 (Wall fill — единственный colorRow внутри этой секции, строки 143-154).
  • .hpf-card[data-card="plan"] .hpf-colorrow .hpf-opacity input — не гипотетический селектор: он уже используется сегодня в demo/smoke_general_settings_form.mjs:65 для того же самого действия (ввод числа в поле % Wall fill), только там проверяется запись в конфиг, а не вычисленная непрозрачность.
  • flatSwatch && !coverSwatch — соответствует реальным атрибутам компонента (src/hp-color-opacity.ts:76-77, flat-swatch/cover-swatch); Wall fill в разметке (general-settings-dialog.ts:150) имеет flat-swatch без cover-swatch — ровно то условие, которое просит проверить AC3(б).
  • «При α=1 (как у фона General, showOpacity=false) протечка не видна» — подтверждено: general-settings-dialog.ts:181, .opacity=${1} .showOpacity=${false} для bg_color. Значит выбор Wall fill (α=0.4, showOpacity=true) как представительной плашки — не произвольный, а единственный вариант, на котором протечка вообще проявится.
  • «(а) … условие opacity === '1' в oneSurface для плиток заменяется проверкой AC1» — сверено с реальной строкой demo/smoke_dialog_polish_605.mjs:40 (getComputedStyle(painted).opacity === '1' внутри oneSurface, которая сегодня верна для всех плиток, потому что плитки сегодня всегда непрозрачны — то есть после реализации AC1 это условие действительно станет неверным для α<1 и требует замены, как и написано).
  • «Без (б) этот мутант [M-615-plate] выживает» — логически верно: сегодня в demo/*.mjs и test/ нет ни одной ассерции на getComputedStyle(...).opacity для .hpf-colorfield/.hpf-colorrow (это и было находкой M1), и правка явно добавляет её как часть AC3, а не оставляет как «уже есть».

Итог: M1 закрыта не декларативно, а предметно — новая формулировка называет реальные, существующие сегодня селекторы и значения, а не воображаемые. Ложного ощущения прикрытого регресса, о котором предупреждало PROCESS.md §2.7, новая редакция не создаёт.

Дополнительно проверено остальное эхо этой дельты (обязательное действие §2.9 — проверять и то, до чего дельта дотягивается, не только саму находку):

  • Скоуп: добавлена строка «Новая проверка в смоке, что плашки цвета остаются сплошными (AC3). Сегодня такой проверки нет» — согласуется с M1 и с кодом.
  • Контракт п.7 (плашки остаются сплошными при любом α, flat-swatch без cover-swatch) — переформулирует то, что раньше было только в «Не-скоупе», как явный пункт контракта; поведенчески ничего нового не описывает (плашки и так сплошные сегодня, это подтверждено r1), это не смена контракта, а его явное проговаривание применительно к AC3(б).
  • План автотестов: три мутанта вместо двух (добавлен M-615-plate) — согласуется с таблицей AC3.
  • Риски: «протечка на плашки… защита — новая проверка AC3(б) и мутант M-615-plate» — согласуется, не противоречит остальным рискам.
  • «Принято предположительно»: добавлен пункт про одну представительную плашку — корректно помечен как решение, которое можно поменять свободно, продуктового вопроса не требует (сама техника защиты — не то, что видит пользователь).
  • Редакторское (не находка, как отметил и владелец): в AC2 восстановлено имя свойства («вычисленный color подписи…») — сверено с текущим текстом, совпадает.

Однозначность AC3 после правки: наблюдаемый результат, способ доказательства и условие красноты не расходятся — таблица читается без домысливания.

Унаследовано из r1

Без повторной проверки в этом раунде приняты (документ docs/reviews/SPEC-REVIEW-615-r1.md, материал на коммите dev@9d1d27325d7f, дерево 2b3f9bb13865aa81206dba3cd06f7b1cf151dd93):

  • Обязательные разделы §7.1 присутствуют все, продуктовая рамка (сценарий, что видит человек, персона — администратор дома, поверхность — General settings, не View) верна и соответствует docs/SCOPE.md.
  • Описание проблемы и её механизм (src/hp-color-opacity.ts:852, src/editors/form-kit.ts:316, src/logic.ts:1436-1438) — точны.
  • Скоуп/не-скоуп (кроме добавленной строки про новую проверку, см. выше) — соответствуют реальному состоянию src/editors/*.ts и docs/USER-GUIDE.ru.md.
  • AC1 и AC2 — полноценные, с реалистичной таблицей «чем краснеет»; правка r2 их не трогала (кроме восстановленного имени свойства в AC2, проверено выше).
  • AC4 — корректно ссылается на предрелизный гейт golden, не требует пересъёмки в задаче.
  • Классификация трека small (не trivial) — обоснована, дельта её не меняет.
  • Отсутствие продуктовых вопросов владельцу — подтверждено повторно и в r2 (комментарий владельца: «Продуктовых вопросов нет»); правка M1 была технической, что и предписывает процесс («технический вопрос, вынесенный владельцу, — замечание»), поэтому её решил сам владелец текстом ТЗ, а не вопросом.

Закрытие раунда r1

Находка r1 Чем закрыта Где это видно
M1 (Medium, в скоупе): AC3 называет несуществующую защиту плашек («остаётся», «краснеет») как факт, хотя такой проверки сегодня нет ни в demo/*.mjs, ни в test/ AC3 разбит на (а) существующие проверки для плиток / (б) новая проверка этой задачи, явно названная как отсутствующая сегодня и создаваемая в рамках этой же задачи / (в) регресс-смоки. «Остаётся» заменено на конкретный сценарий: flatSwatch && !coverSwatch у всех hp-color-opacity внутри .hpf-colorfield General, плюс проверка Wall fill после ввода 40 — .swatch opacity '1', .trigger backgroundImage 'none'. Названо, почему без (б) мутант M-615-plate выживает Тело issue #615, раздел «Критерии приёмки», строка AC3 (столбцы «Наблюдаемый результат» / «Чем доказан» / «Чем краснеет»); эхо в разделах «Скоуп», «Контракт поведения» п.7, «План автотестов», «Риски», «Принято предположительно»

Находки

Нет. Ни High, ни Medium в этом раунде не обнаружено.

Что проверено и корректно

  • Все выше перечисленные технические детали AC3(б) (селекторы, атрибуты, значения) сверены построчно с src/editors/form-kit.ts, src/editors/general-settings-dialog.ts, src/hp-color-opacity.ts и с существующими demo/smoke_dialog_polish_605.mjs, demo/smoke_general_settings_form.mjs — расхождений нет.
  • Выбор Wall fill как представительной плашки логически обоснован кодом (только у неё showOpacity=true и α≠1 по умолчанию среди плашек General), а не произволен.
  • Новая формулировка AC3 не открывает продуктового вопроса и не меняет видимое поведение — это по-прежнему только описание того, как задача защищает существующий (не меняющийся) не-скоуп.
  • Однозначное число, видимое пользователю (%, hex, вычисленная непрозрачность свотча) — не дублируется независимыми источниками: подпись % и опорная непрозрачность CSS-слоя оба выводятся из одного и того же α конфигурации; задача не вводит второй источник этого числа. test/single-source-numbers.test.mjs здесь не задет диффом текста ТЗ и не требует прогона на этом этапе (кода ещё нет).

Чего не проверял

  • Реализация ещё не существует (этап ТЗ) — typecheck/test/build/golden/ мутанты не прогонялись, неприменимо.
  • AC1, AC2, AC4, сценарий, не-скоуп (кроме одной добавленной строки), i18n, модель данных — не перепроверялись заново в этом раунде, так как дельта их не касается; приняты по r1 (см. «Унаследовано из r1»).
  • Точный список золотых кадров, которые изменит правка (AC4) — как и в r1, это ответственность хендоффа/предрелизного гейта, не спецификации.
  • Само существование мутанта #605 рядом в реестре — как и в r1, подтверждено, что его нет; создание мутантов (M-615-tile/label/plate и, если нужно, для #605) — часть будущей реализации, не находка ни в одном из раундов.

Вердикт

Единственная находка предыдущего раунда закрыта предметно, новых находок нет. По §2.4/§4 PROCESS.md — зелёный вердикт. Бюджет циклов не расходуется (зелёный вердикт цикла не образует, #227): израсходовано остаётся 1/2.


Материал раунда

  • Issue: #615, репозиторий Matysh/houseplan-card.
  • Материал: тело issue (раздел ## ТЗ, редакция r2) на момент разбора, плюс комментарий владельца 2026-09-24T02:23:00Z как источник объявленной дельты.
  • Предыдущий раунд: r1, документ docs/reviews/SPEC-REVIEW-615-r1.md, вердикт жёлтый, материал — тело issue на момент разбора r1 (хеш тела 160aa133569bbc2145349668472db875bb0326975c789bd2b48b76511222101f, привязан к dev@9d1d27325d7f).
  • Вердикт этого раунда: зелёный · High 0 · Medium 0.

Материал раунда

  • Ветка: dev, коммит 4de5c0c0b52f — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 76cc0be454bbeaef33572c4613230b39b506fd9e
    git log --all --format='%H %T' | grep 76cc0be454bb
    
  • Тело issue: c97b73a26ff6fd7f6f98066a8188d815fbfac1ad9db4ed0085317efe13f01a30
  • Вердикт конвейера: green · High 0