mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 11:49:16 +00:00
docs: review document for #531
Проверка (CI) / Классификация изменённых файлов (push) Successful in 26s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Failing after 52s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 24s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 25s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 43s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 4m59s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 7m4s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Классификация изменённых файлов (push) Successful in 26s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Failing after 52s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 24s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 25s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 43s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 4m59s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 7m4s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Issue: #531 User-Visible: no
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# SPEC-REVIEW-531-r2
|
||||
|
||||
**Issue:** #531 — «Панорама плана в Firefox: `viewBox` переписывается на каждый
|
||||
кадр жеста, композитор ждёт 13 vsync-тиков»
|
||||
**Этап:** spec (ревью ТЗ, PROCESS.md §2.4)
|
||||
**Трек:** полный (не изменился со времени r1 — критерий §5, который задача не
|
||||
проходит, назван и подтверждён в r1: «нет влияния на производительность»)
|
||||
**Заход:** r2 · блокирующих циклов израсходовано 1 из 4
|
||||
**Материал:** тело issue #531 на текущем HEAD, `dev` `b4a16ad7`. Продуктовый
|
||||
код не тронут: `git diff af2081cb..b4a16ad7 -- src/live-viewport.ts
|
||||
src/live-interaction-runtime.ts src/houseplan-card.ts docs/ARCHITECTURE.md
|
||||
scripts/mutation-gate.mjs test/live-viewport.test.mjs
|
||||
demo/benchmark_large_house.mjs` пуст. Единственный коммит между материалом r1
|
||||
и этим раундом — `b4a16ad7 docs: review document for #531` (класс C, публикация
|
||||
самого документа r1), никакого влияния на технические утверждения r1.
|
||||
|
||||
## Разбор по дельте (PROCESS.md §2.10)
|
||||
|
||||
Предыдущий раунд закончился жёлтым вердиктом с единственной находкой Medium
|
||||
(в скоупе), остальное ТЗ принято. Автор ответил комментарием
|
||||
(`2026-09-11T09:58:44Z`), назвав ровно три правки текста ТЗ: переписан К2,
|
||||
добавлен AC2а, переформулирован риск 1. Код между раундами не менялся (см.
|
||||
выше) — делать полный повторный разбор нет предмета: дельта строго локальна
|
||||
(один контрактный пункт, один новый AC, одна строка риска), не является
|
||||
ребейзом, не меняет контракт поведения за пределами уже поднятого вопроса и не
|
||||
затрагивает новую подсистему. Разбор в этом раунде ограничен дельтой и всем, до
|
||||
чего она дотягивается: К2, АС2/АС2а как пара, риск 1 и их согласованность с
|
||||
остальным контрактом (К1, К5) и остальными AC (AC1, AC3-AC9), которые дельта не
|
||||
меняет текстуально, но с которыми новый текст обязан не конфликтовать.
|
||||
|
||||
## Закрытие раунда r1
|
||||
|
||||
| Находка r1 | Чем закрыта | Где это видно |
|
||||
|---|---|---|
|
||||
| Medium — второй триггер К2 (сдвиг) не имел ни ориентировочной константы, ни собственного AC; ни один из AC1-AC9 не мог покраснеть, если реализация вообще не построит сдвиговую ветку | К2 переписан как два явных условия с названными константами-ориентирами (`LIVE_VIEWBOX_REFRESH_MS` ≈100 мс, `LIVE_VIEWBOX_REFRESH_SHIFT` ≈0.15) и объяснением, зачем нужен второй; добавлен отдельный **AC2а** (`unit`), который с подменёнными часами проверяет сдвиговый путь независимо от временного: кадр со смещением выше порога обязан переписать `viewBox` немедленно, хотя `LIVE_VIEWBOX_REFRESH_MS` ещё не истёк, а кадр ниже порога — не должен переписывать | Тело issue #531, раздел `### Контракт`, пункт К2 (два подпункта «по времени» / «по сдвигу», абзац «Оба порога — константы модуля»); раздел `### AC`, новый пункт **AC2а** |
|
||||
| Low — обязательные разделы §7.1 присутствуют по содержанию, но не оформлены отдельными заголовками | Снято ревьюером r1 без правки, автор текст не трогал (подтверждено комментарием «Low ... снят ревьюером без правки — текст не трогал») | Не требует проверки — решение уже зафиксировано в SPEC-REVIEW-531-r1.md |
|
||||
|
||||
Проверка не ограничилась чтением заявления автора: ниже — построчная сверка,
|
||||
что новый текст АС2а действительно ловит отсутствие сдвиговой ветки, а не
|
||||
просто существует.
|
||||
|
||||
**АС2а умеет покраснеть.** Если реализация не построит путь «накопленный сдвиг
|
||||
→ досрочная перезапись» и оставит только временной бюджет — кадр со смещением
|
||||
выше `LIVE_VIEWBOX_REFRESH_SHIFT`, но с ещё не истёкшим
|
||||
`LIVE_VIEWBOX_REFRESH_MS`, при отсутствующей сдвиговой ветке не перепишет
|
||||
`viewBox`; AC2а прямо требует, чтобы он его переписал — assertion провалится.
|
||||
Симметрично: если реализация триггерит по сдвигу слишком рано (например,
|
||||
использует долю от неверной оси или не выполняет сброс накопленного смещения
|
||||
после перезаписи), негативная часть AC2а («кадр со смещением ниже порога — не
|
||||
переписывает») ловит и это. Это ровно тот сценарий, который в r1 не мог
|
||||
провалиться ни на одном из AC1-AC9 — пробел закрыт предметно, а не
|
||||
декларативно.
|
||||
|
||||
**Согласованность с остальным контрактом не нарушена.** К1 («каждый кадр — это
|
||||
только трансформ») и новое К2 не конфликтуют: кадр, на котором истёк один из
|
||||
двух бюджетов (временной или сдвиговый), — явно описанное исключение, а не
|
||||
нарушение К1, и после него «трансформ этих узлов возвращается в единицу в том
|
||||
же кадре» для обоих путей одинаково. АС2 (временной путь) и АС2а (сдвиговый
|
||||
путь) размечены как независимые сценарии и не пересекаются: АС2 говорит «по
|
||||
истечении бюджета», АС2а — «пока временной бюджет ещё не истёк». Риск 1
|
||||
(«пустая полоса на набегающем крае») теперь корректно ссылается на «оба
|
||||
порога К2» вместо одного, и вывод риска («пороги — константы модуля, их
|
||||
достаточно уменьшить») остаётся верным для обоих. AC5 (смок, суммарный счётчик
|
||||
перезаписей за 20 кадров) не переписан и не должен был: у него по-прежнему
|
||||
нет обязанности различать триггер — это ровно то, для чего существует АС2а.
|
||||
AC8 (таблица мутантов на К1/К4) не получил новой строки под сдвиговый триггер;
|
||||
это не пробел этого раунда — §2.7 (таблица «AC · чем доказан · чем краснеет»)
|
||||
требование к код-ревью для защитных AC, а не к тексту спецификации, и АС2а сам
|
||||
по себе уже задаёт проверяемый негативный сценарий текстом.
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Без повторной проверки в этом раунде приняты все выводы
|
||||
`docs/reviews/SPEC-REVIEW-531-r1.md` (материал: тело issue #531 на dev
|
||||
`af2081cb`), поскольку продуктовый код и остальной текст ТЗ, от которых эти
|
||||
выводы зависят, между раундами не менялись (подтверждено пустым `git diff`
|
||||
выше):
|
||||
|
||||
- продуктовая рамка и выбор полного трека (docs/SCOPE.md, J1; критерий §5);
|
||||
- построчная сверка технических утверждений с `src/live-viewport.ts`,
|
||||
`src/live-interaction-runtime.ts`, `src/houseplan-card.ts` (`paintLiveViewport`
|
||||
пишет `viewBox` безусловно; `isIdentityLiveLayerProjection` уже существует у
|
||||
трансформа и отсутствует у `viewBox`; `_floorView(view) === view` в
|
||||
неизометрическом режиме — факт, не приближение; теги
|
||||
`data-hp-live-viewbox`/`data-hp-live-layer` существуют и используются как
|
||||
описано, включая изометрическую ветку);
|
||||
- проверяемость AC1, AC3, AC4, AC6, AC9 и их привязка к существующей
|
||||
инфраструктуре (`test/live-viewport.test.mjs`, `scripts/mutation-gate.mjs`,
|
||||
`docs/ARCHITECTURE.md:1908`);
|
||||
- честность разделения «AC внутри репозитория доказывают механизм» / «приговор
|
||||
по скорости — профиль владельца» (AC7 golden, раздел «Приёмка по скорости»);
|
||||
- риски 2-4, откат, touch-вывод («единственная точка входа `_liveVp()`,
|
||||
Pointer Events унифицируют мышь и тач — отдельного контракта не требуется»);
|
||||
- статус трёх «Принятых технических предположений» как действительно
|
||||
технических, не подменяющих продуктовое решение;
|
||||
- Low-находка о неформальной структуре разделов §7.1 — снята r1, автор
|
||||
текст, к которому она относится, не менял.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет. Единственная находка r1 (Medium) закрыта по существу — новый текст не
|
||||
просто добавляет константу, а даёт конкретный, способный провалиться сценарий
|
||||
для триггера, который раньше мог остаться нереализованным незамеченно. Новых
|
||||
находок дельта не вносит: правка локальна, не противоречит соседним пунктам
|
||||
контракта и не расширяет скоуп.
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Гейты `npx tsc --noEmit`/`npm test`/`npm run build`/`node
|
||||
scripts/check-docs.mjs` не запускались — в материале этого раунда нет
|
||||
изменений класса A/B/D (диапазон `origin/dev..HEAD` пуст, `src/**` не
|
||||
менялся), прогонять их значило бы проверять пустое множество; та же логика,
|
||||
что в r1.
|
||||
- Реализуемость числовых ориентиров `LIVE_VIEWBOX_REFRESH_MS≈100 мс` и
|
||||
`LIVE_VIEWBOX_REFRESH_SHIFT≈0.15` на живом железе владельца — по тексту ТЗ
|
||||
(«Приёмка по скорости — отдельно и не здесь») это предмет профиля на этапе
|
||||
код-ревью/пре-релиза, не текста спецификации; унаследовано из r1 без
|
||||
повторной оценки.
|
||||
- Изометрический путь и поведение при одновременном зуме и панораме —
|
||||
унаследовано из r1 («детальная проверка изо-пути остаётся код-ревью по факту
|
||||
диффа»), дельта этого раунда К6 и зум не касается.
|
||||
|
||||
## Вердикт
|
||||
|
||||
**Зелёный · заход r2/4 · High: 0 · Medium: 0.**
|
||||
|
||||
Единственная находка r1 закрыта предметно: К2 теперь называет константу для
|
||||
обоих триггеров перезаписи `viewBox`, и новый AC2а даёт сценарий, который
|
||||
красится именно на отсутствии сдвиговой ветки (проверено построчно выше, а не
|
||||
принято на слово автора). Согласованность нового текста с остальным
|
||||
контрактом (К1, К5, AC2, AC5, риск 1) проверена и дефектов не выявила. Код
|
||||
между раундами не менялся, поэтому весь остальной корпус выводов r1
|
||||
наследуется без повторной проверки (раздел «Унаследовано из r1»).
|
||||
|
||||
Следующий статус — «Готово к разработке» (`S5-ready`).
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `dev`, коммит `b4a16ad7043d` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `9ac2a0132e8bb5d8db8eaab5fa14e1a714063caf`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 9ac2a0132e8b
|
||||
```
|
||||
- Тело issue: `89e75138a50434ac52f42cef606d8af741a8ae3b022dba382c4b62c1f4887e8a`
|
||||
- Вердикт конвейера: `green` · High 0
|
||||
Reference in New Issue
Block a user