Files
houseplan-card/docs/reviews/SPEC-REVIEW-668-r1.md
T
2026-09-27 09:18:50 +00:00

103 lines
18 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.
# SPEC-REVIEW-668-r1
**Issue:** [#668](https://github.com/Matysh/houseplan-card/issues/668) — «EN user guide отстаёт от RU» (перевод/синхронизация `docs/USER-GUIDE.md` с `docs/USER-GUIDE.ru.md`, выделено из #667 п.8)
**Этап:** spec (`S4-spec-review`) · трек: полный (метки `P2`, `docs`, `S4-spec-review`; ни `small`, ни `trivial` не выставлены)
**Заход:** r1 · блокирующих циклов израсходовано 0 из 4
**Материал:** тело issue #668, раздел `## ТЗ` (получено `gh issue view 668 --json body`), плюс 1 комментарий-аналитика («Взял: аналитик», оценка P2/полный трек, «принято предположительно», передача на ревью). Прежних вердиктов на этом issue нет — раздел «Унаследовано из r0» не применим.
**Роль:** ревьюер ТЗ, независимая сессия, без контекста автора.
## Скоуп проверки
ТЗ описывает синхронизацию структуры и смысла `docs/USER-GUIDE.md` (EN) с актуальным `docs/USER-GUIDE.ru.md`: сейчас EN короче на ~40 заголовков (57 против 98 на `dev`) и не покрывает самостоятельные пользовательские сценарии — мобильную шапку, Merge/Split/Resize/толщину стен, настройки проёмов/замков, скрытые/деактивированные устройства, живой текст, мебель, свои изображения, солнце/пылесос, оптимизацию плана и памятку безопасности. Задача обслуживает J4 и J6 из `docs/SCOPE.md`: README и HACS ведут на EN-руководство, поэтому разрыв бьёт по основному пути онбординга англоязычного администратора. Продукт, UI, i18n-файлы и RU-руководство не меняются; `User-Visible: no`.
## Как проверялось
1. Прочитаны целиком `docs/SCOPE.md`, `docs/process/REVIEWER.md`; по ссылкам конспекта открыт `PROCESS.md` §2.3–§2.5, §7.1, §7.2, §4, §12.
2. Прочитано тело issue #668 (проблема + `## ТЗ`, все подразделы) и комментарий-аналитика полностью.
3. Проверены обязательные разделы ТЗ по §7.1 (список, порядок, полнота) — см. таблицу ниже.
4. Сверена фактическая база ТЗ с текущим `dev` (рабочая копия, HEAD `2f857a0f`):
- заголовки RU (`grep -n '^#' docs/USER-GUIDE.ru.md`): 23 нумерованных `##`-раздела (1…23) + отдельный ненумерованный H2 «Краткая памятка безопасности» между разделами 22 и 23 — совпадает с формулировкой AC1 дословно.
- заголовки EN (`grep -n '^#' docs/USER-GUIDE.md`): те же 23 номера присутствуют, но подавляющее большинство H3/H4 из RU отсутствует (например, RU §5 «Режимы интерфейса» — 4 подраздела, EN §5 «Interface modes» — 1; RU §14 «Редактор подложки» — 5 подразделов, EN §14 «Background editor» — 0) — подтверждает описанный в issue разрыв, тема из Scope реально отсутствует, а не преувеличена.
- каждая тема из списка «обязательно покрыть» сверена построчно с текущими RU-подзаголовками — расхождений не найдено, список точный.
5. Прочитан `scripts/check-docs.mjs` целиком (260 строк) — там уже есть частичный структурный гейт (`<!-- docs-section: … -->`, строки 172–185), сверяющий порядок/состав маркеров для `docs/USER-GUIDE.md`/`.ru.md` по 14 из 23 разделов; см. находку ниже.
6. Проверено, что ветка `issue/668-user-guide` существует и её diff с `origin/dev` пуст (`git diff origin/dev...origin/issue/668-user-guide --stat`) — код/документ ещё не тронуты, DoR не нарушено преждевременной реализацией.
7. Проверено существование команд, названных в AC/тест-плане: `npm run gate:small` (`scripts/gate-small.mjs`), `npm run bundle:clean` (`bundle-policy.mjs --clean`) — есть в `package.json`; `scripts/gate-small.mjs` в собственном комментарии подтверждает, что `check-docs` в строгом режиме в него не входит — согласуется с тем, что AC5 называет его отдельной командой.
### Обязательные разделы (§7.1)
| Требуется | В ТЗ | Порядок |
|---|---|---|
| Сценарий | «Пользовательский сценарий» | ✓ 1-й |
| Что человек увидит до/после | «Что человек видит до и после» | ✓ 2-й |
| Проблема | «Проблема» (плюс дублирующий обзор до `## ТЗ`) | ✓ 3-й |
| Скоуп/не-скоуп | «Scope» / «Не-scope» | ✓ |
| Контракт поведения / UX | «Контракт документации и UX» (объединены — оправдано: для документационной задачи это одно и то же) | ✓ |
| Модель данных и миграция | «Модель данных и миграция» — «нет» | ✓ |
| i18n | «i18n» — словари не меняются, EN-термины сверяются с `src/i18n/en.json` | ✓ |
| AC1…ACn с доказательством | 7 критериев, у каждого есть метод доказательства | ✓ (см. находку) |
| План автотестов | «План автотестов» | ✓ |
| Риски | «Риски и меры» | ✓ |
| Откат | «Откат» | ✓ |
| Release-артефакты | «Release-артефакты» | ✓ |
Все обязательные разделы присутствуют в правильном порядке — пропусков нет.
## Находки
### Medium — AC4 смешивает две проверки под одним недоопределённым методом доказательства
**Где:** issue #668, раздел `## ТЗ` → `### Acceptance criteria`, строка AC4: «EN и RU показывают одинаковую отметку актуальной версии; содержание/порядок RU и продуктовый код задачей не изменены. Доказательство: unit + проверка diff».
**В чём проблема:** AC4 объединяет два разных утверждения под одним методом:
1. равенство отметки версии («Current for **v1.73.0**» / «Актуально для **v1.78.0-beta.5**» — это обычная строка текста перед `## Содержание`, а не заголовок);
2. отсутствие изменений в RU-файле и продуктовом коде — по сути переформулировка «Не-scope», а не отдельно проверяемое поведение.
Раздел «План автотестов» описывает только один новый unit-тест — структурный паритет **заголовков** H2–H4 (порядок, уровень, номер). Строка версии заголовком не является и текстом теста нигде не упомянута: ни один описанный тест не читает и не сравнивает эту строку. Слово «unit» в AC4 отсылает к тесту, которого нет ни в плане автотестов, ни в остальном ТЗ. Часть 2 («RU/код не менялись») тестом типа `unit` в обычном смысле не проверяется — это ревью diff, а не автоматическая проверка данных.
Итог: у AC4 по факту единственный реальный метод доказательства — «проверка diff» (ручная, на код-ревью), а «unit» — либо неточная формулировка, либо пропущенный пункт тест-плана. Как ни трактовать, § 7.1 требует однозначного указания способа доказательства для каждого AC, а здесь оно не совпадает с тест-планом того же ТЗ.
**Почему это не оставить как есть:** без исправления код-ревьюер имеет ровно тот же документ и не сможет определить, обязан ли он был увидеть автоматический тест на строку версии, — доказательство AC4 останется голословным «unit», который на самом деле никогда не запускался.
**Как чинится (в скоупе, без нового issue):** один из двух вариантов на выбор автора — (a) убрать «unit» из AC4 и оставить только «проверка diff» для обеих частей; либо (b) явно добавить в «План автотестов» пункт «строка версии сравнивается тем же/отдельным тестом» и указать, что именно он проверяет (совпадение подстроки версии, а не заголовков). Любой из вариантов — правка одной-двух строк текста ТЗ, не требует нового цикла реализации.
### Low (снято ревьюером, для протокола) — пересечение с существующим гейтом `check-docs.mjs`
`scripts/check-docs.mjs:172-185` уже сравнивает EN/RU по маркерам `<!-- docs-section: … -->` (сейчас 14 из 23 разделов промаркированы, порядок и состав должны совпадать — иначе `errors.push`). Новый AC6-тест (полное сравнение дерева заголовков H2–H4) по объёму перекрывает эту существующую проверку для тех разделов, что уже промаркированы, но ТЗ никак не упоминает существующий механизм и не говорит, должен ли новый тест его заменить, расширить (промаркировать оставшиеся 9 разделов) или существовать параллельно. Не блокирую: это чисто техническое решение о раскладке тестов («агенты решают сами», §7.1), и обе проверки, работая независимо, не противоречат друг другу — риск лишь в дублировании усилий у реализатора. Оставляю как заметку для код-ревью: если после реализации `docs-section`-маркеры и новый unit-тест утверждают структуру по-разному, это будет находка код-ревью, а не спека.
## Что проверено и корректно
- Численные утверждения в «Проблеме»/«Аналитике» (57 vs 98 заголовков) и точный список отсутствующих тем сверены с реальным `dev` и подтверждены построчно — не «догадка, записанная как факт».
- AC1 «23 нумерованных раздела + краткая памятка безопасности» — сверено с обоими файлами, совпадает дословно на этом SHA.
- AC6 (защитный AC на дрейф структуры) — метод доказательства явно назван и специфицирует «чем краснеет»: негативная проба на временных фикстурах, пропущенный заголовок / неверный уровень должны явно падать. Это ровно то, что требуется от защитного критерия уже на этапе ТЗ.
- Contract-раздел закрывает три реалистичных риска до того, как они стали открытыми вопросами: сохранение внешних/внутренних ссылок, обязательность сверки с EN i18n вместо буквального переноса RU-терминов, и явный протокол на случай, если RU расходится с фактическим продуктом (уходит отдельной issue, а не тянется в #668 как факт).
- Не-scope корректно исключает переписывание RU, дословный перевод и новые скриншоты/changelog — не даёт скоупу расползтись на соседние поверхности.
- «Модель данных и миграция», i18n, откат, release-артефакты — по существу «нет изменений», что верно для чисто документационной задачи и не притворяется, что где-то есть скрытый эффект.
- `User-Visible: no` для документационного изменения соответствует правилу `AGENTS.md` («документация, которая не меняет продукт»), а не является попыткой спрятать пользовательское изменение от changelog.
- Ветка создана от актуального `dev`, диффа с `dev` нет — код к моменту ревью ТЗ не тронут, `DoR` не нарушено гонкой вперёд.
- Открытых продуктовых вопросов к владельцу в ТЗ нет; две единственные технические развилки («принято предположительно») — про формат языка (смысловой, не побуквенный, паритет) и про то, что RU считается базой с проверкой по коду — обе корректно помечены как несущественные для владельца и не эскалированы искусственно.
## Чего не проверял
- Не запускал `npm test` / `npx tsc --noEmit` / `npm run build` / `npm run gate:small` — на этапе ТЗ кода ещё нет (ветка пуста), эти гейты неприменимы к спек-ревью и относятся к код-ревью.
- Не проверял `node scripts/check-docs.mjs --external` в строгом смысле (сетевые ссылки) — не нужно на этом этапе; команда лишь прочитана и подтверждена как существующая с ожидаемым поведением.
- Не оценивал качество будущего перевода/содержания — его ещё не существует; AC2/AC3 по договорённости ТЗ доказываются на код-ревью чек-листом тем и сверкой с `src/i18n/en.json`.
- Не сверял каждый пункт списка тем (мебель, живой текст, замки и т.д.) с каноническими документами подсистем (`WALL-THICKNESS.md`, `SUN.md`, `TOUCH-SUPPORT.md`) построчно — это работа автора реализации и код-ревьюера при написании фактического текста, не предмет проверки формулировки ТЗ.
## Вердикт
Вердикт: жёлтый · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 1 → в задаче
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/668-user-guide`, коммит `2f857a0f6b81` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `1ccf52c4df9d7dfc33d3e5cbb63baf142eab53a2`
```
git log --all --format='%H %T' | grep 1ccf52c4df9d
```
- Тело issue: `6f92c0a35cb43dd19a414618b4d1f9c48394a8107b95c61bacbe7fbf03d8bef9`
- Вердикт конвейера: `yellow` · High 0