Files
houseplan-card/docs/reviews/SPEC-REVIEW-580-r2.md
T
2026-09-15 09:05:58 +03:00

200 lines
17 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-580-r2
**Issue:** #580 «Солнечные лучи от внешних углов проходят сквозь толстые стены»
**Этап:** ТЗ на ревью (`S4-spec-review`), трек — полный продуктовый
**Заход:** r2 · блокирующих циклов израсходовано 1/4 (r1 был жёлтым и списал
1 цикл; зелёный вердикт цикл не образует — §4)
**Материал:** тело issue #580, раздел `## ТЗ`, на момент комментария автора
«Исправления по SPEC-REVIEW-580-r1 внесены в тело ТЗ» (id `5674992378`,
2026-09-15T05:00:25Z; `updated_at` issue = 05:00:27Z — тело правилось прямо
перед этим комментарием). Продуктового кода по-прежнему нет: ветка
`issue/580-outer-sun-wall-occlusion` не продвинулась дальше
`d37b2c9f8a4369082fec6970117cc97dd1e303c7` (сверено: `git log` ветки и
`git diff d37b2c9f..origin/issue/580-outer-sun-wall-occlusion --stat` —
пусто, только коммит с документом ревью попал в общую историю).
## Дельта раунда
Единственный источник изменений — комментарий автора `5674992378`, который
объявляет пять правок по находке M1 из SPEC-REVIEW-580-r1 плюс правку L1.
Сверка по телу issue (текущий полный текст получен `gh issue view --json
body`) подтверждает все пять и шестую:
1. добавлен раздел `### Пользовательский сценарий`;
2. добавлен раздел `### Что человек увидит до и после` (буллеты «До»/«После»
без терминов реализации типа `sun_ray_origin`);
3. добавлен раздел `### Влияние и риски` с явными строками `Touch:`,
`Производительность:`, `i18n: нет`, `Основные риски:`;
4. риски из комментария «Аналитика» перенесены в тело ТЗ (та же
формулировка, детализированная под конкретные AC);
5. п.4 контракта переписан без хеджирующего «может» (было: «свет внутри
доступной части туннеля может оставаться видимым»; стало: «В туннеле
остаётся только участок света от внешней плоскости до места, где его
полностью перекрывает откос»);
6. AC2 расширен явным условием: «...туннельная часть заканчивается на
блокирующем откосе и остаётся непустой, если луч успевает войти во
внешний пролёт» — снимает саму неопределённость, а не просто убирает
слово.
Остальной текст ТЗ (диагноз «Проблема», контракт п.1–3/5–6, «Технический
подход», AC1/AC3–AC7, «Затронутые файлы», «Совместимость и откат»,
«Принятые предположения») по утверждению автора не менялся; ниже это
принято как унаследованное из r1, см. раздел «Унаследовано из r1».
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** (Medium, в скоупе): нет разделов «Сценарий»/«До-после», нет `i18n`, нет влияния на touch и производительность, риски не перенесены в тело ТЗ — DoR §2.5 формально не проходится | Все пять пунктов добавлены отдельными разделами/строками в тело `## ТЗ` | `### Пользовательский сценарий`; `### Что человек увидит до и после`; `### Влияние и риски` → `Touch:`, `Производительность:`, `i18n: нет`, `Основные риски:` (текст issue, текущая версия) |
| **L1** (Low, на усмотрение автора): контракт п.4 использует «может» про свет в туннеле на предельно косом угле, AC это не проверяет | Хедж убран, контракт п.4 переформулирован как безусловное правило с явной оговоркой про вход луча во внешний пролёт; AC2 добавил проверку этого же условия | Контракт, п.4 (текст «В туннеле остаётся только участок…») + `AC2`, фраза «...остаётся непустой, если луч успевает войти во внешний пролёт» |
Обе находки закрыты по существу, не косметически: M1 была про отсутствие
текста DoR-пунктов — текст добавлен и отвечает по существу (а не заглушками
вроде «TBD»); L1 была про модальность контракта — модальность убрана, а не
просто переформулирована в другую хедж-форму.
## Унаследовано из r1
Без повторной проверки в этом раунде принято всё, чего дельта не касалась —
см. SPEC-REVIEW-580-r1.md (документ этого репозитория, коммит `a18e41e2`),
раздел «Что проверено и корректно», на состоянии тела issue до правки
(комментарий `IC_kwDOTOcLQM8AAAABUkBntg` / `5674919862`, 2026-09-15T04:52:39Z)
и коде на `d37b2c9f8a4369082fec6970117cc97dd1e303c7`:
- диагноз бага соответствует коду `computeSunRays()` (`src/sun.ts:402-459`) —
комнатная и туннельная часть луча в режиме `outer` строятся двумя
независимыми клипами одного `quad`, без пересечения друг с другом;
- технический подход реализуем на существующих входных данных
(`wallDepthByOpening`, координаты/угол/длина окна, контур комнаты) без
новой геометрии стен;
- регрессионный периметр (контракт п.3, п.5) верно называет существующие
тесты `#577` (`test/sun.test.mjs:468,495`) и `DEV-EB173-01`
(`test/sun.test.mjs:509`), которые нельзя сломать;
- `docs/USER-GUIDE.ru.md` не нуждается в правке — таблица «Поведение» уже
описывает целевое, исправленное поведение режима «внешние углы»;
- AC1, AC3–AC7 однозначны, каждому назван способ доказательства
(unit ×2, browser smoke, golden, гейты, review) — эти AC дельта не
трогала, повторно не разбирались;
- «Принятые предположения» оформлены по правилу §7.1 явным блоком, оба
технические, эскалация владельцу не нужна — текст не менялся;
- не-скоуп (взаимное затенение стен/крыльев) назван явно и совпадает с
зафиксированным лимитом `docs/SUN.md`;
- track-решение «полный продуктовый трек» обосновано названным критерием
(сложность/риск выше 3) — раздел не менялся.
## Как проверялось (по дельте)
1. Получено текущее тело issue (`gh issue view 580 --json body`) и все
комментарии с их id и временем (`gh api .../issues/580/comments`), чтобы
отделить дельту от унаследованного текста без доступа к истории правок
issue (GitHub API не отдаёт диффы тела issue напрямую — сверка велась по
явным цитатам находок в SPEC-REVIEW-580-r1.md и по перечню правок в
комментарии автора).
2. Построчно сверены пять правок из комментария автора с текущим текстом
ТЗ — все пять присутствуют по существу, не формальными заглушками
(раздел «Дельта раунда» выше).
3. Перечитан `docs/SUN.md`, раздел «The rim — a hairline along the sides»
(строки 315-354), чтобы оценить риск «неверная боковая обводка после
сужения», который автор добавил в «Основные риски». Архитектурно rim
выводится «for free» из уже клипованного полигона луча
(`rayRimEdges()` режет стороны из ALREADY clipped polygons, `rimStops()`
возвращает `rayStops()` по идентичности) — то есть после исправления
геометрии комнатной части rim скорректируется автоматически, без
отдельной правки кода и без отдельного AC. Это подтверждает корректность
контракта п.5 («боковой rim... сохраняют существующий контракт») и
снимает первоначальное опасение, что риск rim остался без покрытия
тестами — он структурно исключён самой архитектурой, а не нуждается в
отдельном AC.
4. Перепроверена логическая непротиворечивость нового текста контракта
п.4 и обновлённого AC2 — противоречий нет, AC2 добавляет ровно ту
оговорку (полный блок луча у самого входа в пролёт), которую общее
правило контракта не проговаривает явно.
5. Сверено, что новый раздел «Влияние и риски» не расширяет и не сужает
скоуп: `Touch: не меняется`, `i18n: нет`, `Производительность:` явно
ограничивает правку одним пересечением полигонов в уже пересчитываемом
пути и запрещает новые циклы по пикселям/кадрам — совпадает с тем, что
уже было верно по коду в r1 (r1 констатировал горячий путь, но не
ограничение сложности; теперь ограничение сформулировано явно самим
автором, а не мной за него).
6. Проверено, что AC1, AC3, AC4–AC7 и остальной контракт (п.1-3,5,6)
текстуально не менялись относительно того, что уже было разобрано и
принято в r1 — заново геометрию не проверял (см. «Унаследовано из r1»).
Гейты (`tsc`/`test`/`build`/`check-docs`/инварианты/смоки/golden) не
прогонялись: продуктового кода в этом раунде по-прежнему нет (см.
«Материал» выше) — их не над чем гонять, аналогично r1.
## Находки
Не найдено. Обе находки r1 (M1, L1) закрыты по существу; дельта нового
Medium/High не вносит. Замечание про rim (см. «Как проверялось», п.3)
не стало находкой: после чтения `docs/SUN.md` выяснилось, что риск
структурно закрыт архитектурой rim (`rayRimEdges()`), а не пробел в ТЗ.
## Что проверено и корректно
- M1 закрыта по существу: все пять пунктов DoR §2.5 (сценарий, до/после,
i18n, touch, производительность) и перенос рисков в тело ТЗ присутствуют
как содержательный текст, а не формальные заглушки.
- L1 закрыта по существу: контракт п.4 больше не хеджирует поведение
словом «может», а AC2 явно проверяет обе ветки предельно косого случая
(пустая комнатная часть + непустая/пустая туннельная в зависимости от
входа луча).
- Новый раздел «Влияние и риски» согласован с остальным ТЗ: перечисленные
риски покрываются названными AC (AC1-AC3 — численные вырождения и
сохранение полного пролёта/неизменности `inner`, AC5 — шов на внутренней
плоскости через golden-снимок; риск по боковому rim закрыт архитектурно,
см. выше, а не отдельным AC — это корректно, а не пропуск).
- Дельта не меняет контракт по существу (диагноз, подход, AC1/AC3-AC7),
поэтому наследование выводов r1 обосновано согласованностью текста, а не
просто заявлением автора.
- Track-решение, не-скоуп и ссылка на `docs/USER-GUIDE.ru.md` не требуют
повторной проверки — дельта их не касается.
## Чего не проверял
- Не проверял `npx tsc --noEmit` / `npm test` / `npm run build` /
`check-docs` — продуктового кода всё ещё нет, гонять нечего (то же, что в
r1).
- Не прогонял браузерные смоки, golden и инварианты модели — актуальны на
код-ревью, когда появится реализация AC1-AC5.
- Не проверял `python -m pytest tests_backend` — задача не касается
`custom_components/**/*.py`.
- Не выполнял заново геометрический разбор `computeSunRays()` — контракт и
диагноз, к которым он относится, дельта не трогала; разбор унаследован из
r1 (см. выше).
## Вердикт
Зелёный: находки r1 (M1, L1) закрыты по существу, новых High/Medium дельта
не вносит. ТЗ отвечает на все обязательные пункты §7.1/DoR §2.5, контракт
однозначен, AC1-AC7 у каждого указан способ доказательства. Готово к
переходу в `S5-ready`.
## Материал раунда
- Issue: #580, репозиторий Matysh/houseplan-card.
- Материал ТЗ: тело issue, раздел `## ТЗ`, на момент комментария автора
`5674992378` (2026-09-15T05:00:25Z, «Исправления по SPEC-REVIEW-580-r1
внесены в тело ТЗ»); `updated_at` issue = 2026-09-15T05:00:27Z.
- Ветка `issue/580-outer-sun-wall-occlusion`, без продуктовых изменений
относительно `d37b2c9f8a4369082fec6970117cc97dd1e303c7` (сверено `git
diff --stat` на момент ревью).
- Заход r2, предыдущий документ — `docs/reviews/SPEC-REVIEW-580-r1.md`
(коммит `a18e41e2`). Раздел «Закрытие раунда r1» и «Унаследовано из r1»
выше.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/580-outer-sun-wall-occlusion`, коммит `a18e41e20168` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `3bb62e0b2a0f871bcf276f0f130957e7ba048130`
```
git log --all --format='%H %T' | grep 3bb62e0b2a0f
```
- Тело issue: `558be5cfc33a8fe1f475fbc5a0210392339265c20fad0c22e82858b57c96b848`
- Вердикт конвейера: `green` · High 0