mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
@@ -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 | — | — |
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user