docs: review document for #337

Issue: #337
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-28 05:40:28 +00:00
parent 4485417027
commit 5a703ef562
+140
View File
@@ -0,0 +1,140 @@
# 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-находки
сняты с записью выше. Статус — «Готово к разработке».