mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
@@ -0,0 +1,171 @@
|
||||
# SPEC-REVIEW-266-r3
|
||||
|
||||
Issue: [#266](https://github.com/Matysh/houseplan-card/issues/266) — «Рефакторинг 3/5: расщепить styles.ts»
|
||||
ТЗ: `docs/specs/266-split-styles.md` (коммит `3a49b142`, ветка `issue/266-split-styles`)
|
||||
Предыдущий раунд: SPEC-REVIEW-266-r2, вердикт жёлтый (Medium М2), ТЗ проверялось на коммите `afb6e151`
|
||||
Этап: spec (PROCESS.md §2.4) · заход r3 · блокирующих циклов израсходовано 2/4
|
||||
Вердикт: **зелёный**
|
||||
|
||||
## Скоуп ревью
|
||||
|
||||
Третий заход, разбор по дельте (PROCESS.md §2.10, issue #214). Предмет — изменения
|
||||
ТЗ между `afb6e151` (на чём получен вердикт r2) и `3a49b142` (текущий HEAD):
|
||||
|
||||
```
|
||||
git diff afb6e151..3a49b142 -- docs/specs/266-split-styles.md
|
||||
```
|
||||
|
||||
Дельта — 4 строки: строка «Статус», AC2 (арифметика прототипа), AC6a (счёт
|
||||
`prefers-reduced-motion`-блоков 8→10). Правка только текстовая, точечная,
|
||||
адресует ровно находку M2 из r2 — не ребейз, не смена контракта поведения, не
|
||||
новая подсистема, объём несопоставим с исходной задачей → полный повторный
|
||||
разбор не требуется. Заново проверены AC2 и AC6a и всё, до чего дотягивается
|
||||
эта дельта (числа, на которые они ссылаются, и юнит, который их фиксирует).
|
||||
Остальной текст ТЗ наследуется из r2 без повторной проверки (раздел ниже).
|
||||
|
||||
**Важное отступление от обычного заходa этой стадии.** Между r2 и r3 в ветку
|
||||
`issue/266-split-styles` дополнительно попали 6 коммитов реализации
|
||||
(`cbdc2489`, `c684f178`, `7d094fd2`, `bf52524d`, `55f7126a`, `0d9320fe`) —
|
||||
инструмент-генератор слайсов и все пять файлов `src/styles/*.styles.ts` плюс
|
||||
финальный сборщик. Автор сообщил об этом честно в комментарии к ревизии 3:
|
||||
подготовленные заранее коммиты реализации уехали в публикуемую ветку по
|
||||
ошибке (несработавший `stash` перед `push`, унесённый ребейзом), историю
|
||||
опубликованной ветки не переписывает. Разбор ниже — отдельным разделом
|
||||
«Процессное замечание», не как находка по тексту ТЗ.
|
||||
|
||||
## Как проверялось
|
||||
|
||||
- Прочитан диф `afb6e151..3a49b142` целиком для `docs/specs/266-split-styles.md`
|
||||
(выше) и полный текущий текст файла.
|
||||
- Прочитан документ `docs/reviews/SPEC-REVIEW-266-r2.md` (коммит `34335d1e`) —
|
||||
находка M2 и её формулировка.
|
||||
- Арифметика AC2 пересчитана вручную: `248+381+540+1180+1359+19 = 3727`;
|
||||
порог `3690×1.05 = 3874.5`; `3727 ≤ 3874.5` — сходится, разрыв r2 устранён.
|
||||
- Поскольку реализация уже физически лежит в ветке (см. отступление выше),
|
||||
числа AC2 и AC6a сверены не только с текстом ТЗ, но и с фактическим кодом —
|
||||
строгая проверка, а не совпадение на слово автора:
|
||||
- `wc -l src/styles.ts src/styles/*.styles.ts` → `19 / 248 / 381 / 540 /
|
||||
1180 / 1359` — совпадает с AC2 буквально, каждый файл под лимитом 1650,
|
||||
сумма 3727 под порогом 3874;
|
||||
- `grep -c '@media (prefers-reduced-motion: reduce)'` по пяти новым файлам
|
||||
→ 10 совпадений (`base.styles.ts`:1, `chrome.styles.ts`:1,
|
||||
`devices.styles.ts`:2, `plan.styles.ts`:6); `grep` того же паттерна по
|
||||
`src/styles.ts` на коммите r2 (`afb6e151`, до переноса) → тоже 10 — AC6a
|
||||
«10» верен, старые «8» из r1/r2 были ошибкой счёта, как и признаёт текст;
|
||||
- `@media (forced-colors: active)` — 2 блока и до, и после (в
|
||||
`plan.styles.ts`, строки 314 и 1189) — совпадает с AC6a;
|
||||
- прочитан `test/styles-split.test.mjs` — юнит буквально реализует то, что
|
||||
AC4/AC5/AC6a описывают (порядок сборщика, непересечение селекторов со
|
||||
списком исключений, счёт медиа-обёрток 2/10), и способен упасть: любое из
|
||||
трёх чисел, порядок массива или лишний общий селектор ломает assert.
|
||||
- Проверено наличие `demo/smoke_plan_snap_overlay.mjs` и `demo/smoke_preloader.mjs`,
|
||||
названных в §7 ТЗ как обязательные на слайсах `plan`/`base` — оба файла на
|
||||
месте.
|
||||
- process-gate прогнан для диагностики процессного замечания (см. ниже):
|
||||
`node scripts/process-gate.mjs --issues` → `FAIL п.8 статус issue — issue
|
||||
#266: статус S4-spec-review, а нужен один из S5-ready / S6-in-progress /
|
||||
S7-code-review / S8-merged`.
|
||||
|
||||
## Закрытие раунда r2
|
||||
|
||||
| Находка r2 | Чем закрыта | Где видно |
|
||||
|---|---|---|
|
||||
| **M2** (Medium, в скоупе) — AC2 «факт» 4431 строка не проходил собственный порог 3874.5, разрыв не объяснён | AC2 переписан: источник роста назван явно (пустые строки-разделители генератора-прototipa), приведён уплотнённый замер 248/381/540/1180/1359+19=3727 ≤ 3874 | `docs/specs/266-split-styles.md`, AC2 (диф `afb6e151..3a49b142`); арифметика и цифры перепроверены против фактических файлов `src/styles/*.styles.ts` (раздел «Как проверялось») — совпадают буквально |
|
||||
|
||||
Побочно, вместе с M2, автор поправил и AC6a (счёт `prefers-reduced-motion` 8→10) —
|
||||
это не было находкой r2 (r2 унаследовал L2-риск как «не критично»), но правка
|
||||
корректна и подтверждена: фактический счёт в источнике на момент r2 (`afb6e151`)
|
||||
и сейчас — 10, «8» было ошибкой обоих предыдущих раундов, как и пишет автор.
|
||||
|
||||
## Унаследовано из r2
|
||||
|
||||
Без повторной проверки, документ `docs/reviews/SPEC-REVIEW-266-r2.md` на `afb6e151`:
|
||||
|
||||
- §0 (сценарий), §1.1 (структура каталога, распределение по кластерам),
|
||||
§1.2 (сборщик, внешний контракт `cardStyles`) — не тронуты дельтой r2→r3;
|
||||
- §1.3.1–§1.3.4 (golden как главный критерий, запрет дубликатов, порядок
|
||||
склейки, бюджет бандла) — не тронуты;
|
||||
- §1.3.5/§1.3.6 (scope-ключ сверки, обязательные смоки `forced-colors`/
|
||||
`reduced-motion`) — унаследованы из r2, который сам унаследовал их как
|
||||
закрытие M1 из r1 (`SPEC-REVIEW-266-r1.md` на `4c93f28e`);
|
||||
- §1.4 (порядок слайсов), §2 (скоуп/не-скоуп), §3 (UX/i18n/touch), §4 (риски),
|
||||
§5 (release-артефакты), §8 (откат) — не тронуты;
|
||||
- AC1, AC3, AC4, AC5, AC6, AC7, AC8 — текст не менялся дельтой r2→r3;
|
||||
доказательства AC4/AC5/AC6a перепроверены заново в этом раунде (см. выше),
|
||||
поскольку дельта их задевала через AC6a; AC1/AC3/AC6/AC7/AC8 наследуются
|
||||
без повторной проверки;
|
||||
- классификация «класс A, полный флоу», обязательные разделы §7.1 — приняты
|
||||
в r1, не пересматривались.
|
||||
|
||||
## Процессное замечание (не находка по ТЗ, не блокирует вердикт)
|
||||
|
||||
Между r2 и r3 в ветку попали 6 коммитов реализации класса A (`src/**`):
|
||||
инструмент `scripts/dev/styles-split.mjs` и пять файлов
|
||||
`src/styles/*.styles.ts` + финальный сборщик `src/styles.ts` — то есть
|
||||
продуктовый код написан и закоммичен, пока issue #266 находится в статусе
|
||||
`S4-spec-review`, раньше «Готово к разработке». Это прямое совпадение с
|
||||
формулировкой PROCESS.md §12: «Запрещено: код без issue или из статуса
|
||||
раньше «Готово к разработке»».
|
||||
|
||||
Автор сообщил об этом сам и честно (комментарий к ревизии 3): заранее
|
||||
подготовленные коммиты реализации уехали в публикуемую ветку по ошибке
|
||||
(несработавший `stash` перед `push`, унесённый последующим ребейзом), история
|
||||
опубликованной ветки не переписана. Намеренного нарушения или сокрытия нет.
|
||||
|
||||
Тем не менее это стоит зафиксировать отдельно, а не просто отметить в тексте
|
||||
ревью (§12: «оставили в тексте ревью» закрытием не считается — этот принцип
|
||||
для находок out-of-scope, но по духу применим и здесь, раз правило нарушено
|
||||
буквально). Дополнительно: механическая проверка это правило действительно
|
||||
умеет ловить (`node scripts/process-gate.mjs --issues` → `FAIL п.8`), но
|
||||
только пока метка issue равна текущей `S4-spec-review`. Как только этот
|
||||
вердикт станет зелёным и метка перейдёт в `S5-ready` (штатный следующий шаг),
|
||||
повторный прогон того же гейта на тех же коммитах пройдёт зелёным — проверка
|
||||
п.8 сверяет **текущую** метку issue с диапазоном коммитов, а не метку на
|
||||
момент, когда коммит был написан. То есть нарушение, которое сейчас поймано
|
||||
случайно (ревью совпало по времени с окном, где метка ещё не сдвинулась),
|
||||
станет невидимым естественным ходом процесса — ровно случай из PROCESS.md
|
||||
§12: «если правило удалось нарушить незаметно, виновата проверка».
|
||||
|
||||
Завёл отдельный issue с меткой `process` (не блокирует эту задачу и не входит
|
||||
в бюджет циклов #266): **#311** «process-gate п.8 проверяет текущую метку
|
||||
issue, а не метку на момент коммита — код #266 обгонит собственную DoR
|
||||
незаметно».
|
||||
|
||||
Это не находка по содержанию ТЗ — сам документ `docs/specs/266-split-styles.md`
|
||||
не пишет и не подтверждает несуществующее поведение задним числом; наоборот,
|
||||
случайно попавшая реализация дала возможность сверить AC2/AC6a не с оценкой
|
||||
автора, а с фактическим кодом (см. «Как проверялось»), что только укрепило
|
||||
уверенность в ревизии 3. Вердикт по ТЗ не меняется этим замечанием.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Оба обязательных первых раздела (§0 «Сценарий», «Что человек увидит») на
|
||||
месте и не тронуты дельтой — задача refactor-only, продуктового поведения
|
||||
нет, сформулировано честно ещё в r1 и не оспаривалось.
|
||||
- Все обязательные разделы §7.1 присутствуют (структура, скоуп/не-скоуп,
|
||||
контракт, UX/данные/i18n/touch, AC1…AC8 с доказательством у каждого, план
|
||||
автотестов, риски, откат, release-артефакты).
|
||||
- Догадок, выданных за факт, не найдено: единственное новое утверждение
|
||||
ревизии 3 (счёт reduced-motion-блоков «10», источник роста прототипа) явно
|
||||
подтверждено способом получения (`grep -n` по исходнику) и совпадает с
|
||||
фактическим кодом ветки.
|
||||
- Арифметика AC2 сведена и корректна (пересчитано вручную и против кода).
|
||||
- Открытых продуктовых вопросов нет.
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Тяжёлые гейты (`typecheck`/`test`/`build`/`golden`/смоки/мутационный
|
||||
гейт) прогонами не запускал. Дельта этого раунда — 4 строки текста ТЗ, для
|
||||
которых это несоразмерно; сами гейты и полный код — предмет код-ревью
|
||||
(`S7-code-review`), которое ещё не началось (issue не покидал S4).
|
||||
Совпавшие с этим раундом коммиты реализации сверил точечно (`wc -l`, `grep`,
|
||||
чтение `test/styles-split.test.mjs`) ровно в объёме, нужном для проверки
|
||||
AC2/AC6a этого ТЗ, а не как код-ревью — полный аудит реализации (стиль,
|
||||
покрытие мутационного гейта, побочные правки в `scripts/fix-test-build.mjs`
|
||||
и `scripts/mutation-gate.mjs`) будет сделан на своём этапе.
|
||||
- Не проверял, синхронизированы ли три копии бандла (`dist/`,
|
||||
`custom_components/houseplan/frontend/`, `demo/srv/assets/`) — не предмет
|
||||
спек-ревью.
|
||||
- Не запускал `demo/smoke_plan_snap_overlay.mjs` / `demo/smoke_preloader.mjs`
|
||||
сам — только подтвердил их существование; коммит-сообщения слайсов 4 и 5
|
||||
заявляют «OK», перепроверка результата смоков — код-ревью.
|
||||
Reference in New Issue
Block a user