From 2d4ace1b58ff1d47a83e4c09d479630b6111839f Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 27 Aug 2026 23:36:15 +0000 Subject: [PATCH] docs: review document for #62 Issue: #62 User-Visible: no --- docs/reviews/SPEC-REVIEW-62-r2.md | 119 ++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-62-r2.md diff --git a/docs/reviews/SPEC-REVIEW-62-r2.md b/docs/reviews/SPEC-REVIEW-62-r2.md new file mode 100644 index 00000000..800ac541 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-62-r2.md @@ -0,0 +1,119 @@ +# SPEC-REVIEW-62-r2 + +- **Issue:** https://github.com/Matysh/houseplan-card/issues/62 +- **ТЗ:** `docs/specs/062-i18n-registry.md` +- **Материал ревью:** ветка `issue/62-i18n-registry`, SHA `0a203649` +- **Заход:** r2 (повторный, разбор по дельте — PROCESS.md §2.10, issue #214) +- **Предыдущий раунд:** SPEC-REVIEW-62-r1, SHA `21d47c52`, вердикт жёлтый + (High: 0, Medium: 1 → в задаче), документ `docs/reviews/SPEC-REVIEW-62-r1.md` +- **Трек:** полный (без изменений с r1) — критерий `small` не выполняется, + задета class A i18n сразу в нескольких поверхностях. + +## Дельта + +`git diff 21d47c52..0a203649` затрагивает ровно один файл — `docs/specs/062-i18n-registry.md`, ++8/-2 строк, два места: + +1. §9 (i18n и документация) — добавлен абзац о судьбе существующей строки + `Ground rules` в `CONTRIBUTING.md`. +2. §10 (AC и доказательства) — уточнены формулировки доказательств AC2, AC5, AC8. + +Комментарий автора от 2026-08-27 подтверждает тот же объём: «убран ложный scope +lazy loading, исправлена политика документации, добавлен compatibility-контракт +… доказательства AC» — но фактический diff между r1 и r2 меньше объявленного: +lazy loading и compatibility-контракт неизвестного языка (§6.3/§8) были частью +диапазона **до** r1 (SHA `21d47c52` уже их содержал и был материалом r1), в +диапазоне r1→r2 их нет. Не расхождение с текущей проверкой — просто автор +описал изменения с более раннего SHA, чем зафиксированный r1; дельта r1→r2 сама +по себе локальна и не требует полного разбора (§2.10: правка не меняет контракт +поведения, не задевает новую подсистему, размер несопоставим с задачей). + +Дешёвые гейты (`typecheck`/`test`/`build`) не прогонялись по той же причине, что +и в r1: диапазон `origin/dev...HEAD` не содержит ни одного файла class A/B, +только документы. Продуктового кода по-прежнему нет — это ожидаемо для этапа ТЗ. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +| --- | --- | --- | +| **M1** (Medium, в скоупе): §9/AC9 добавляют новый раздел «Translations», но не отменяют существующую в `CONTRIBUTING.md` строку Ground rules «one JSON file + registering it in `src/i18n.ts`» — реализация оставит два противоречащих flow | В §9 добавлен явный абзац: «Существующая строка в `Ground rules` … не остаётся рядом вторым контрактом: она заменяется ссылкой на новый раздел и формулировкой про frontend/backend JSON и `src/i18n/registry.ts`» | `docs/specs/062-i18n-registry.md:196-199` (diff `21d47c52..0a203649`) | +| **L1** (Low, снят с записью в r1, не требовал правки): AC2 без явного маркера «Доказательство:» | Добавлен явный маркер | `docs/specs/062-i18n-registry.md:209` — «**Доказательство:** unit-тест pure resolver.» | +| **L2** (Low, снят с записью в r1, не требовал правки): AC5/AC8 используют слово «inspection» вместо канонического словаря доказательств | Слово «inspection» убрано из обеих AC, заменено на дифф-ориентированные формулировки | `docs/specs/062-i18n-registry.md:217` — «unit на pure options helper и source diff `src/editor.ts` без ручного списка локалей»; `:225` — «static registry source diff + успешный production build» | + +M1 был единственной блокирующей (Medium) находкой r1. Формулировка в §9 +конкретна и исполнима: указывает, что именно происходит со старой строкой +(заменяется, а не остаётся вторым источником истины) и чем — ссылкой на новый +раздел плюс актуальным описанием flow. Проверено чтением: `CONTRIBUTING.md:49` +на текущий момент действительно содержит цитируемую в r1 строку +`Adding a language = adding one JSON file + registering it in src/i18n.ts.` — +референт находки не устарел, и правка §9 бьёт точно по нему. + +L1/L2 не требовали правки по вердикту r1 («снимается без правки текста ТЗ»), +но автор закрыл их тоже — это не создаёт риска и не меняет решение раунда. + +Отдельно проверено: новая формулировка AC8 («static registry source diff + +успешный production build») не ослабляет доказательство относительно версии +r1. Утверждение AC8 — «в production bundle нет dynamic import/Promise-based +translation path» — при отсутствии `import(` в исходниках (что показывает +`source diff`) гарантированно не воспроизводится и в бандле статическим +TypeScript/Rollup пайплайном; сам r1 уже принял эквивалентный по строгости +метод («inspection») как допустимую категорию «проверено чтением, не +исполнением» (см. L2 в r1). Понижения строгости нет. + +## Унаследовано из r1 + +Без повторной проверки в r2 приняты следующие выводы SPEC-REVIEW-62-r1.md +(SHA `21d47c52`), поскольку дельта r1→r2 их не задевает: + +- Обязательные разделы §7.1 ТЗ присутствуют полностью (сценарий, что человек + увидит, проблема, скоуп/не-скоуп, контракт поведения, UX, модель данных и + миграция, i18n, AC1–AC9, план автотестов, риски, откат, release-артефакты). +- Продуктовых вопросов владельцу по существу нет; пограничный случай + (неизвестный сохранённый `language` в редакторе, §6.3/AC6) решён автором + обоснованно, без домысливания и без необходимости эскалации. +- Резолюция языка (§6.2) построчно проверена на эквивалентность текущему + рантайму для всех обычных значений HA locale; AC7 не нарушается. +- Заявление «English/Russian пользователь изменений не увидит» подтверждено + чтением: единственная новая видимая ветвь (временная option) активируется + только для кода, отсутствующего в registry. +- Тестовая стратегия (§11) опирается на уже используемый в проекте паттерн + (`test-build/*.js`), а не изобретает новый. +- Non-scope (§5), откат (§13) и release-артефакты (§14) заполнены осмысленно. +- Трек (полный) и его обоснование соответствуют умолчанию AGENTS.md/#338. +- Фактические утверждения ТЗ о текущем коде (`src/i18n.ts`, `src/editor.ts`, + `test/i18n.test.mjs`, `custom_components/houseplan/translations/`, + `tsconfig.test.json`, `src/types.ts:276`) сверены с деревом в r1 и дельта + r1→r2 их не меняет — код не изменился, диапазон `origin/dev...HEAD` + по-прежнему содержит только документы. + +## Что проверено в r2 и признано корректным + +- AC2/AC5/AC8 (§10) после правки используют канонический словарь доказательств + (`unit`, diff, «успешный production build») без потери проверяемости метода. +- §9 больше не оставляет `CONTRIBUTING.md` с двумя конфликтующими описаниями + contribution flow — инструкция для реализации однозначна. +- Изменение локально: не задевает контракт поведения (§6), не открывает новую + подсистему, не требует ребейза (origin/dev не продвинулся вперёд — + `git merge-base origin/dev HEAD` совпадает с текущим tip `dev`, `fffe9fb1`). + +## Чего не проверял и почему + +- **Гейты `typecheck`/`npm test`/`npm run build`/`check-docs.mjs`/smoke/golden/ + backend pytest** — не запускались, как и в r1: диапазон `origin/dev...HEAD` + по-прежнему не содержит ни одного файла class A/B, только `docs/**`. + Продуктового кода нет — гонять их не на чем на этапе ТЗ. +- **Инварианты модели / `smoke-select.mjs`** — не применимо, дельта не + затрагивает геометрию, `layout`, `marker.space`, `open_spans`, код вообще. +- Полный повторный разбор ТЗ (сценарий, non-scope, риски, откат и т.д.) не + проводился по правилам §2.10 — дельта локальна и не задевает эти разделы; + соответствующие выводы наследуются из r1 (см. раздел выше) без риска + регрессии, так как сами разделы текстуально не менялись между `21d47c52` и + `0a203649`. + +## Вердикт + +Единственная Medium-находка r1 закрыта конкретной, исполнимой формулировкой в +§9, оба Low-замечания закрыты сверх требуемого. Новых находок дельта r1→r2 не +вносит. High нет, Medium нет. + +**Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0**