22 KiB
SPEC-REVIEW-660-r3
- Issue: https://github.com/Matysh/houseplan-card/issues/660
- Этап:
S4-spec-review(ревью ТЗ, PROCESS.md §2.4) - Трек: полный (не пересматривался в r3, обоснование не менялось — см. «Унаследовано из r2»)
- Материал: тело issue #660 в редакции r3 (
updatedAt: 2026-09-26T07:37:01Z); комментарий автора «ТЗ обновлено до r3 по SPEC-REVIEW-660-r2» (2026-09-26T07:36:59Z) предшествует установкеS4-spec-review(07:37:01) на 2 секунды — тот же паттерн, что в r1→r2. Таймлайн меток: вердикт r2 (07:34:32) →S4-spec-reviewснята,S3-specвыставлена (07:35:09) → комментарий автора о доработке (07:36:59) →S3-specснята,S4-spec-reviewвыставлена (07:37:01). Тело сверено напрямую сdocs/reviews/SPEC-REVIEW-660-r2.md: раздел## ТЗв r2 уже был полным; в r3 изменены только Скоуп п.3, Не-скоуп (одна фраза), AC4, AC9 и вводная строка «Редакция r3» — остальной текст (Сценарий, До/После, Проблема по коду, AC1/AC2/ AC3/AC5…AC8/AC10, UX/i18n/данные, таблица «AC · чем доказан · чем краснеет», План автотестов, Риски, Откат, Release-артефакты, «Принято предположительно») не редактировался. - Заход: r3 · блокирующих циклов израсходовано 2 из 4 (полный трек, лимит 4)
- Роль: ревьюер ТЗ (не автор)
Скоуп ревью
Задача не изменилась с r1/r2: полировка шапки главной панели после #647 — (1) inline-кнопки сводной панели остаются активными во всех трёх редакторах на ширинах
480 px; (2) расстояние между блоком редакторов и блоком зума уменьшается вдвое до измеримых значений; (3) резерв под крестик закрытия переезжает внутрь
.modes, включая явную оговорку поведения на ≤480 px; (4)Escполучает единый терминальный выход в View из Plan и Devices.
Проверялось: закрыт ли единственный High SPEC-REVIEW-660-r2 (крестик пропадал на
≤480 px вместе со всем .modes, AC9 был недоказуем, единственный touch-выход из
Plan/Devices исчезал); не появилось ли новое противоречие в изменённых Скоуп п.3 /
Не-скоуп / AC4 / AC9; согласие обновлённого текста с кодом «как есть» и с
docs/UX-MODES.md (в частности со строками 17-20 про «editor X slot» телефонной
шапки, которые в r2 не были предметом находки).
Дельта локальна. В отличие от r1→r2 (где дописывался весь раздел ## ТЗ
впервые, то есть объём дельты был сопоставим с задачей), r2→r3 меняет пять коротких
фрагментов текста, все они — прямой ответ на единственную находку High-1 r2. Раздел
разбирается по дельте (PROCESS.md §2.10): полностью проверены только Скоуп п.3,
Не-скоуп, AC4, AC9 и их взаимная непротиворечивость с кодом/каноном; остальные
части ТЗ, не тронутые дельтой (AC1, AC2, AC3, AC5-AC8, AC10, План автотестов,
Риски, Откат, Release-артефакты, «Принято предположительно», выбор трека,
правомерность Q1/Q2), приняты без повторного разбора — см. «Унаследовано из r2».
Как проверялось
- Прочитаны
docs/process/REVIEWER.mdцеликом и PROCESS.md §2.4, §2.5, §2.10, §4, §7.1, §7.2 (по ссылкам конспекта). - Прочитано текущее тело issue #660 целиком (
gh issue view 660 --json body) и комментарии (gh issue view 660 --json comments): «Аналитика», ответ владельца Q1/Q2, вердикты r1/r2, комментарий автора «ТЗ обновлено до r3». - Сверена история меток issue (
gh api .../timeline --paginate) — порядок событий red-вердикт r2 →S3-spec→ комментарий автора →S4-spec-reviewподтверждён (см. «Материал» выше). - Прочитаны
docs/reviews/SPEC-REVIEW-660-r1.mdи-r2.mdцеликом; единственная находка r2 (High-1: перенос крестика внутрь.modesбез оговорки по ширине ломает видимость на ≤480 px) сверена построчно с новым текстом (раздел «Закрытие раунда r2» ниже). - Прочитан
docs/UX-MODES.md:1-40(описание телефонной шапки, включая «the editor X slot of #647» как отдельный от вкладок режимов элемент) и строки 56-61, 116-125 (обе цитаты, которые AC10 требует заменить) — новый текст Скоуп п.3/AC4 им не противоречит: канон уже описывал крестик на телефоне как элемент, присутствующий независимо от режима, что и воспроизводит r3. - Перечитан код, который правит дельта:
src/styles/chrome.styles.ts:150-166— медиазапросmax-width: 480px: списокdisplay: none(.title, .modes, .spacer, .header-action, .summary-control) и отдельное правило.head > .zoomctl, .head > .editor-close-slot { flex: none }; подтверждает, что сегодня.modesпрячется целиком, а.editor-close-slot— нет (независимое от него правило);src/houseplan-card.ts:10805-10824— текущая разметка:.modes(только при_canEdit) и<span class="editor-close-slot">как физический sibling после.modes, перед<span class="spacer">;docs/USER-GUIDE.ru.md:265-278(«Шапка на телефоне») — «В редакторе крестик закрытия остаётся в строке» — подтверждает наблюдаемое сегодня поведение, которое AC9/Скоуп п.3 r3 обязаны сохранить после переноса слота в.modes.
- Проверено, что продуктового кода для #660 в
origin/dev...HEADпо-прежнему нет (git diff origin/dev...HEAD --statпуст,git log --oneline -5показывает только доковые коммиты предыдущих ревью) — гейты не гоняются, этапspec.
Находки
Не найдено. Единственная находка SPEC-REVIEW-660-r2 закрыта содержательно (см. «Закрытие раунда r2»), новых High/Medium/Low в изменённых фрагментах не появилось.
Что проверено и корректно
- High-1 из r2 закрыт содержательно и правильным из двух предложенных путей.
r2 предлагал на выбор: (а) крестик остаётся физическим соседом
.modesна ≤480 px, либо (б) медиазапрос телефонной шапки переписывается так, чтобы прятать только.modetab-кнопки, сохраняя видимость и позицию крестика. Автор выбрал (б): Скоуп п.3 теперь явно говорит «На ≤480 px не скрывать весь.modes: скрывать только.modetab, а контейнер делать визуально прозрачным и схлопнутым до 24 px слота» — техническое решение согласуется с существующим CSS (.modesсегодня —display: inline-flex; gap; background; border-radius; padding— все эти свойства перечислены как то, что нужно снять на ≤480 px, не голословно). - AC4 и AC9 обновлены синхронно со Скоуп п.3, а не только он. AC4 явно
добавляет: «На ≤480 px
.modetabскрыты, но.modesи его слот остаются; в редакторе виден и работает крестик, в View остаётся неинтерактивный пустой резерв» — это ровно то, что делает AC9 доказуемым (r2 констатировал: «AC9 недоказуем как написан» именно потому, что слот тогда пропадал целиком). AC9 теперь прямо называет фактическую защиту: «на 390/480 px крестик остаётся видимым в строке и touch-кликом закрывает Plan, Devices и Decor; это обязательный путь выхода при скрытых.modetabи отсутствии пункта View в gear-меню» — устраняет второй пункт находки r2 (тупик для touch-only администратора). - Не-скоуп больше не противоречит Скоуп п.3. r2 отмечал: «восстановление
видимости крестика на ≤480 px требует трогать CSS-структуру телефонной шапки...
а это прямо соседствует с исключённой поверхностью и нигде не выделено как
разрешённое исключение». В r3 добавлена явная оговорка: «Адаптивное правило
самой шапки для сохранения крестика на ≤480 px входит в скоуп» — снимает
формальное противоречие между «Не-скоуп: изменение мобильного gear-меню» и
фактически требуемой правкой CSS-медиазапроса шапки (это разные поверхности:
меню шестерёнки не трогается, трогается только
.modes/.editor-close-slot). - Новый текст согласован с каноном, а не только с самим собой.
docs/UX-MODES.md:17-20уже описывает крестик как элемент телефонной шапки, присутствующий независимо от режима («... the zoom cluster, one gear and — for an admin — the editor X slot of #647»); r3 воспроизводит именно эту семантику («слот остаётся» в View как пустой резерв, в редакторе — как активная кнопка), а не вводит новое расхождение. AC10 по-прежнему называет ровно две цитаты канона на замену (строки 56-61 «outside the editors», 116-125 «disappear in Plan, Devices and Background») — обе останутся неверны после реализации и обе учтены. - Мутация для AC4 прямо кодирует закрытую находку. Таблица «AC · чем доказан ·
чем краснеет» для AC4: «мутант возвращает слот sibling либо скрывает весь
.modesна ≤480 px» — это буквально откат к архитектуре, которую нашёл High-1 r2; мутант не абстрактный, а прицельно бьёт по регрессии, которую разбирало предыдущее ревью. - Единственный технический вопрос, который мог бы остаться открытым
(визуальная позиция крестика на ≤480 px «как до #660», не только видимость и
кликабельность) — закрыт через «Принято предположительно». Раздел явно
называет: «На ≤480 px сохранить контейнер в layout, скрыть только
.modetabи убрать у схлопнутой группы фон/padding, чтобы видимым остался прежний 24 px крестик/резерв» — это техническая деталь компоновки (снятие padding/background у пустого контейнера), а не продуктовое решение, поэтому её место — именно в «Принято предположительно», не в отдельном AC; помечена как «поменять свободно», как и требует §7.1. - Остальной текст ТЗ (не тронутый дельтой r3) не проверялся заново в этом раунде — см. «Унаследовано из r2».
Чего не проверял
- Гейты (
tsc,npm test,npm run build,check-docs.mjs, смоки, golden, инварианты) — не прогонял: этапspec, продуктового кода для #660 вorigin/dev...HEADпо-прежнему нет (git diffпуст). Предмет код-ревью после реализации. - Не проверял заново AC1, AC2, AC3, AC5-AC8, AC10, План автотестов, Риски, Откат, Release-артефакты, «Принято предположительно» (кроме пункта про ≤480 px, разобранного выше) — эти части не менялись между r2 и r3, дельта их не задевает (см. «Унаследовано из r2»).
- Не измерял в браузере фактическую видимую позицию крестика на 390/480 px после
снятия padding у
.modes— реализации ещё нет; это станет предметом код-ревью и browser-смока (smoke_mobile_view_header.mjs), когда появится код. - Не проверял, действительно ли
scripts/mutation-registry.mjsуже содержит указанные в таблице мутанты — план автотестов только обещает их добавить, что нормально для стадииspec. - Не пересматривал выбор полного трека и правомерность вопросов Q1/Q2 — оба установлены в r1 и не пересматривались в r2; текст, на котором они основаны, не редактировался и в r3.
Закрытие раунда r2
| Находка (r2) | Чем закрыта | Где это видно |
|---|---|---|
High-1: Скоуп п.3 переносит крестик внутрь .modes без оговорки по ширине; .modes скрыт display:none на ≤480 px → крестик пропадает из телефонной шапки, AC9 недоказуем, touch-only администратор теряет единственный способ выйти из Plan/Devices |
Скоуп п.3 добавляет явную оговорку: на ≤480 px скрывается только .modetab, .modes-контейнер остаётся в layout визуально прозрачным и схлопнутым до 24 px слота; AC4 и AC9 переписаны синхронно (крестик/слот остаются, обязательный touch-выход назван прямо); Не-скоуп явно вносит адаптивное правило шапки как разрешённое исключение |
тело issue #660, разделы «Скоуп» п.3 (последние два предложения), «Не-скоуп» (последнее предложение первого пункта), «AC4», «AC9» |
Находка закрыта содержательно, выбранным путём (б) из двух предложенных в SPEC-REVIEW-660-r2 «Как закрыть», без формальной отписки: изменения синхронны между Скоуп/Не-скоуп/AC4/AC9, а не точечная правка одной строки.
Унаследовано из r2 (без повторной проверки в этом раунде)
- Полнота обязательных разделов §7.1 и структура ТЗ по образцу #647 — установлена в SPEC-REVIEW-660-r2 (закрытие High-1 r1); текст этих разделов (Сценарий, До/После, Проблема по коду, UX/i18n/данные, таблица «AC · чем доказан · чем краснеет» кроме строки AC4, План автотестов, Риски, Откат, Release-артефакты, «Принято предположительно» кроме пункта про ≤480 px) не редактировался между r2 и r3.
- Соответствие AC10/Release-артефактов канону
docs/UX-MODES.md— установлено в SPEC-REVIEW-660-r2 (закрытие High-2 r1); текст AC10 не менялся. - Измеримые цели AC3 (50±1 px / 40.5±1 px) — установлены в SPEC-REVIEW-660-r2 (закрытие Medium-1 r1); текст AC3 не менялся.
- Архитектурная состоятельность AC1/AC2 (снятие guard в
renderControls()без новой width-detection логики) и реализуемость AC7/AC8 (терминальныйEscукладывается в существующую структуру_onKey) — проверены по коду в SPEC-REVIEW-660-r2, текст этих AC не менялся. - Отказ от лёгкого трека (
small) и выбор полного трека — обоснование не менялось с r1 (несколько поверхностей + новый UX-контракт), не пересматривался в r2 и r3. - Продуктовая правомерность вопросов Q1/Q2 — установлена в r1, не пересматривалась в r2 и r3.
Вердикт
Единственная находка SPEC-REVIEW-660-r2 (High-1: перенос крестика внутрь .modes
без оговорки по ширине ломал видимость на ≤480 px) закрыта содержательно и
синхронно во всех местах текста, которые она затрагивала: Скоуп п.3, Не-скоуп,
AC4, AC9. Выбранное решение — переписать медиазапрос телефонной шапки так, чтобы
прятать только кнопки режимов, а не весь .modes — согласуется с действующим
кодом (chrome.styles.ts:150-166) и с каноном docs/UX-MODES.md:17-20, который
уже описывает крестик как элемент телефонной шапки, не зависящий от видимости
вкладок режимов. Новых High/Medium в изменённых фрагментах не найдено; остальной,
не тронутый дельтой текст, был полностью проверен в r2 и не пересматривался.
Продуктового кода для задачи всё ещё нет, гейты не применимы к стадии spec.
Зелёный вердикт: ТЗ готово к разработке, находок нет.
Вердикт: зелёный · заход r3 · блокирующих циклов 2/4 · High: 0 · Medium: 0 → в задаче
Материал раунда
- Ветка:
dev, коммитd65b9e39d5e6— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
d55b5f3d47e446be687eda886e90efad6d0bccb3git log --all --format='%H %T' | grep d55b5f3d47e4 - Тело issue:
8934e3862ceec6de29d1fd24fe32df49790efd62d8288fb28e36eecb05e44387 - Вердикт конвейера:
green· High 0