From 4bdd266fbbe4a74ed68143bc64d55e3008a01ef2 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 20:45:50 +0000 Subject: [PATCH] docs: review document for #43 Issue: #43 User-Visible: no --- docs/reviews/SPEC-REVIEW-43-r2.md | 159 ++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-43-r2.md diff --git a/docs/reviews/SPEC-REVIEW-43-r2.md b/docs/reviews/SPEC-REVIEW-43-r2.md new file mode 100644 index 00000000..44ed0d58 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-43-r2.md @@ -0,0 +1,159 @@ +# SPEC-REVIEW-43-r2 + +- Issue: https://github.com/Matysh/houseplan-card/issues/43 +- Ревьюер: Claude (роль «Ревьюер ТЗ», PROCESS.md §2.4) +- Материал: `docs/specs/043-private-support-report.md` на коммите `e25aa302` + (ветка `issue/43-help-feedback`), дельта против r1 (`docs diff + 00b68450..e25aa302 -- docs/specs/043-private-support-report.md`). +- Заход: r2 · блокирующих циклов израсходовано 1 из 4. +- Трек: полный (не изменился с r1). +- Формат разбора: **по дельте** (PROCESS.md §2.9, issue #214) — обоснование + ниже, в «Почему делаю по дельте, а не заново». + +## Предыдущий раунд + +- Вердикт r1: жёлтый · High 0 · Medium 1 (в скоупе) · Low 1 (снят без цикла). +- Комментарий с вердиктом: issue #43, 2026-09-01T20:40:11Z. +- Документ r1: `docs/reviews/SPEC-REVIEW-43-r1.md`, зафиксирован коммитом + `4559b5cd`. +- SHA, на котором получен вердикт r1: `755fa4cf` (упомянут в тексте вердикта + и в шапке `SPEC-REVIEW-43-r1.md`). Этот SHA не резолвится в текущем дереве — + автор пишет в хендоффе r2 «Ветка перебазирована на актуальный dev», и + `git rebase` переписал хеши; коммит с тем же содержимым сегодня называется + `00b68450` (`git diff 00b68450..HEAD` даёт содержательно тот самый и + единственный дифф, который описывает хендофф r2). + +## Почему делаю по дельте, а не заново + +Формально это ребейз на ушедший вперёд `dev` — сценарий, для которого +инструкция требует полного разбора, если ребейз действительно сделал это +«другим кодом» (§7.2). Проверил, что это не тот случай: + +- `git merge-base HEAD origin/dev` = `4fa670e8`; коммиты `dev` между старой и + новой базой (`823fc316..4fa670e8`: пин растеризации скриншотов, измерение + дрейфа кадра, гейт стабильности) не трогают ни `AGENTS.md`, ни + `PROCESS.md`, ни `scripts/process-gate.mjs`, ни `docs/TOUCH-SUPPORT.md` — + `git diff --stat` по этим путям в диапазоне пуст. Это ровно те четыре + документа, на которые опирались обе находки r1. +- `git diff 00b68450..HEAD --stat` показывает три файла: добавленный документ + ревью `docs/reviews/SPEC-REVIEW-43-r1.md` (артефакт публикации, не правка + автора), `docs/specs/README.md` (1 строка, не содержательная), и + `docs/specs/043-private-support-report.md` — 24 изменённые строки, все три + правки локализованы в §9.1, §11 и §18 и построчно соответствуют двум + находкам r1. +- Ни договор поведения (§4/§6–8), ни AC1–AC17 (§13), ни privacy allowlist + (§7.2/7.3), ни UX-контракт (§6) дельта не задевает. + +Поэтому разбор r2 ограничен: (а) доказать закрытие двух находок r1 построчно, +(б) проверить, что дельта не сломала ничего в соседних разделах, (в) +унаследовать всё остальное из r1 без повторной проверки. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| **Medium.** `support-relay/**` как новый top-level каталог не попадает ни в класс A, ни в B `scripts/process-gate.mjs::classify()` → коммит, трогающий только этот каталог, проходит гейт без трейлера `Issue:` и без проверки статуса issue. | §9.1 переписан: relay переехал под `scripts/support-relay/**`, что совпадает с `CLASS_B` (`/^scripts\//` в `scripts/process-gate.mjs:59`) без каких-либо правок `AGENTS.md`/`PROCESS.md`/`process-gate.mjs`. §18 добавляет обязательство держать runtime/manifest/tests/README relay целиком в этом поддереве и завести process-gate regression fixture, доказывающую, что relay-only коммит классифицируется как B. | `docs/specs/043-private-support-report.md:404-412` (§9.1), `:621-623` (§18). Проверено запуском `node scripts/process-gate.mjs` на HEAD — «гейт пройден, предупреждений 0», путь `scripts/support-relay/` реально попадает в `CLASS_B` по regex `scripts/process-gate.mjs:59`. | +| **Low.** §11 по содержанию реализует `Touch editor: supported`, но не содержит канонической фразы, которую требует `docs/TOUCH-SUPPORT.md`. | В §11 первой строкой добавлено `**Touch editor: supported.**` с уточнением, что диалог доступен из View и всех трёх редакторов с одинаковым touch-контрактом, а kiosk по-прежнему его скрывает. | `docs/specs/043-private-support-report.md:465-467`. Фраза дословно совпадает с канонической формой из `docs/TOUCH-SUPPORT.md:165` (`Touch editor: supported`). | + +Обе находки закрыты текстом, а не заявлением: правка видна в дифф-контексте +выше, а не только в комментарии автора. + +## Проверка дельты (не унаследовано — перепроверено заново) + +1. **Согласованность пути relay по всему документу.** `grep -n + "support-relay" docs/specs/043-private-support-report.md` даёт ровно два + совпадения (§9.1 заголовок и §18 release-артефакты) — оба уже указывают на + `scripts/support-relay/**`, старого top-level упоминания `support-relay/` + без префикса нигде не осталось. Более широкий `grep -n "relay"` (60+ + вхождений по всему файлу) показал, что остальные упоминания — это + архитектурная роль сервиса («project-controlled relay», «relay secret», + «relay fixture» и т.д.), а не файловый путь, поэтому переезд каталога их + не касается — переименование сделано полностью, частичной правки нет. +2. **Не нарушает ли новое место relay границу HACS-пакета.** `hacs.json` + (`zip_release: true`, `filename: houseplan.zip`) не перечисляет + содержимое явно — упаковка определяется отдельным релизным шагом, не + `process-gate.mjs`; `scripts/**` и раньше не попадал в + `custom_components/houseplan/frontend/` (единственный источник + HACS-фронтенда по `CLASS_D`). Утверждение «excluded from the HACS + artifact» в §9.1 остаётся верным после переезда, это не новый риск, + привнесённый дельтой. +3. **Не конфликтует ли `scripts/support-relay/**` с существующей ролью + `scripts/`.** `tsconfig.json` ограничивает typecheck `src/**/*.ts`; + каталог `scripts/` уже состоит из `.mjs`/`.py`-скриптов вне зоны + компиляции TS — новый relay-код в том же дереве не меняет эту границу и + не требует правки `tsconfig*.json` (что и означало бы `A+B`, а не только + `B`, в терминах самого §9.1). +4. **Формулировка "a product commit that also changes `src/**` remains A+B и + follows the stricter class-A flow"** (§9.1) сверена с + `scripts/process-gate.mjs:137` (`classes: new Set(files.map(classify))`) и + условиями `classes.has('A') || classes.has('B')` для строгих проверок — + описание корректно: набор классов коммита — это множество классов всех + его файлов, а не единственная метка. +5. **Трейлеры коммита дельты.** `git show e25aa302 -s` → `Issue: #43`, + `User-Visible: no` — верно для docs-only правки без видимого поведения. +6. **Гейты на этой дельте.** Дифф `00b68450..e25aa302` строго класса C + (только `docs/specs/043-private-support-report.md`). Прогнал: + - `node scripts/process-gate.mjs` → «диапазон origin/dev..HEAD, коммитов + 3; гейт пройден, предупреждений 0» (офлайн, без `--issues`); + - Validate CI на `e25aa302` зелёный (см. ссылку в хендоффе автора и в + инструкции ревью) — покрывает `tsc --noEmit`/`npm test`/`npm run + build`, предмета для которых у docs-only дельты и так нет. + `check-docs.mjs`, browser-смоки, `model-invariants`, `pytest + tests_backend`, golden — не прогонял: `src/**`, `custom_components/**` и + геометрия/`layout` дельтой не тронуты, у этих гейтов нет предмета + проверки на чисто документном коммите (то же обоснование, что в r1). + +## Унаследовано из r1 (без повторной проверки) + +Документ: `docs/reviews/SPEC-REVIEW-43-r1.md`, зафиксирован на `4559b5cd`, +разбирал ТЗ на `00b68450` (тогда назывался `755fa4cf` до ребейза). +Дельта r1→r2 не задевает ни один из пунктов ниже, поэтому принимаю выводы r1 +без повторной проверки: + +- Обязательные разделы §7.1 (сценарий, до/после, проблема, скоуп, контракт + поведения, UX, модель данных/миграция, i18n, AC1–AC17, план автотестов, + риски, откат, release-артефакты) — все на месте и однозначны. +- Продуктовые вопросы Q1–Q5 корректно отделены от технических и закрыты + владельцем в issue дословно, без додумывания. +- Пять утверждений §3 о текущем состоянии кода проверены построчно по + `src/houseplan-card.ts`, `src/houseplan-editor-runtime.ts`, + `custom_components/houseplan/{websocket_api,import_export,repairs}.py`, + `src/i18n/*.json` — расхождений не найдено. +- Privacy allowlist/exclusion §7.2/7.3 внутренне непротиворечивы; точная + геометрия включена осознанно как продуктовое решение (Q2), а не побочный + эффект. +- «Одно число — один источник» для preview/download/submit спроектировано + контрактом (кешированный TTL-токен + mutation-gate §6.4/7.1/8.1/AC5/AC10 + + §14.4), а не оставлено на волю реализации. +- Технические допущения промаркированы в §20 как «assumed, change freely». +- i18n RU/EN/DE/FR соответствует уже существующим локалям, список языков не + расширяется произвольно. +- Cross-links issue↔ТЗ↔`docs/specs/README.md` на месте. +- DoR-зависимости §17 (relay deployment, mailbox, staging) корректно вынесены + как внешние операционные факты с явным `blocked`-путём, а не спрятаны как + допущения. + +## Чего не проверял (r2) + +- Полные `npm test`/`npm run build`/browser-смоки/`model-invariants`/`pytest + tests_backend` — не прогонял отдельно: Validate CI зелёный на этом самом + SHA (`e25aa302`), а дельта и так docs-only без предмета для этих гейтов. +- Реальная развёртываемость relay, секреты, содержимое ещё не написанного + `scripts/support-relay/**` — кода ещё нет, это заявленная DoR-зависимость + §17/§18, появится на этапе реализации и code-review. +- Golden/скриншоты, performance-профили — не относятся к докс-only дельте. +- Process-gate regression fixture, которую §18 требует для доказательства + классификации relay-only коммита как B — она появится вместе с кодом; + на этапе ТЗ можно проверить только текст требования (проверено, есть). + +## Вывод + +Обе находки r1 закрыты предметно, построчно и без побочных повреждений +соседних разделов: relay-код явно и полностью перенесён в уже +классифицированный класс-B каталог `scripts/support-relay/**` (подтверждено +чтением `scripts/process-gate.mjs` и живым прогоном гейта), а §11 получил +каноническую фразу `Touch editor: supported`, дословно совпадающую с +требованием `docs/TOUCH-SUPPORT.md`. Ребейз на актуальный `dev` не изменил +существа рассмотрения: коммиты `dev`, вошедшие в диапазон, не трогают ни один +документ, на который опирались находки r1. Новых находок в дельте нет. +Rec: **зелёный**, готово к переводу в `S5-ready`.