docs: review document for #660

Issue: #660
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-26 07:43:22 +00:00
parent d65b9e39d5
commit 1ecf96d596
2 changed files with 227 additions and 1 deletions
+2 -1
View File
@@ -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 | — | — |
+225
View File
@@ -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`) и `<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 → в задаче
---
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `d65b9e39d5e6` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `d55b5f3d47e446be687eda886e90efad6d0bccb3`
```
git log --all --format='%H %T' | grep d55b5f3d47e4
```
- Тело issue: `8934e3862ceec6de29d1fd24fe32df49790efd62d8288fb28e36eecb05e44387`
- Вердикт конвейера: `green` · High 0