Files
houseplan-card/docs/reviews/SPEC-REVIEW-660-r3.md
T
2026-09-26 07:43:22 +00:00

22 KiB
Raw Blame History

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».

Как проверялось

  1. Прочитаны docs/process/REVIEWER.md целиком и PROCESS.md §2.4, §2.5, §2.10, §4, §7.1, §7.2 (по ссылкам конспекта).
  2. Прочитано текущее тело issue #660 целиком (gh issue view 660 --json body) и комментарии (gh issue view 660 --json comments): «Аналитика», ответ владельца Q1/Q2, вердикты r1/r2, комментарий автора «ТЗ обновлено до r3».
  3. Сверена история меток issue (gh api .../timeline --paginate) — порядок событий red-вердикт r2 → S3-spec → комментарий автора → S4-spec-review подтверждён (см. «Материал» выше).
  4. Прочитаны docs/reviews/SPEC-REVIEW-660-r1.md и -r2.md целиком; единственная находка r2 (High-1: перенос крестика внутрь .modes без оговорки по ширине ломает видимость на ≤480 px) сверена построчно с новым текстом (раздел «Закрытие раунда r2» ниже).
  5. Прочитан docs/UX-MODES.md:1-40 (описание телефонной шапки, включая «the editor X slot of #647» как отдельный от вкладок режимов элемент) и строки 56-61, 116-125 (обе цитаты, которые AC10 требует заменить) — новый текст Скоуп п.3/AC4 им не противоречит: канон уже описывал крестик на телефоне как элемент, присутствующий независимо от режима, что и воспроизводит r3.
  6. Перечитан код, который правит дельта:
    • 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.
  7. Проверено, что продуктового кода для #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 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: d55b5f3d47e446be687eda886e90efad6d0bccb3
    git log --all --format='%H %T' | grep d55b5f3d47e4
    
  • Тело issue: 8934e3862ceec6de29d1fd24fe32df49790efd62d8288fb28e36eecb05e44387
  • Вердикт конвейера: green · High 0