Files
houseplan-card/docs/reviews/SPEC-REVIEW-585-r1.md
T
claude[bot] d86b613cef
Проверка (CI) / Классификация изменённых файлов (push) Successful in 29s
Проверка (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 46s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 21s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 22s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Failing after 44s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 8m53s
Проверка (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) Failing after 19s
docs: review document for #585
Issue: #585
User-Visible: no
2026-09-19 19:11:13 +00:00

198 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-585-r1
**Issue:** [#585](https://github.com/Matysh/houseplan-card/issues/585) — узкая разрешимая щель между узлами решётки 4 px теряется при разрешении коллизий поднятых 2.5D-маркеров.
**Этап:** ТЗ на ревью (`S4-spec-review`), заход r1, полный трек (не `small`: сложность/риск 8/10, влияние на производительность).
**Ревьюер:** независимая сессия, без контекста реализации (в реализации кода ещё не участвовал никто — `S6-in-progress` не проходился).
**Вердикт: зелёный.**
---
## 1. Скоуп ревью
Тело issue #585 целиком: репорт дефекта («Что не так» / «Чем доказано» / «Почему не
починено в бете» / «Как чинить по-настоящему» / «Приёмка»), раздел `## ТЗ` (16
пронумерованных подразделов по PROCESS.md §7.1) и единственный комментарий —
`S2-analysis` от 2026-09-19, фиксирующий полный трек с названным нарушенным
критерием §5.
Задача — исправление ранее одобренного исключения из `docs/SCOPE.md` (2.5D,
issue #89): скрытый experimental-вид за `hp_alpha`, сохранённая модель/камера/
пользовательский контракт не трогаются, меняется только взаимное размещение
поднятых маркеров устройств и замков проёмов внутри уже принятого бюджета 48 CSS
px / 4 CSS px.
## 2. Как проверялось
Прочитано в порядке, предписанном заданием:
1. `docs/SCOPE.md` — мандат 2.5D как узкое одобренное исключение (#89), инвариант
блокировки замков (не задет — задача не касается действий).
2. `AGENTS.md`, `PROCESS.md` (главы 1–14 целиком) — классы файлов, лёгкий трек и
критерий его отказа, §7.1 обязательные разделы ТЗ, §2.4/§2.10 формат ревью и
правило деления по дельте (не применялось: это r1, других документов по #585
в `docs/reviews/` и в истории git нет — проверено `find` и
`git log --all --oneline | grep 585`, единственный релевантный коммит
`9683a590` — временное расширение допусков перед бетой, не фикс).
3. Тело issue #585 и его единственный комментарий (аналитика).
4. `docs/USER-GUIDE.ru.md` — не требуется: фича скрыта за `hp_alpha`, не входит
в пользовательский интерфейс, ТЗ явно фиксирует `User-Visible: no`.
5. `docs/ISOMETRIC.md` целиком (Stage 1/2/4) — проверка того, что числа и
формулировки ТЗ (48 CSS px, 4 CSS px, камера `rotDeg=0 tiltDeg=20`,
исключение room labels из взаимной коллизии, отсутствие тетера/подложки)
совпадают с зафиксированным контрактом, а не изобретены заново.
6. `src/iso-overlays.ts` целиком — сверка утверждений ТЗ с действующей
реализацией `resolveIsoOverlayPlacement`/`resolveIsoOverlayCollisions`:
стабильный порядок (`nudgeDistanceCss` → `kind\0id`), текущий грубый шаг
4 px (`ISO_OVERLAY_GROUP_COARSE_STEP_CSS_PX`, коммит `699ab471`/#583),
существующий broad phase по ячейкам (`nearby`, `wallsNear`), деградированный
fallback с минимальным штрафом (`penalty`), исключение room labels
(`IsoOverlayCollisionKind = Exclude<IsoRaisedOverlayKind, 'room-label'>`).
7. `demo/performance/budgets-large-house-isometric.json`,
`demo/performance/budgets-isometric-stage3-dense.json` — текущие значения
`noiseAllowanceMs` (450/150/120) сверены с числами ТЗ §10 (что именно
временное и что возвращается к 150/60/75).
8. `test/performance-budget.test.mjs` (строки 260–290) — тест
`'изометрический допуск жеста покрывает ровно принятый шаг #583, не больше
(#585)'` уже сегодня фиксирует эти же временные числа и явно называет #585
как задачу, которая их отменит. ТЗ описывает уже существующий, а не
придуманный контракт.
9. `demo/fixtures/large-house.mjs:33` — `name: \`Room ${floor + 1}.${index +
1}\`` подтверждает, что «Room 2.5» из АС2 — реальное имя комнаты фикстуры
`large` (этаж 2, комната 5), а не опечатка/догадка.
10. `demo/golden/matrix.mjs:284` и `demo/golden/baselines/` — сцена
`isometric-large-warm-remount-dark` (fixture `large`, space `perf-floor-2`,
mode `view`) существует и baseline-файл на месте.
11. `demo/performance/*.json` / `scripts` — имена профилей
`large-house-isometric-v1` и `isometric-stage3-dense-v1` совпадают с полем
`profile` обоих budget-файлов, значит АС6 ссылается на реальные профили.
Гейты не запускались: этап ТЗ не подразумевает исполнение кода (§2.4), материал
для проверки — текст, а не диапазон коммитов. Кода по #585 в ветке ещё нет
(`git log --all` не находит коммитов реализации #585 после `9683a590`).
## 3. Находки
Нет ни одной High- или Medium-находки.
**Low (снята с записью, не блокирует).** Раздел «1. Сценарий» не называет
персону `docs/SCOPE.md` по имени (например, «home admin»), хотя PROCESS.md §7.1
явно требует называть персону. Ситуация описана однозначно — включение
скрытого `hp_alpha` через URL/hash-параметр физически доступно только тому, кто
осознанно лезет в query/hash грамматику продукта, то есть тому же «home admin»,
единственной персоне со сценариями настройки/тестирования по SCOPE.md; у
«household members» и «guests/kiosk» нет пути включить эксперимент. Отсутствие
буквального слова не создаёт риска неверного толкования и не влияет ни на один
AC — снимаю без правки текста.
## 4. Обязательные разделы §7.1 — проверка полноты
Все обязательные разделы присутствуют и пронумерованы в теле issue:
сценарий (1) · что человек увидит до/после (2) · проблема (3) · скоуп (4) и
не-скоуп (5) · контракт поведения (6) · UX (7) · модель данных и миграция (8) ·
i18n (9) · производительность (10, сверх минимума §7.1, обоснованно для этой
задачи) · критерии приёмки AC1…AC8 с доказательством (11) · план автотестов
(12) · затронутые файлы (13) · риски и откат (14) · release-артефакты (15) ·
принятые предположения (16). Ничего из требуемого не пропущено.
Раздел 2 («До/после») — одна фраза без терминов реализации, как требуется:
«в Room 2.5 два маркера визуально совмещаются» → «оба маркера видны раздельно».
## 5. Однозначность AC и способ доказательства
| AC | Формулировка проверяема? | Доказательство названо? |
|---|---|---|
| AC1 | Да — числовые пороги (≤48 px сдвиг, ≥4 px зазор, внутри комнаты, без пересечения стены) | unit, узкий геометрический свидетель |
| AC2 | Да — конкретная сцена и комната названы и существуют в фикстуре/матрице голденов (проверено, п.2.9–2.10 выше) | golden + unit (двойной оракул, без golden как единственного судьи — прямое требование #435-класса) |
| AC3 | Да — перечислены все существующие контракты (порядок/перестановка, радиус, room/hole/wall safety, исключение room labels, fit-mode skip, degraded fallback) | unit |
| AC4 | Ограниченность поиска сформулирована качественно («существенно меньше полного диска», «нет площадного перебора 1 px»), но абсолютный запрет — полного скана диска — задан точно и проверяем по коду | unit + ревью кода (названо явно, не спрятано за «прочитано глазами») |
| AC5 | Да — «меняется только объявленная сцена» с явным условием на исключения | golden |
| AC6 | Да — точные числа допусков (150/60/75), неизменность hardMax/ratio, точный SHA CI | Linux CI (perf-профили названы по имени) |
| AC7 | Да — команды названы буквально | `npm run typecheck`, `npm run test:unit`, `npm run build` |
| AC8 | Да — три конкретных документа | ревью кода |
Единственная качественная формулировка (AC4, «существенно меньше») не создаёт
находки: жёсткая, машинно проверяемая часть контракта («не содержит площадного
перебора 1 px по диску», п.6.5–6.8 контракта поведения) уже количественная и её
достаточно для отказа реализации, вернувшейся к старому алгоритму под новым
именем. Точный коэффициент сокращения — деталь, которую пользователь не
наблюдает, и её по PROCESS.md §7.1 решают агенты, а не владелец.
## 6. Проверка «догадка выдана за факт»
Каждое утверждение о существующем поведении в ТЗ (числа 48/4 CSS px, порядок
сортировки, отсутствие тетера/подложки, исключение room labels, деградированный
fallback, текущие временные допуски 450/150/120, профили performance, имя
проблемной сцены и комнаты) сверено с действующим кодом, тестами, budget-json
или `docs/ISOMETRIC.md` (см. §2 выше) — совпадает буквально, ничего не
изобретено задним числом.
Единственное явно новое техническое решение — сам способ поиска (граничный
перебор вместо площадного/решётчатого скана, п.6.5–6.8 контракта) — помечено в
разделе 16 «Принятые предположения» как техническое решение автора, подлежащее
пересмотру ревьюером кода, а не как факт о существующей системе. Это ровно тот
случай, когда решать не пользователю: способ поиска пользователем не
наблюдается, наблюдается только результат (АС1–АС5).
Открытых продуктовых вопросов автор не поднимал и не должен: сценарий,
объём видимых изменений (только внутри уже скрытого эксперимента, обычный вид
не трогается) и деградация (существующий контракт degraded, не новый) уже
зафиксированы предыдущими задачами (#570, #583) и не требуют решения владельца
заново.
## 7. Соответствие DoR (§2.5) на выходе из ревью
- ТЗ существует в теле issue, ссылка issue↔ТЗ на месте (это и есть issue) — ✅;
- AC1…AC8 пронумерованы, у каждого назван способ доказательства — ✅ (см. §5);
- затронутые файлы и модули перечислены (§13 ТЗ) — ✅;
- i18n: явно «нет новых строк/ключей» — ✅;
- миграция/compatibility: явно «не меняются», согласуется с
`docs/CONFIG-COMPATIBILITY.md` (алгоритм работает только с производной
экранной геометрией кадра, схему не трогает) — ✅;
- производительность: названа количественно, включая обратный откат временных
допусков и неизменность hard-потолков — ✅;
- touch: явно сохранён существующий контракт («Фокус, hover, click/tap и
HA-действия остаются привязаны к визуально смещённому маркеру по
существующему контракту», §7 ТЗ) — влияния нет, названо — ✅;
- release-артефакты: явно `User-Visible: no`, никакого changelog — ✅;
- откат: атомарный откат алгоритма + baseline + budget allowances — ✅;
- открытых продуктовых вопросов нет (см. §6 выше) — ✅.
Все пункты DoR выполнены — задача готова к переходу в `S5-ready`.
## 8. Что не проверялось (и почему это не требуется на этом этапе)
- Работоспособность самого граничного алгоритма (это предмет кода, а не ТЗ);
на этапе спецификации проверяется формулируемость и проверяемость контракта,
а не его реализация.
- Реальный прогон `npm run typecheck` / `npm test` / `npm run build` — код по
#585 в ветке не появился, гонять гейты не на чём.
- Правильность цифр в таблицах «Чем доказано» / «Почему не починено в бете» —
это диагностика самого автора, не входящая в проверяемый контракт ТЗ (АС не
утверждают ни одно из измеренных там чисел); её будет проверять код-ревью на
реальном прогоне Linux CI по АС6.
- Полный список из 12 изометрических голденов и byte-diff у остальных 11 — вне
ТЗ-ревью, входит в АС5 и проверяется код-ревью по итогам съёмки.
---
**Материал раунда:** тело issue #585 на момент разбора (id issue: 585,
единственный комментарий `S2-analysis` от 2026-09-19T19:03:26Z). Других
документов ревью или коммитов реализации по #585 в репозитории нет —
`git log --all --oneline | grep 585` находит только `9683a590` (предшествующее
временное расширение допусков, не относится к этой ТЗ-редакции). Раздел
«Унаследовано из r0» не пишется: это первый заход.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `c38382b7318a` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `a34fbb3a3bd1828db2c7fb65a42e43f9ae921195`
```
git log --all --format='%H %T' | grep a34fbb3a3bd1
```
- Тело issue: `7e85ec65b07414bb734b5f19ffb10510ee60b3af4fdb52ed429df29d2593ebc8`
- Вердикт конвейера: `green` · High 0