docs: review document for #532

Issue: #532
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-11 15:31:27 +00:00
parent 116cfd5fef
commit 8afba7e6ed
+166
View File
@@ -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`) явно признана риском с планом на случай провала, а не выдана
за решённую. Готово к разработке.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `116cfd5fefc4` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `45453f44ff5e3243d824ab00132e42c14c9f7c33`
```
git log --all --format='%H %T' | grep 45453f44ff5e
```
- Тело issue: `b15dfcb6b8488979f9d1b9d85cad33d752f45ce246f228439ebf47e35f7e048a`
- Вердикт конвейера: `green` · High 0