Files
houseplan-card/docs/reviews/CODE-REVIEW-668-r1.md
T
2026-09-27 09:29:49 +00:00

96 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CODE-REVIEW-668-r1
Issue: #668 «Английское руководство пользователя отстаёт от русского»
Материал раунда: `85cba3d8b4e335b0519f8f089f1c534eabf89e9f` (HEAD, `origin/dev..HEAD`)
Коммиты в материале:
- `85cba3d8` docs: синхронизировать английское руководство (#668) — `Issue: #668`, `User-Visible: no`
- `cbc39cea`, `d24b0f0e` — документы SPEC-REVIEW r1/r2 (не относятся к коду)
Класс изменения: C (документация) + B (`scripts/user-guide-parity.mjs`, `test/user-guide-parity.test.mjs`, правка `scripts/check-docs.mjs`). Класс A (`src/**`, `custom_components/**`) не тронут.
## Скоуп
Задача выделена из #667 (п. 8): синхронизировать смысл и структуру `docs/USER-GUIDE.md` с `docs/USER-GUIDE.ru.md`, покрыть перечисленный в Scope список отсутствующих тем, расширить структурный гейт `scripts/check-docs.mjs` полным профилем H2–H4 и отметкой версии. Не-scope: продукт, UI, i18n, RU-руководство, changelog/release notes — задача этого не трогает (проверено diff'ом, см. ниже). Обслуживает J4/J6 из `docs/SCOPE.md` (онбординг и поддержание плана англоязычным администратором).
Прошёл spec-review в двух раундах: r1 — жёлтый (Medium в скоупе: AC4 требовал «unit», которого не было в плане автотестов), r2 — зелёный (AC4 переписан явно на два доказательства). Это первый заход код-ревью.
## Как проверялось
Прочитаны в указанном порядке: `docs/SCOPE.md`, `docs/process/REVIEWER.md`, `AGENTS.md`, тело issue #668 и все 7 комментариев (аналитика → ТЗ → SPEC-REVIEW r1 → правка → SPEC-REVIEW r2 → хендофф реализации), `docs/USER-GUIDE.ru.md` (как источник терминологии), а также канонические `SUN.md`, `VACUUM.md` — разделы, которых касается новый EN-текст.
Дельта разбиралась не по дельте предыдущего раунда (это первый код-ревью-заход задачи), а целиком, как и полагается для r1.
Прочитаны построчно: `scripts/user-guide-parity.mjs`, `test/user-guide-parity.test.mjs`, диф `scripts/check-docs.mjs`, весь `docs/USER-GUIDE.md` (итоговый файл, 1444 строки) и параллельно сверялся с `docs/USER-GUIDE.ru.md` по позиции разделов.
Автоматически сверен полный профиль заголовков EN/RU (`node` с логикой, эквивалентной `guideHeadingProfile`) — 97 заголовков H2–H4 с обеих сторон совпадают позиционно, номера 23 нумерованных H2 идентичны, порядок и уровни идентичны.
Точечно сверены с кодом/каноном спорные фактические утверждения:
- инвариант замка (`docs/SCOPE.md` «Lock invariant») — раздел «Lock» не ослабляет формулировку, добавляет явное «a plan tap never toggles a lock»;
- кнопки диалога закрытия настроек «Continue»/«Discard» — найдены буквально в `src/i18n/settings/en.json:50-51` (`dialog.discard_confirm`: "Discard", `dialog.discard_keep`: "Continue"), автор заявил это как сверенное — подтверждено;
- термины «Show hidden on plan», «Select all ({count})», «Hide selected ({count})» — найдены дословно в `src/i18n/en.json`;
- разбивка фаз солнца по часам (05:00–08:00 и т. д.), порог 3°, фейд 2 с, переход окружения 1,1 с (1100 мс) — совпадают с `docs/SUN.md`;
- калибровка пылесоса 40 см, сглаживание пути 17.5 см, буфер 4000 точек — совпадают с `docs/VACUUM.md`;
- брейкпоинт телефонной шапки ≤ 480 px — совпадает с `src/houseplan-card.ts:10837`, `src/header-menu.ts` (issue #616);
- список из 8 скриншотов (`images/0N-*.png`) в EN и RU расположен в одинаковых по смыслу местах.
Выполнены гейты, не покрытые ссылкой на зелёный Validate этого SHA (Validate подтверждает `typecheck`/`test`/`build`/`docs`, но AC требует явного исполнения и демонстрации, что защитный тест умеет падать):
- `node --test test/user-guide-parity.test.mjs` — 4/4 green (структурный тест на реальных файлах + три отрицательные пробы).
- Мутационная проверка «тест умеет падать» на **реальных** файлах (не только на строковых фикстурах теста): временно вырезан заголовок `### Lock` из `docs/USER-GUIDE.md`, тест сразу покраснел (`not ok 1`), затем рабочая копия восстановлена (`cp` бэкапа, подтверждено `git status --porcelain` — пусто).
- Контрольная проверка, что чисто текстовая правка заголовка того же уровня (без изменения количества/уровня заголовков) тест не ловит — ожидаемо, т.к. AC1/AC6 специфицируют защиту структуры (порядок/уровень), а не текста; содержательное соответствие — предмет AC2 (ревью кода), не автотеста. Разночтения не найдено.
- `node scripts/check-docs.mjs --external` — green: «Documentation checks passed (7 files, 12 external links)» → AC5 подтверждён исполнением.
- `node --check` на всех трёх изменённых `.mjs`-файлов — синтаксически чисты.
- `git diff origin/dev...HEAD --stat -- docs/USER-GUIDE.ru.md src/ custom_components/` — пусто → AC4 (неизменность RU/продукта) подтверждён.
- `git diff origin/dev...HEAD --stat -- dist/ custom_components/houseplan/frontend/ demo/golden/baselines/` — пусто → бандл и golden-эталоны в коммит не попали (часть AC7).
- Версии `Current for **v1.78.0-beta.5**.` / `Актуально для **v1.78.0-beta.5**.` — идентичны (AC4).
## Чего не проверял
- `npx tsc --noEmit`, полный `npm test`, `npm run build` со сверкой бандла, `npm run gate:small` целиком — не перегонялись повторно: Validate на этом же SHA (`85cba3d8`) уже завершился success (https://github.com/Matysh/houseplan-card/actions/runs/36308972032), и диф не касается `src/**`/`custom_components/**/*.py`, так что риска регрессии в собираемости не вижу.
- Browser-смоки, `golden:verify`, `pytest tests_backend`, инварианты модели, performance — не запускал: задача документационная, исполняемое и визуальное поведение продукта не меняет (нет правок `src/**`), AC не называют эти гейты, а `smoke-select.mjs` для чисто docs/scripts-диффа предметно не даёт прямых совпадений (диф не касается кода карточки/демо). Явно не прогонял `node scripts/smoke-select.mjs --base <base> --head <head>` — прошу считать это осознанным пропуском по диффу (только `docs/**`, `scripts/check-docs.mjs`, `scripts/user-guide-parity.mjs`, `test/**`), а не недосмотром: инструмент разбирает связи изменённого продуктового/демо-кода со смоками, а здесь такого кода нет.
- Не вычитывал построчно весь текст EN-руководства против RU слово-в-слово (объём ~1444 строк); выборочно проверил структуру целиком (автоматически) и содержание — по разделам с наибольшим риском фактической ошибки (безопасность/замок, солнце, пылесос, диалоги, брейкпоинты, i18n-термины) и по перечню тем из Scope. Чек-лист тем из Scope (мобильная шапка, контекстные подсказки, Merge/Split/Resize/толщина/нулевая толщина, проёмы/режимы/замок/толстые стены, авто-появление маркеров/скрытые/деактивированные, жесты/действия/подложка/активность/отображение/бейджи/иконки/матрица, заливки/наследование/источник света, инструменты подложки/двойной клик/живой текст/мебель/свои изображения, солнце/калибровка/путь пылесоса, оптимизация/сохранения/риск-отмена, памятка безопасности) — сверен по заголовкам и содержанию, все присутствуют по существу (AC2).
- Не сверял английские термины i18n построчно для каждого упоминания в тексте (только выборочно для контролов, упомянутых в самых чувствительных разделах); полное построчное сопоставление 1444 строк с `src/i18n/en.json` не выполнялось — это соразмерное для документационной задачи сужение (§8), а не пропуск конкретного риска.
- `npm run inventory` не запускал — документ не содержит счётчиков тестов, которые требовалось бы актуализировать.
## Находки
Не найдено находок уровня High или Medium. Один пункт снят как Low без действия:
- **Low, снято, не блокирует.** В `scripts/check-docs.mjs` для пары `docs/USER-GUIDE.md`/`docs/USER-GUIDE.ru.md` теперь работают два параллельных структурных гейта: старый по 13 именованным `docs-section`-маркерам (строки ~175-186) и новый полный H2–H4/version профиль (`guideParityErrors`, строки 188-191). Это было явно предвидено в SPEC-REVIEW-668-r1 (Low, снято ревьюером) с оговоркой «если после кода это разъедется — находка код-ревью». Разъезда не произошло: список из 13 маркеров идентичен и в том же порядке в обоих файлах (проверено `grep`), а старый гейт остаётся нужен отдельно для пары `README.md`/`README.ru.md`, которую новая функция не покрывает — то есть он не read-only дубль, а разделяет ответственность (README vs. полная структура USER-GUIDE). Оставляю как есть, без действия.
## Что проверено и корректно
- AC1 — H2–H4 профиль и 23 нумерованных раздела совпадают позиционно между EN/RU; unit `node --test test/user-guide-parity.test.mjs` green.
- AC2 — все перечисленные в Scope темы присутствуют содержательно и в соответствующих разделах (сверено по чек-листу выше).
- AC3 — выборочно проверенные названия контролов (Show hidden on plan, Select all/Hide selected, Continue/Discard) дословно совпадают с `src/i18n/en.json` и `src/i18n/settings/en.json`; несуществующего поведения в проверенных разделах не встретил.
- AC4 — отметки версии идентичны (`v1.78.0-beta.5`); RU и продуктовый код не изменены (diff пуст).
- AC5 — `node scripts/check-docs.mjs --external` green.
- AC6 — защитный тест доказан таблицей:
| AC | Чем доказан | Чем краснеет |
|---|---|---|
| AC6 (пропуск подраздела) | `test/user-guide-parity.test.mjs` кейс 2 на строковой фикстуре | подтверждено также мутацией реального `docs/USER-GUIDE.md` (удалён `### Lock`) — `not ok 1`, тест-прогон приведён выше |
| AC6 (смена уровня) | кейс 3 на строковой фикстуре | `#### Деталь` вместо `### Detail` красит `heading profiles differ` |
| AC6 (версия) | кейс 4 на строковой фикстуре | разные версии красят `current versions differ` |
- AC7 — `bundle:clean`-состояние подтверждено: `dist/**`, `custom_components/houseplan/frontend/**`, `demo/golden/baselines/**` не в диффе; трейлеры `Issue: #668` и `User-Visible: no` на коммите на месте (докрутка changelog не требуется).
- Трейлеры и класс изменения соответствуют AGENTS.md: `User-Visible: no`, оба changelog не тронуты (и не должны были).
- Число «одна версия — один источник» (§8): версия `v1.78.0-beta.5` встречается в EN и RU и берётся из одного и того же места по построению (структурный гейт сравнивает их напрямую); других видимых пользователю чисел, продублированных в этом диффе, не встретил.
## Вердикт
Зелёный. AC1–AC7 выполнены и доказаны; единственная Low-находка снята без действия, High/Medium нет.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/668-user-guide`, коммит `85cba3d8b4e3` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `08ee50612259632359530b8c7a8226782d45f9a0`
```
git log --all --format='%H %T' | grep 08ee50612259
```
- Тело issue: `aeef91d8b412d0d7dddc4e4c9179746e50a716ed6a80a3078c645cdd925fd5b2`
- Вердикт конвейера: `green` · High 0