Files
houseplan-card/docs/reviews/SPEC-REVIEW-337-r1.md
T
2026-08-28 05:40:28 +00:00

141 lines
15 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-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-находки
сняты с записью выше. Статус — «Готово к разработке».