15 KiB
SPEC-REVIEW-266-r3
Issue: #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», перепроверка результата смоков — код-ревью.