# SPEC-REVIEW-337-r1 - Issue: https://github.com/Matysh/houseplan-card/issues/337 - ТЗ: `docs/specs/337-lazy-editor-chunk.md`, commit `6e7ab6b7` (ветка `issue/337-lazy-editor-chunk`, HEAD detached) - Трек: полный (обоснование в аналитике: производительность + несколько поверхностей/public asset contract — критерий §5 назван, `small` корректно отклонён) - Этап: spec-review, заход r1, блокирующих циклов израсходовано 0/4 - Вердикт: **зелёный** ## Скоуп Задача переносит View/editor границу frontend в реальную модульную границу (`src/editors/runtime/`), делает multi-asset build/раздачу/CI/HACS-контракт и безопасно минифицирует статические CSS-литералы, чтобы initial View graph уложился в ≤256 000 B gzip. Данные/layout/геометрия/UX/touch policy не меняются, только: (а) до входа в редактор код редакторов не грузится, (б) при редкой ошибке загрузки чанка показывается новое локализованное сообщение, а View остаётся рабочим. Проверка по `docs/SCOPE.md`: работа не добавляет функциональность — она инфраструктурно защищает J1/J6 (быстрый рабочий View для kiosk/tablet-персон, которые являются «the product» по SCOPE) и не задевает ни один пункт out-of-scope. Отдельный вопрос владельцу не нужен: видимое поведение не меняется, кроме двух явно описанных добавлений (индикатор ожидания, сообщение об ошибке), и автор прямо заявил в комментарии, что продуктовых вопросов нет — это соответствует действительности, разночтений о персоне/сценарии в ТЗ я не нашёл. ## Как проверялось Ревью документа на этом этапе не имеет кода для гейтов (typecheck/test/build неприменимы — commit `6e7ab6b7` меняет только `docs/specs/337-lazy-editor-chunk.md`). Вместо этого каждое фактическое утверждение ТЗ, которое можно спутать с непроверенной догадкой, сверено с текущим репозиторием на `HEAD`: | Утверждение ТЗ | Проверка | Результат | |---|---|---| | `dist/houseplan-card.js` 1 353 147 B raw / 378 335 B gzip, `src/houseplan-card.ts` ≈1052 KiB, View+3 редактора в одном классе | `wc -c src/houseplan-card.ts` → 1 071 305 B (22 809 строк) | согласуется с заявленным порядком величины | | `custom_components/houseplan/__init__.py` раздаёт один точный файл `StaticPathConfig(FRONTEND_URL, ...)` без auth | прочитан файл целиком | подтверждено; новый asset-route не вводит новый класс уязвимости — паритет с текущим | | GUI config editor (`houseplan-card-editor`) сейчас eager | `grep "import './editor'"` в `houseplan-card.ts:190` — статический импорт | подтверждено, AC11 закрывает реальный источник веса | | Существующий `mode-transition` CSS-класс переиспользуется под loading surface | найден в `plan.styles.ts`/`houseplan-card.ts`, уже используется как de-emphasis coordinate | правдоподобно, а конкретная реализация прямо отнесена к §18 «принято предположительно» | | «Старый браузер, способный исполнять текущий ESM bundle, способен исполнять native dynamic import» (§12) | `tsconfig.json` target `es2021`, без даунлевелинга; в коде 811 использований `?.` и 110 `??` — уже требуется ES2020+ движок | **верно**: минимальный движок, способный распарсить нынешний бандл, уже новее движков без `import()` (Chrome 63/FF 67/Safari 11.1) — вычислено, не принято на веру | | Ручная установка сегодня — это копирование папки `custom_components/houseplan`, а не одного JS (README.md:109-112, USER-GUIDE.ru.md:97-102) | прочитаны оба файла | подтверждено — multi-asset дерево не ломает существующий документированный manual-install путь; отдельный top-level `houseplan-card.js` GitHub-asset никогда не был этим путём | | `docs/specs/README.md`/PROCESS.md §7.1 обязательные разделы | построчная сверка ТЗ §1–§18 | все присутствуют по содержанию (см. ниже) | | Трейлеры коммита `6e7ab6b7` | `git log -1 --format=%B` | `Issue: #337` / `User-Visible: no`, корректно — ТЗ не является пользовательским изменением | | #34 (направление декомпозиции, на которое ссылается §7.1) | `gh issue view 34` | #34 сам в `S3-spec`, ещё не утверждён; его текущий целевой tree (`editors/plan/`, `editors/devices/`, `editors/render/`, …) и «безопасный порядок» (render-слои → диалоги → контроллеры, маленькими слайсами) не совпадают дословно с `editors/runtime/` из #337 | Дополнительно сверены обязательные разделы ТЗ (`PROCESS.md` §7.1): сценарий (§1) · что человек видит (§2) · проблема (§3) · скоуп/не-скоуп (§4–§5) · контракт поведения и UX (§6) · архитектурный контракт (§7) · модель данных и миграция (§12) · i18n (§11) · AC1…AC13 с доказательством (§13) · план автотестов (§14) · риски (§15) · откат (§16) · release-артефакты (§17) · блок «принято предположительно» (§18). Все присутствуют по существу, не только по названию. ## Находки Ничего в статусе High или Medium-в-скоупе, требующего возврата автору. Три наблюдения Low, ревьюер снимает их с записью (правка необязательна, вносить можно по желанию автора в этом же цикле без отдельного возврата): 1. **`houseplan-space-card` не упомянута в границе runtime.** У неё есть собственный GUI config editor (`src/space-editor.ts`, статически импортированный в `space-card.ts:39`, 93 строки/3.3 KB raw). ТЗ §7.1/§6.2.6 описывает границу и AC11 только для `houseplan-card`. Снято: вклад в gzip пренебрежимо мал (на два порядка меньше бюджета), «Обе карточки в одном файле» и обе регистрируются надёжно — п.6.1.1 это покрывает; не наблюдается риска для AC1/AC2. Если авторы решат вынести и его — не помешает, но не является требованием этого ТЗ. 2. **Число/размер editor-чанков не ограничено.** Формально ТЗ можно закрыть набором очень мелких чанков, что било бы по числу HTTP-запросов при первом входе в редактор, хотя раздел «Риски» уже фиксирует намерение «переносить законченными typed slices». Снято: нет продуктового контракта на задержку входа в редактор кроме «не выглядит зависшим» (150 ms порог, §15), а именно этим и ограничен риск. 3. **Имя `src/editors/runtime/` разойдётся с целевым деревом #34** (`editors/plan/`, `editors/devices/`, `editors/decor/`, `render/`, `dialogs/` — сам #34 ещё в `S3-spec`, не утверждён). Это два разных среза: #34 — про читаемость и единственный источник состояния, #337 — про то, что статически не импортируется в entry; частичное совпадение целей не значит, что нужно ждать #34. Снято: §18 прямо относит имена внутренних модулей и форму typed host port к «принято предположительно, можно менять свободно» — реальной привязки к продукту нет, а сведение выполнимости и проверяемости ТЗ не страдает. Ни одна из трёх не задевает выполнимость или проверяемость ни одного AC1…AC13, поэтому они не поднимаются выше Low и не создают жёлтый вердикт. ## Что проверено и корректно - Числовой бюджет непротиворечив: «250 KiB» (§4.2) и «256 000 B» (issue, AC1/§13) — один и тот же порог (250×1024=256000), никакого двойного источника значения нет. - Каждый AC1…AC13 имеет явный, разный и проверяемый способ доказательства (unit/manifest-тест/Playwright-smoke/backend-тест/golden/статический гейт); ни один не сформулирован как «проверено ревьюером на глаз». - Не-цели (§5) корректно исключают геометрию, config/layout, `polyclip-ts`, lazy i18n, backend API/SVG-вычисления и automatic idle-prefetch — согласуется с `docs/SCOPE.md` (никакой новый функционал сверх заявленной работы) и не противоречит `docs/CONFIG-COMPATIBILITY.md` (миграции нет, контракт не сформулирован — не нужен, раз stored data не меняется). `docs/WALL-THICKNESS.md`/`CANVAS.md` не затронуты (геометрия explicitly вне скоупа) — глубокая сверка с ними не требовалась. - §6.4 (failure/retry/fingerprint) и §10 (fingerprint/cache) описывают ровно одну попытку retry, запрет auto-hard-reload и явную обработку mismatch — внутренне непротиворечиво и без недосказанных веток. - Формулировки пользовательских сообщений (§6.2.3, §6.4.2) — новый текст, а не изобретённая замена существующей терминологии `USER-GUIDE.ru.md`: там нет готовой фразы под этот сценарий (grep пуст), так что это не нарушение правила «UI не говорит на языке разработчика». - Блок «принято предположительно» (§18) корректно отделяет технические решения (имена модулей, формат manifest, реализация delayed-surface, механизм инвалидации manifest, gzip-параметры сборки, разбиение на коммиты) от того, что зафиксировано как продуктовое решение и менять нельзя (URL ресурса, отсутствие auto-reload, сохранение рабочего View при ошибке, отсутствие prefetch) — ровно то разделение, которого требует PROCESS.md §7.1. - Трек и метка (`S4-spec-review`, полный трек) корректны для задачи со сложностью 9/10 и влиянием на public asset contract. ## Чего не проверял - Гейты `npx tsc --noEmit` / `npm test` / `npm run build` / `bundle:sync` / `check-docs.mjs` / инварианты геометрии — **не запускал**: на этом этапе нет продуктового кода, диапазон коммита r1 — один файл в `docs/specs/`. Они становятся обязательными на этапе код-ревью (§2.7), когда появится реализация. - Достижимость бюджета ≤256 000 B самой декомпозицией — это инженерный риск, который ТЗ само называет негарантированным («если модульная декомпозиция не доводит граф до бюджета, задача не считается выполненной») и оставляет измеримым на этапе реализации; ревью ТЗ не может предсказать фактический результат code-splitting, только то, что критерий сформулирован проверяемо. - Полное содержание `docs/ARCHITECTURE.md`, `docs/DEVELOPMENT.md`, `docs/TOUCH-SUPPORT.md` не перечитывалось построчно — сверены только фрагменты, релевantные конкретным утверждениям ТЗ (раздел «Как проверялось»); геометрия/touch/config не в скоупе задачи, поэтому глубокого разбора WALL-THICKNESS.md/CANVAS.md/CONFIG-COMPATIBILITY.md не требовалось. ## Итог ТЗ выполнимо и проверяемо, разделы полны, продуктовых вопросов владельцу нет и не появилось при ревью, скоуп соответствует `docs/SCOPE.md`. Три Low-находки сняты с записью выше. Статус — «Готово к разработке».