From 8afba7e6edb5f747cb0d644cd949331bae4cec40 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Fri, 11 Sep 2026 15:31:27 +0000 Subject: [PATCH] docs: review document for #532 Issue: #532 User-Visible: no --- docs/reviews/SPEC-REVIEW-532-r1.md | 166 +++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-532-r1.md diff --git a/docs/reviews/SPEC-REVIEW-532-r1.md b/docs/reviews/SPEC-REVIEW-532-r1.md new file mode 100644 index 00000000..2ed6d6c1 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-532-r1.md @@ -0,0 +1,166 @@ +# SPEC-REVIEW — issue #532 · заход r1 + +## Скоуп ревью + +Issue #532, полный трек (владелец назвал нарушенный критерий §5: «нет влияния на +производительность» — задача целиком о нём). ТЗ живёт в теле issue под +заголовком `## ТЗ` (решение #517); ревью — этот документ, не комментарий, как и +положено полному треку. Раунд первый: `git log --oneline origin/dev..HEAD` для +#532 пуст, кода ещё нет — предмет ревью строго текст ТЗ и его согласованность с +текущим состоянием репозитория (`dev`@`116cfd5f`). + +Материал: тело issue #532 (разделы до `## ТЗ` — симптом и замер S1; раздел +`## ТЗ` — собственно спецификация; `## Состояние при заведении` — метаданные +заведения) и два комментария («Аналитика (S2)», «ТЗ готово — на ревью (S3→S4)»). +Устных пояснений автора не запрашивалось. + +## Как проверялось + +1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` §2.3/2.4/7.1/7.2/§4, + `docs/SUN.md` (раздел «Current four-phase background»). +2. Каждое техническое утверждение ТЗ сверено с текущим кодом, а не принято на + слово: + - `grep` по `src/styles/plan.styles.ts` подтвердил дословно селектор К1 — + `.stage.daycycle .hp-paperg, .hp-static-stage.daycycle .hp-paperg` со + стопкой из трёх `drop-shadow` и `transition: filter 1100ms …` (строки + 89–96), плюс дубль в `@media (prefers-reduced-motion: reduce)` (100–101). + Ровно то место, куда К1 просит добавить `will-change: filter`. + - `grep` по `src/space-render.ts`/`houseplan-card.ts` подтвердил, что класс + `daycycle` навешивается только когда `dayCycle` вычислен (т.е. только при + `bg_mode: 'daynight'`) — это подтверждает АC1/AC4 («при статичном фоне — + не несёт, и `filter` тоже отсутствует»): без класса `.daycycle` селектор + К1 не совпадает вовсе, значит ни `filter`, ни будущий `will-change` не + применятся. + - `demo/golden/matrix.mjs` подтвердил дословно цифры К2: сценарии + `day-cycle-{dawn,day,dusk,night}-dark` используют пресет `stage` — + `{ maxChannelDelta: 10, maxDiffRatio: 0.0005 }` (строка 6) — именно то, + что ТЗ называет действующим порогом. + - `src/glow-blend.ts` подтвердил утверждение К4: `svgScreenBlendSupported` + — рантайм-проба, не читающая `bg_mode`; довод «свет не зависит от фона» + обоснован кодом, а не только измерением. +3. Проверены на однозначность и способ доказательства все AC1–AC5 (таблица + ниже), включая то, умеет ли названный мутант/проверка отличить сломанную + защиту от рабочей — насколько это можно оценить до появления теста. +4. Сверены обязательные разделы §7.1 с текстом ТЗ (таблица ниже). +5. Проверено разделение «продуктовый вопрос / техническое решение» (§7.1, + владельцу — только о том, что видит и делает человек). + +Гейты (`typecheck`/`test`/`build`) не запускались: на этой стадии нет кода +`#532` — `git log --oneline origin/dev..HEAD` для ветки задачи пуст, дерево +ровно на `116cfd5f`. Прогонять их нечего — это забота код-ревью следующего +этапа. + +## Проверка обязательных разделов ТЗ (PROCESS.md §7.1) + +| Раздел §7.1 | Есть в ТЗ | Где | +|---|---|---| +| Сценарий (персона/поверхность/момент) | да | «Продуктовая рамка»: домочадцы и админ в View, настенный планшет/телефон/десктоп, сам план | +| Что человек увидит до/после | да | «До.»/«После.» | +| Проблема | да (фактически) | абзац «До.» плюс разделы до `## ТЗ` (Симптом, замер аналитики) — единый контекст issue, а не выдумка | +| Скоуп и не-скоуп | да | К1 задаёт единственную правку; «Чего задача не трогает» — явный не-скоуп | +| Контракт поведения | да | К1–К4 | +| UX | да (в виде «нет») | «Ни одной новой настройки, ни одного нового элемента интерфейса» | +| Модель данных и миграция | да (в виде «нет») | «не трогает: … bg_mode и его миграции» | +| i18n | да (в виде «нет») | «не трогает: … i18n» | +| AC1…ACn с доказательством | да | таблица «AC и доказательства», у каждого — «чем доказан»/«чем краснеет» | +| План автотестов | да | новый смок `demo/smoke_daycycle_raster.mjs`, его регистрация в `smoke-links.mjs`/`check-inputs.mjs`, мутант в `mutation-gate.mjs` — раздел «Затронутые файлы» | +| Риски | да | 4 риска, включая главный технический (бюджет `will-change` в Gecko) с планом на случай провала | +| Откат | да | одна строка — ревёрт декларации | +| Release-артефакты | да | оба changelog, `docs/SUN.md`, `golden:verify` (AC3) | + +Все обязательные разделы присутствуют по содержанию. Формально «Продуктовая +рамка» идёт не первым текстом под `## ТЗ` (перед ней — строка автора, раздел +«Документация» и «Чего задача не трогает») — §7.1 хочет продуктовые разделы +первыми. Содержательно это ни на что не влияет: у issue нет предыстории, +которую скрывают, здесь просто иной порядок изложения. Low, не блокирует, не +записываю отдельной находкой. + +## Проверка AC на однозначность и доказуемость + +| AC | Однозначен? | Доказательство названо? | Комментарий | +|---|---|---|---| +| AC1 | да — `getComputedStyle` даёт `will-change: filter` да/нет, `filter` присутствует/отсутствует, по двум значениям `bg_mode` | да, `demo/smoke_daycycle_raster.mjs`, часть 1 | падает от мутанта `daycycle-outline-not-promoted» — правдоподобно: он снимает декларацию, `getComputedStyle` перестаёт видеть `will-change` | +| AC2 | да — числовой порог «не больше чем вдвое», отношение, а не абсолютные мс | да, тот же смок, часть 2, CDP-трасса `RasterTask` | заявленный запас (0.26 против порога 2.0, и 7.9 без правки) восьмикратный в обе стороны — порог не хрупкий | +| AC3 | да — 4 конкретных golden id | да, `npm run golden:verify` | пороги сверены с `matrix.mjs`, совпадают | +| AC4 | да, но по факту вторая половина AC1 | да | не дефект, просто разнесено на два номера ради «краснеет» на другой мутации (декларация без `.daycycle`) | +| AC5 | да — два конкретных факта (текст в `SUN.md`, обе строки changelog) | да, «ревью кода построчно» — допустимый способ доказательства для документных AC | — | + +Ни один AC не сформулирован как решение-без-обоснования: пороги (2.0; `7`/255 +канала; `2%` шум между прогонами) — измеренные величины из комментария S2, а +не придуманные числа, и это видно по совпадению цифр между комментарием и ТЗ. + +## Проверка «догадка вместо решения» + +Отдельный технический раздел «Принято предположительно» правильно +отделяет то, что не наблюдает пользователь и что решает автор (`will-change: +filter` vs `transform`, порог 2.0, движок свидетеля — Chromium, метод замера — +CDP `RasterTask`), от продуктовых утверждений. Ни одно продуктовое +утверждение (вид не меняется, новых настроек нет) не подано как факт без +основания — оба подтверждены измерением (максимальное отклонение канала 7 при +пороге 10) либо тривиальны (правка — одна декларация, интерфейс не трогается). + +Главная техническая неопределённость — бюджет памяти `will-change` в Gecko +может молча отклонить подсказку — не скрыта и не выдана за решённый вопрос: +она вынесена в Риск №1 с явным планом «если так — задача не закрыта, +переходит в К3». Это не относится к продуктовым вопросам владельца (§7.1: +только «что видит/делает человек» и «объём видимых изменений») — это +инженерная неопределённость стороннего движка, которую нельзя разрешить +вопросом, только измерением после реализации. Правильно, что автор сам назвал +её ревьюеру третьим пунктом «где спорить», а не спрятал. + +## Находки + +Нет ни одной находки High или Medium. Формальная асимметрия в порядке +разделов (см. выше) — Low, не блокирует и не создаёт риска для приёмки; в +исправлении не нуждается. + +## Что проверено и корректно + +- Все селекторы, свойства и значения, на которые ссылается ТЗ + (`.hp-paperg`, класс `daycycle`, стопка `drop-shadow`, `transition`, golden + id и их пороги, источник `screenBlend`), дословно совпадают с текущим + кодом на `116cfd5f` — ТЗ не описывает воображаемую версию файла. +- К3/К4 (слои окружения и блендинг света вне скоупа) обоснованы цифрами из + S2-аналитики (13% и «в пределах шума» соответственно), а не решением + «на глаз». +- AC2 использует отношение, а не абсолютные миллисекунды — устойчиво к шуму + раннера, восьмикратный запас в обе стороны от порога. +- Откат — одна строка, соответствует размеру правки. +- Не-скоуп корректно исключает миграции, i18n, touch-контракт, PDF-сцену — + все верно, ни один из них декларация `will-change: filter` не затрагивает. + +## Чего не проверял + +- Гейты `typecheck`/`test`/`build`/`golden`/смоки — нет кода для проверки на + этой стадии, дерево `#532` пусто относительно `dev`. +- Реальное поведение в Gecko/Firefox — по постановке самой задачи, это не + предмет автоматических AC, а предмет профиля владельца после реализации + («Приёмка по скорости — отдельно»); дать вердикт по нему на этапе спецификации + нельзя и не нужно. +- Существование/содержимое ещё не написанных файлов + (`demo/smoke_daycycle_raster.mjs`, правки `mutation-gate.mjs`, + `smoke-links.mjs`, `check-inputs.mjs`) — это работа код-ревью следующего + этапа, когда файлы появятся. + +## Вердикт + +Зелёный. ТЗ полное по §7.1, каждый AC однозначен и снабжён способом +доказательства и способом падения, технические утверждения проверены по +текущему коду и не разошлись с ним, продуктовая рамка и не-скоуп на месте, +единственная значимая техническая неопределённость (реакция Gecko на +`will-change`) явно признана риском с планом на случай провала, а не выдана +за решённую. Готово к разработке. + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `116cfd5fefc4` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `45453f44ff5e3243d824ab00132e42c14c9f7c33` + ``` + git log --all --format='%H %T' | grep 45453f44ff5e + ``` +- Тело issue: `b15dfcb6b8488979f9d1b9d85cad33d752f45ce246f228439ebf47e35f7e048a` +- Вердикт конвейера: `green` · High 0