docs: spec #266 revision 2 — scope-keyed diff, media-wrapper gates, real size caps

Issue: #266
User-Visible: no
This commit is contained in:
Codex
2026-08-26 00:44:00 +03:00
parent 5c466b6c01
commit afb6e151e5
+7 -5
View File
@@ -1,7 +1,7 @@
# ТЗ #266 — Расщепить styles.ts на файлы поверхностей
Issue: https://github.com/Matysh/houseplan-card/issues/266
Статус: ревизия 1.
Статус: ревизия 2 (после SPEC-REVIEW-266-r1: scope-ключ сверки, обязательные смоки медиа-обёрток, фактические пороги размера, класс B для scripts/**).
База: #34 (зонтик декомпозиции, этап 5), #241 (соразмерный выбор проверок), прецедент `editor-secondary.styles.ts`.
## 0. Сценарий
@@ -45,7 +45,8 @@ export const cardStyles: CSSResultGroup = [
2. **Без дубликатов.** Юнит: множества селекторов пяти файлов попарно не пересекаются (парсинг заголовков правил; допущенные исключения перечисляются в тесте явно с причиной, ожидаемо — пустой список).
3. **Порядок склейки фиксирован.** Юнит: `cardStyles` — массив ровно из пяти элементов в порядке §1.2 (сравнение ссылок на импортированные константы).
4. **Бандл не растёт больше шума.** Сравнение размера `dist/houseplan-card.js` до/после: дельта ≤ 1 КБ (склейка тех же строк).
5. **Refactor-only.** Ни один селектор и ни одно объявление не добавляется, не удаляется и не редактируется — только перенос. Проверка ревьюером: нормализованное множество правил (селектор → текст объявлений) до и после совпадает; авторский инструмент сверки прикладывается к ветке (`scripts/dev/styles-diff.mjs`, класс C, удаляется или остаётся по решению ревью).
5. **Refactor-only.** Ни один селектор и ни одно объявление не добавляется, не удаляется и не редактируется — только перенос. Проверка ревьюером: нормализованное множество правил до и после совпадает, где ключ правила — **полный путь вложенности** (`@media`/`@supports`/`@keyframes`-обёртки) + селектор, значение — отсортированные декларации. Потеря или смена медиа-обёртки при переносе меняет ключ и краснит сверку — ровно сценарий отказа из SPEC-REVIEW-266-r1 (golden не эмулирует `forced-colors` и снимает всё под `reducedMotion: 'reduce'`). Инструмент: `scripts/dev/styles-diff.mjs` (класс B, остаётся в репозитории).
6. **Медиа-обёртки под прямым прогоном.** Слепые зоны golden закрываются смоками: `smoke_plan_snap_overlay.mjs` (блок `forced-colors` у `.plan-snap-line`/`.hidden-wall-line`) и `smoke_preloader.mjs` (`prefers-reduced-motion` boot-pulse) обязательны на слайсах `plan` и `base`. Блок `.iso-*` под `forced-colors` не покрыт ни одним прогоном — его перенос дополнительно фиксируется юнитом: в итоговой склейке присутствуют оба `@media (forced-colors: active)` блока с их правилами (проверка по данным инструмента сверки).
### 1.4 Порядок работ — слайсы
@@ -73,17 +74,18 @@ CHANGELOG не трогается (User-Visible: no, пиксели не мен
## 6. AC
1. `src/styles.ts` ≤ 40 строк: только импорты, комментарий о порядке каскада и `export const cardStyles`. Доказательство: ревью кода + юнит §1.3.3.
2. Пять файлов `src/styles/*.styles.ts`, каждый ≤ 1 200 строк. Доказательство: ревью кода.
2. Пять файлов `src/styles/*.styles.ts`; фактический замер прототипа расщепления: base 300, chrome 447, devices 623, dialogs 1452, plan 1609 строк — порог: каждый ≤ 1 650, сумма пяти файлов + сборщик ≤ исходных 3 690 строк + 5 % (накладные заголовки/импорты). Доказательство: ревью кода.
3. Golden: 129/129 зелёные, эталоны байтово не менялись (`git status` чист по `demo/golden/baselines/`). Доказательство: `golden`-прогон CI + ревью диффа.
4. Юнит непересечения селекторов пяти файлов — зелёный, список исключений пуст (или обоснован построчно). Доказательство: `unit`.
5. Юнит порядка склейки §1.3.3 — зелёный. Доказательство: `unit`.
6. Нормализованное множество правил до/после идентично (инструмент §1.3.5, отчёт в ветке/комментарии). Доказательство: ревью кода по отчёту.
6. Нормализованное множество правил до/после идентично — ключ включает полный путь вложенности (§1.3.5); отчёт (`diff` двух JSON — пустой) в хендоффе, перепроверяется ревьюером. Доказательство: ревью кода по отчёту.
6a. Юнит присутствия медиа-обёрток: оба блока `@media (forced-colors: active)` и все 8 блоков `@media (prefers-reduced-motion: reduce)` присутствуют в итоговой склейке с исходными правилами. Доказательство: `unit`.
7. Дельта размера бандла ≤ 1 КБ. Доказательство: числа в хендоффе, перепроверяются ревьюером.
8. `npm test`, `build` + сверка трёх бандлов, `check-docs` — зелёные. Доказательство: CI.
## 7. План тестов
Юниты: непересечение селекторов, порядок и состав сборщика. Инструмент сверки правил (норм. множество) — прогон до/после на каждом слайсе. Golden: полный verify без переприёмки. Мутационный гейт: новых мутантов нет — refactor-only без новой логики; существующие мутанты остаются зелёными (их якоря вне styles.ts).
Юниты: непересечение селекторов, порядок и состав сборщика, присутствие медиа-обёрток (§6a). Инструмент сверки правил (scope-ключ) — прогон до/после на каждом слайсе. Смоки: `smoke_plan_snap_overlay` (forced-colors) и `smoke_preloader` (reduced-motion) обязательны на слайсах plan/base. Golden: полный verify без переприёмки. Мутационный гейт: новых мутантов нет — refactor-only без новой логики; существующие мутанты остаются зелёными (пять мутантных патчей адресуют `src/styles.ts` — их `file`/якоря обновляются на новые файлы поверхностей в коммитах соответствующих слайсов, юнит «якорь ровно один раз» держит реестр в актуальном состоянии).
## 8. Откат