From 1ecf96d596af0983dd09c16fae36505b567e5981 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sat, 26 Sep 2026 07:43:22 +0000 Subject: [PATCH] docs: review document for #660 Issue: #660 User-Visible: no --- docs/reviews/INDEX.md | 3 +- docs/reviews/SPEC-REVIEW-660-r3.md | 225 +++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/SPEC-REVIEW-660-r3.md diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 200a9ab5..0839dfb4 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,11 +1,12 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1076, issue: 380. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1077, issue: 380. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| | #660 | [SPEC-REVIEW-660-r1.md](SPEC-REVIEW-660-r1.md) | spec · r1 | 🔴 красный | 2 | 1 | Раздел ## ТЗ в теле issue отсутствует целиком; Изменение прямо противоречит двум местам; AC «расстояние уменьшено ровно вдвое» не | `docs/process/AUTHOR.md` `REVIEWER.md` `test/core-file-budget.test.mjs` `scripts/smoke-select.mjs` `demo/helpers/hp-test.mjs` `docs/UX-MODES.md` `docs/reviews/SPEC-REVIEW-647-r1.md` | | #660 | [SPEC-REVIEW-660-r2.md](SPEC-REVIEW-660-r2.md) | spec · r2 | 🔴 красный | 1 | 0 | Скоуп п.3 переносит крестик внутрь .modes, но .modes | `src/styles/chrome.styles.ts` `src/houseplan-card.ts` `docs/USER-GUIDE.ru.md` `docs/UX-MODES.md` `src/houseplan-editor-runtime.ts` `src/header-menu.ts` `smoke_mobile_view_header.mjs` | +| #660 | [SPEC-REVIEW-660-r3.md](SPEC-REVIEW-660-r3.md) | spec · r3 | 🟢 зелёный | 0 | 0 | — | — | | #657 | [CODE-REVIEW-657-r1.md](CODE-REVIEW-657-r1.md) | code · r1 | 🔴 красный | 1 | 0 | после fast-forward слияния (dev не двигался за время ревью) docs/reviews/INDEX.md остаё… | `docs/reviews/INDEX.md` `test/reviews-index.test.mjs` `_process.yml` `merge-candidate.mjs` `test/merge-candidate.test.mjs` `scripts/reviews-index.mjs` | | #657 | [CODE-REVIEW-657-r2.md](CODE-REVIEW-657-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | из r1 — проверка закрытия | `scripts/merge-candidate.mjs` `PROCESS.md` `mutation-registry.mjs` `INDEX.md` | | #656 | [CODE-REVIEW-656-r1.md](CODE-REVIEW-656-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/docs/reviews/SPEC-REVIEW-660-r3.md b/docs/reviews/SPEC-REVIEW-660-r3.md new file mode 100644 index 00000000..73a75071 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-660-r3.md @@ -0,0 +1,225 @@ +# 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`) и `` как физический sibling после + `.modes`, перед ``; + - `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