21 KiB
SPEC-REVIEW-647-r2
- Issue: https://github.com/Matysh/houseplan-card/issues/647
- Этап:
S4-spec-review(ревью ТЗ, PROCESS.md §2.4) - Трек:
small(лёгкий), по аналитике автора в комментарии «Аналитика» - Материал: тело issue #647, раздел
## ТЗ, редакция r2 (снимок на момент этого ревью, 2026-09-25); предыдущий комментарий-ответ автора «ТЗ r2 — ответ на SPEC-REVIEW-647-r1» - Заход: r2 · блокирующих циклов израсходовано 1 из 2 (лёгкий трек)
- Роль: ревьюер ТЗ (не автор)
Скоуп ревью
Редакция r2 — прямой ответ на жёлтый вердикт SPEC-REVIEW-647-r1 (0 High,
2 Medium, оба в скоупе, закрываются правкой текста). Дельта локальна: автор
переписал п.4 «Скоупа», добавил К5/К6 в «Контракт поведения» и AC5/AC6 в
таблицу доказательств, расширил «Release-артефакты» (docs/UX-MODES.md) и
уточнил «UX, i18n» по touch-контракту; заодно поправил абзац «Проблема (по
коду)», испорченный в r1 форматированием (вложенные обратные кавычки).
Остальные разделы ТЗ (сценарий, «что человек увидит», не-скоуп, план
автотестов, риски, откат, «принято предположительно») не менялись по
существу.
По правилу «объём разбора по дельте» (PROCESS.md §2.10) разбор ниже
сосредоточен на: (а) действительно ли новый текст закрывает Medium-1 и
Medium-2 из r1, (б) не создали ли сами правки новой неоднозначности или
непроверяемого AC. Разделы, не задетые дельтой и уже проверенные в r1 (состав
обязательных §7.1, точность описания кода «как есть», удаление ключа
count.devices, не-скоуп, план автотестов, трейлеры), приняты без повторной
проверки — см. «Унаследовано из r1» ниже.
Как проверялось
- Сопоставлен текст комментария автора «ТЗ r2 — ответ на SPEC-REVIEW-647-r1» построчно с находками r1 (Medium-1, Medium-2) — заявленные правки существуют в текущем теле issue дословно там, где автор их называет.
- Перечитан весь текущий раздел
## ТЗцеликом (не только изменённые абзацы), чтобы делта не читалась в отрыве от контекста — противоречий между новыми К5/К6/AC5/AC6 и остальным текстом не найдено. - Проверено закрытие Medium-1 (риск: новый слот наследует
@media (max-width: 1100px) { .head .count { display: none } }и прячет крестик на обычной ширине):- п.1 «Скоупа» теперь явно удаляет само правило
.head .countвместе со счётчиком («оно станет мёртвым»), а не просто оставляет его висеть; - п.2 явно требует для слота «собственный класс... не
.countи без наследования его правил»; - п.4 переписан: «слот виден и занимает своё место на любой ширине, где видна группа кнопок режимов (в том числе 721–1100 px, где счётчик скрывался)»;
- добавлен К6 и AC6 с прямой проверкой видимости/клика × на 390/768/1000/
1400 px через
elementFromPoint, с мутантом «слоту правило скрытия как у.count» → смок красный на 1000 и 768 px. 1000 px лежит внутри диапазона 900–1100 px, который r1 просил проверить явно. Три независимых слоя защиты (переписанный скоуп, явный запрет наследования, тестируемый АС с мутантом) закрывают находку с запасом.
- п.1 «Скоупа» теперь явно удаляет само правило
- Проверено закрытие Medium-2 (риск: контракт hit-target ≥24×24 px из
docs/UX-MODES.md:41-44не упомянут в ТЗ и не защищён AC, документ не входит в Release-артефакты):- новый К5: «Кликабельная зона × — не меньше 24 × 24 CSS px
(
getBoundingClientRect()...), глиф — 13 px; клик в точку, отстоящую от центра глифа на 10 px..., закрывает редактор (как в #195)» — дословно воспроизводит контракт из UX-MODES.md и метод регрессионной проверки из истории #195; - новая строка AC5 в таблице с named-мутантом «размер слота 13 px (переменная) → смок красный» — защитный AC теперь имеет непустой третий столбец;
- «Release-артефакты» теперь называют
docs/UX-MODES.mdявно: «строка про panel-host (убрать «device count»...) и абзац про × (× — в отдельном слоте..., hit target ≥ 24 × 24 px сохранён)»; - «UX, i18n» теперь содержит явное обоснование вместо голого утверждения: «Touch: размер кликабельной зоны × не уменьшается (≥ 24 × 24, как сейчас)...» — это уже не непроверенное заявление из «Аналитики» r1, а требование ТЗ со своим AC.
- новый К5: «Кликабельная зона × — не меньше 24 × 24 CSS px
(
- Прочитан
docs/UX-MODES.mdещё раз (строки 1–50) и сверен построчно с планом Release-артефактов r2: строка 14 («...device count, zoom and actions remain») и абзац строк 33–44 (крестик как часть кнопки-режима, «hit target of at least 24 × 24 px without changing the tab's layout footprint») — оба фрагмента действительно устареют после правки и оба поимённо покрыты планом автора («строка про panel-host» и «абзац про ×»). Расхождений между тем, что попросил ревью r1, и тем, что реально устареет в документе, нет. - Проверено состояние кода на материале ревью (SHA
1ba4c23a,git show --stat HEAD,git branch -a,git log --oneline --all | grep 647): для #647 в дереве нет ничего, кроме коммитаdocs: review document for #647(добавляет только сам документ r1 и строку вdocs/reviews/ INDEX.md); веткаissue/647-toolbar-stable-widthв этом чекауте отсутствует — код ещё не написан. Это подтверждает, что на этапеspecгейты (tsc,npm test,npm run build,check-docs.mjs, смоки,golden) неприменимы: сверять их не с чем,src/**в материале не меняется. Ровно так же поступил ревьюер r1 (см. его «Чего не проверял»). - Перепроверены факты кода, на которые опирается r2 (не только цитаты
ТЗ, а сам код):
src/styles/dialogs.styles.ts:27-29(правило.head .count,max-width: 1100px),src/styles/chrome.styles.ts:154-172(.modetab .closex, 24×24 хит-зона через отрицательные поля),src/houseplan-card.ts:10811,10820(крестик внутри активной кнопки,<span class="count">отдельным элементом) — совпадает с описанием «Проблема (по коду)» дословно, включая уже исправленный в r2 абзац (нет разрушенных обратных кавычек, текст читается корректно). - Проверен
docs/reviews/INDEX.md— строка#647 | SPEC-REVIEW-647-r1.md | spec · r1 | 🟡 жёлтый | 0 | 2 | ...присутствует и соответствует документу r1; смежные подсистемные записи (#195code · r1/r2 — оба 🟢,#437— источник сводной панели) подтверждают исходные ссылки ТЗ на историю контрактов. - Перечитаны
docs/SCOPE.mdиdocs/process/REVIEWER.mdзаново для этого захода (без изменений в применимости выводов r1: задача обслуживает J1/J6 как polish уже принятого механизма переключения режимов, вне скоупа не выходит).
Гейты не гонялись — этап spec, материал ревью текстовый (тело issue), в
дереве материала (SHA 1ba4c23a) для #647 нет диффа src/**, test/**
или demo/**: код появится только после перехода в S5-ready/S6-in-progress
и будет предметом код-ревью. Это не сокращение объёма, а соответствие
самому этапу — гейты §8 привязаны к диапазону коммитов, а не к тексту
issue.
Находки
Не найдено. Оба Medium из r1 закрыты правкой текста ТЗ, новых неоднозначностей, непроверяемых AC или противоречий делта не внесла.
Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
Medium-1: п.4 ТЗ дословно предлагал унаследовать .head .count's @media (max-width: 1100px){display:none}, крестик мог исчезнуть на обычной ширине 721–1100 px, ни один AC это не ловил |
П.1 «Скоупа» удаляет само правило .head .count, а не наследует его; п.2 явно запрещает слоту класс .count и наследование его правил; п.4 переписан («слот виден... в том числе 721–1100 px, где счётчик скрывался»); добавлен К6 + строка AC6 с мутантом «правило скрытия как у .count → красный на 1000 и 768 px» |
Тело issue #647, раздел «Скоуп» п.1–п.2, п.4 «Адаптивность»; раздел «Контракт поведения» К6; таблица «AC · чем доказан · чем краснеет», строка AC6 |
Medium-2: контракт hit-target ≥24×24 px (docs/UX-MODES.md:41-44, issue #195) не упомянут в ТЗ, нет защищающего AC, docs/UX-MODES.md не в Release-артефактах, «Аналитика» заявляла «hit area прежние» без обоснования |
Добавлен К5 (дословно воспроизводит контракт ≥24×24 px и метод проверки как в #195); добавлена строка AC5 с мутантом «размер слота 13 px (переменная) → смок красный»; «Release-артефакты» теперь называют docs/UX-MODES.md (обе строки: про panel-host и про ×); «UX, i18n» содержит явное обоснование вместо голого утверждения |
Тело issue #647, раздел «Контракт поведения» К5; таблица AC, строка AC5; раздел «Release-артефакты»; раздел «UX, i18n, модель данных» |
Унаследовано из r1 (принято без повторной проверки)
Материал: docs/reviews/SPEC-REVIEW-647-r1.md, SHA дерева 973c05543e3f...
(якорь того раунда). Делта r2 не касается перечисленного ниже, поэтому
повторно не перепроверялось:
- Обязательные разделы §7.1 присутствуют все (сценарий, «что человек увидит до/после», проблема, скоуп/не-скоуп, UX/i18n/модель данных, план автотестов, риски, откат) — r1, раздел «Что проверено и корректно».
- Описание бага «по коду» и границы правки совпадают с
src/houseplan-card.ts:10797-10820— r1, п.6 «Как проверялось» (в r2 перепроверено повторно в п.7 этого документа, поскольку абзац редактировался; расхождений нет). - Безопасность удаления ключа
count.devices(единственное место чтения, сводная панель #437 использует другой источник) — r1, п.7 «Как проверялось». - AC1–AC3 однозначны и привязаны к способу доказательства с непустой колонкой «чем краснеет» — r1, «Что проверено и корректно» (нумерация AC1–AC3 в r2 не изменилась по содержанию, только сдвинулась таблица вниз добавлением AC5/AC6).
- Не-скоуп сформулирован явно, без пересечения с #437 — r1, «Что проверено и корректно».
- План автотестов ссылается на реально существующие механизмы
(
test/core-file-budget.test.mjs,scripts/smoke-links.mjs,scripts/mutation-registry.mjs,scripts/smoke-select.mjs, фасадdata-hp="mode-tab") — r1, п.10 «Как проверялось». - Трейлеры
User-Visible: yesи требование обоих changelog в одном коммите — r1, «Что проверено и корректно». - Открытых продуктовых вопросов владельцу нет — r1, «Что проверено и корректно»; в r2 не появилось новых.
Что проверено и корректно
- Оба Medium из r1 закрыты по существу (не декларативно): каждое — переписанным текстом скоупа/контракта и новым тестируемым AC с названной мутацией, а не только обещанием в комментарии автора.
- Новые К5/К6 и AC5/AC6 однозначны, ссылаются на конкретный метод
измерения (
getBoundingClientRect,elementFromPoint, смещение 10 px от центра глифа) и называют мутацию, на которой тест обязан покраснеть — колонка «чем краснеет» не пустая ни в одной новой строке. - Правка Release-артефактов называет обе фактически устаревающие строки
docs/UX-MODES.md(строка 14 про panel-host/device count, абзац 33–44 про крестик и его футпринт) — проверено построчным сравнением с текущим содержимым файла, а не на слово автора. - Исправление абзаца «Проблема (по коду)» (вложенные обратные кавычки r1) не изменило фактического содержания — код-цитаты и номера строк те же.
- Дельта не создала противоречий с неизменёнными разделами: «принято предположительно» по-прежнему корректно описывает размер слота как одну переменную, совпадающую с прежней кликабельной зоной (24 px), что теперь явно требуется К5.
- На материале ревью (SHA
1ba4c23a) для #647 отсутствует какой-либо код — подтвержденоgit show --statиgit log; риск «текст ТЗ разошёлся с уже написанным кодом» (типичная причина находки на код-ревью) здесь не применим.
Чего не проверял
- Гейты (
tsc,npm test,npm run build,check-docs.mjs, смоки,golden, инварианты,smoke-select.mjs) — не прогонял: код для #647 ещё не написан на материале ревью, диапазон ревью — текст ТЗ, а не диапазон коммитов. Предмет код-ревью после реализации. - Не проверял браузером в реальном рендере поведение на 1000/900 px —
вывод о том, что мутант «правило скрытия как у
.count» действительно покраснит смок, сделан чтением плана AC, а не исполнением ещё не написанного смока; это неизбежно на этапеspecи будет прямой обязанностью код-ревью (проверить, чтоdemo/smoke_toolbar_stable_width.mjsумеет падать на названной мутации). - Не переоценивал заново трек
small/критерии лёгкого трека — не задеты делтой r2 (добавление двух AC не меняет ни сложность ≤3, ни «одну поверхность», ни отсутствие миграции конфига), и в r1 они не были находкой. - Не проверял golden-кадры и скриншоты документации — правка кода ещё не существует; риск golden-регресса уже учтён в разделе «Риски» ТЗ (принято в r1 без замечаний).
Вердикт
Найдено 0 High, 0 Medium. Оба Medium из r1 закрыты по существу текстом редакции r2 — каждое явной правкой формулировки контракта/скоупа и новым тестируемым AC с названной мутацией. Новых неоднозначностей или непроверяемых AC делта не внесла. ТЗ готово к разработке.
Материал раунда
- SHA материала:
1ba4c23a5813d0cf51fb010d79e45416a15facf2(рабочая копия ревью). - Тело issue #647, редакция r2 — снимок на момент этого ревью, 2026-09-25.
Материал раунда
- Ветка:
dev, коммит1ba4c23a5813— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
b5de29ae951c3df446606e8324139fdb919ff0e1git log --all --format='%H %T' | grep b5de29ae951c - Тело issue:
96f3d23ef7e626083567418cc5d5c098150d97627da79dc8ebe77b949f39a1c1 - Вердикт конвейера:
green· High 0