mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 13:48:57 +00:00
194 lines
16 KiB
Markdown
194 lines
16 KiB
Markdown
# Ревью ТЗ — issue #20, заход r1
|
||
|
||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/20
|
||
- **ТЗ:** `docs/specs/020-glow-open-door-spill.md` (коммит `962b1d0d`, ветка
|
||
`issue/20-glow-open-door-spill`, единственный коммит поверх `origin/dev`)
|
||
- **Трек:** обычный (владелец явно снял `small` 2026-08-15 и подтвердил
|
||
«лёгкий трек: нет» повторно 2026-08-28 — меняется горячий geometry/cache
|
||
path и требуется performance proof)
|
||
- **Заход:** r1 · блокирующих циклов израсходовано 0 из 4
|
||
- **Вердикт:** зелёный · High: 0 · Medium: 0
|
||
|
||
## Скоуп ревью
|
||
|
||
Проверялось ТЗ `docs/specs/020-glow-open-door-spill.md` как артефакт этапа
|
||
`S4-spec-review`: обязательные разделы §7.1 PROCESS.md, однозначность и
|
||
доказуемость AC1…AC10, соответствие `docs/SCOPE.md`, канонической модели
|
||
`docs/LIGHT.md` и терминологии `docs/USER-GUIDE.ru.md`, а также независимая
|
||
проверка каждого фактического утверждения ТЗ о текущем коде (не пересказ
|
||
автора) — ТЗ описывает конкретные функции, кэш-ключи и геометрические типы,
|
||
и первый вопрос ревью к такому тексту: существуют ли они там, где сказано, и
|
||
делают ли то, что сказано. Продуктового кода по #20 нет (ветка содержит
|
||
только правку ТЗ), поэтому гейты §8 к этому заходу неприменимы.
|
||
|
||
История issue: тело 2026-08-09 описывало старую (уже не существующую) модель
|
||
интервалов-occluder; комментарий владельца 2026-08-11 актуализировал
|
||
механику под пост-#71 модель полигона видимости; комментарий 2026-08-15
|
||
зафиксировал P3/feature/обычный трек и закрыл продуктовые вопросы («Вопросы:
|
||
нет — поведение проёма без contact entity и fallback уже определены»);
|
||
комментарий 2026-08-28 подтвердил взятие в работу и текущую редакцию ТЗ.
|
||
Предыдущего цикла ревью ТЗ на этом issue не было — это первый заход, раздел
|
||
«Унаследовано из r0» не применяется.
|
||
|
||
## Как проверялось
|
||
|
||
1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (§2.3–2.10, §7.1,
|
||
§7.2) целиком.
|
||
2. Прочитано тело issue #20 и все четыре комментария владельца.
|
||
3. Прочитан файл ТЗ `020-glow-open-door-spill.md` целиком (224 строки).
|
||
4. Прочитан канонический `docs/LIGHT.md` целиком — источник истины для
|
||
модели света, на которую ТЗ явно ссылается.
|
||
5. Проверена терминология в `docs/USER-GUIDE.ru.md` (`Glow`, ворота как
|
||
аналог двери, «стены не пропускают Glow») — используемые в ТЗ слова не
|
||
изобретены, они те же, что видит пользователь в интерфейсе.
|
||
6. Независимо сверены с кодом все технические утверждения ТЗ, которые могли
|
||
бы оказаться недоказанной догадкой, выданной за факт:
|
||
- `_lightBarriers()` (`src/houseplan-card.ts:10261-10392`) — подтверждена
|
||
фильтрация `passages` через `isInteriorLightOpeningType` (allowlist
|
||
`door | gate | passage`), проверка пола по обе стороны (`onFloor`),
|
||
разделение контурных вырезов (`roomPassages`/`cuts`) и партиций
|
||
(`_partitionOpeningCuts` → `PartitionOpeningCut`), кэш-ключ
|
||
`contentFingerprint([raw, cellCm, gridPitch])` — сейчас **не** содержит
|
||
состояние проёмов, что и есть повод для задачи;
|
||
- `openingAmount()` (`src/logic.ts:316-324`) — подтверждён текущий
|
||
бинарный контракт (0/1, fallback `1` для двери/ворот без датчика,
|
||
`unavailable`/`unknown` не меняются `invert`) — ровно то, что таблица
|
||
ТЗ §"Контракт поведения / 1" описывает как сохраняемый инвариант для
|
||
известного/fallback случая; расширение под `current_position` cover —
|
||
заявленная новая работа, не выдаётся за существующую;
|
||
- `_openingAmt()`/`OpeningVisibleSpec.amount` (`src/houseplan-card.ts:
|
||
12303-12309`, `src/render/opening-symbol.ts:8-61`) — подтверждено, что
|
||
символ проёма уже использует единое дробное `amount` в `[0,1]`
|
||
(`Math.max(0, Math.min(1, spec.amount))`), то есть претензия ТЗ «один
|
||
коэффициент для символа и Glow» технически реализуема без переделки
|
||
символа — расширяется только источник числа;
|
||
- `PartitionOpeningCut` (`src/physical-geometry.ts:145-186`) — подтверждён
|
||
генерический сегмент `{hostId, a, b, depth}`, не привязанный к полной
|
||
длине проёма — масштабирование `a`/`b` вокруг центра для частичного
|
||
выреза, которое требует ТЗ, архитектурно естественно;
|
||
- `_roomWallOpeningInputs()` (`src/houseplan-card.ts:7494-7505`,
|
||
`geometryRoomOpeningInputs`) отдаёт `{x, y, angle, length}` на проём —
|
||
подтверждено, что вырез строится из `length` вокруг центра
|
||
(`houseplan-card.ts:10310-10314`), то есть `length * amount` с тем же
|
||
центром/осью — не выдумка, а прямое следствие существующей формулы;
|
||
- `_contactCandidates()` (`src/houseplan-editor-runtime.ts:6379-6394`) —
|
||
подтверждено, что `cover`-домен уже допустим как `opening.contact` для
|
||
дверных device_class (`door`, `garage_door`, `garage`, `opening`,
|
||
`window`) — «доступный cover» в контракте ТЗ не новая возможность
|
||
привязки, а новое использование уже существующей;
|
||
- `lruWrite(this._lightBarrierPool, cacheKey, entry, 8)` и
|
||
`lruWrite(this._glowClipCache, clipKey, geometry, 256)`
|
||
(`houseplan-card.ts:10389, 10506`) — подтверждены названные в ТЗ
|
||
границы LRU;
|
||
- `demo/smoke_glow.mjs`, `demo/fixtures/large-house.mjs`,
|
||
`demo/benchmark_glow.mjs` — подтверждено существование
|
||
large-house-фикстуры и Glow-бенчмарка, на которые опирается AC9,
|
||
ничего вымышленного.
|
||
7. Проверено соответствие `docs/SCOPE.md`: владелец уже классифицировал
|
||
задачу как «пространственная правдивость света» (комментарий 2026-08-15)
|
||
— это часть J1 («живой пространственный обзор») и общей заявки миссии
|
||
«live, tappable map»; ревью не переоткрывает уже принятое владельцем
|
||
scope-решение.
|
||
8. Проверены незакрытые продуктовые вопросы: их нет — владелец прямо
|
||
подтвердил в комментарии 2026-08-15, что поведение без contact entity и
|
||
fallback уже определено; в ТЗ нет ни одного утверждения о видимом
|
||
поведении, помеченного как решённое, но не подтверждённого ни одним
|
||
документом или существующим кодом.
|
||
9. Код не запускался, гейты §8 не прогонялись — на этапе ревью ТЗ
|
||
продуктового кода нет (см. «Скоуп ревью» выше).
|
||
|
||
## Проверка §7.1 — обязательные разделы
|
||
|
||
Все присутствуют и содержательны: сценарий (персона/поверхность/момент) ·
|
||
что человек увидит до/после (одна фраза, без терминов реализации, кроме
|
||
слова «Glow», которое само является интерфейсным термином из
|
||
USER-GUIDE.ru.md, а не внутренним) · проблема · скоуп и не-скоуп · контракт
|
||
поведения · UX · модель данных и миграция · i18n · AC1…AC10 с указанным
|
||
способом доказательства (unit/smoke/golden/CI-perf) · план автотестов ·
|
||
риски и меры · откат · release-артефакты · блок «принято предположительно».
|
||
|
||
Блок «принято предположительно» (§218-223 ТЗ) содержит только технические
|
||
решения (форма и файл чистого aperture-хелпера, сериализация signature,
|
||
механика частичного `PartitionOpeningCut`, разбиение smoke/golden файлов) —
|
||
ни одно из них не является продуктовым вопросом, спрятанным под видом
|
||
допущения.
|
||
|
||
## Проверка AC
|
||
|
||
Все десять AC пронумерованы, формулируют конкретное наблюдаемое поведение
|
||
(или измеримый контракт кэша/perf) и называют способ доказательства:
|
||
|
||
- AC1, AC2 — closed/open переход, unit геометрии + browser smoke с
|
||
переключением состояния fake `hass`;
|
||
- AC3 — частичное открытие через `cover.current_position`, unit + smoke по
|
||
пикселям;
|
||
- AC4 — матрица `invert` на известных/fallback состояниях, unit;
|
||
- AC5 — классификатор типов (door/gate/passage прозрачны, window/наружная
|
||
дверь/неизвестный тип непрозрачны), unit + smoke;
|
||
- AC6 — паритет контурной стены и независимой перегородки, geometry unit +
|
||
smoke fixture;
|
||
- AC7 — fail-dark источника внутри закрытого проёма, source-guard
|
||
unit/smoke;
|
||
- AC8 — контракт кэша (переиспользование при посторонней сигнатуре, новый
|
||
ключ при смене amount, bounded LRU), unit;
|
||
- AC9 — perf-бюджет на large-house fixture, exact-SHA CI performance smoke
|
||
перед бетой (согласовано с AGENTS.md: performance/golden — предрелизный
|
||
гейт, а не гейт этой стадии);
|
||
- AC10 — golden-сцена closed/open/50%, reviewed Linux golden-артефакт.
|
||
|
||
Все десять привязаны к реально существующим точкам расширения кода (см.
|
||
п.6 выше), ни один не описывает несуществующий API как готовый.
|
||
|
||
## Находки
|
||
|
||
Не найдено ни одной High- или Medium-находки. ТЗ не содержит утверждений о
|
||
поведении, которых нет ни в `docs/LIGHT.md`, ни в текущем коде и которые не
|
||
помечены как допущение; открытых продуктовых вопросов нет — они закрыты
|
||
владельцем заранее.
|
||
|
||
### L1 (Low, снимается без правки) — влияние на touch не названо отдельной строкой
|
||
|
||
DoR-чеклист (`PROCESS.md` §2.5) требует явно названного влияния на touch по
|
||
`docs/TOUCH-SUPPORT.md`. В самом ТЗ такой отдельной строки нет. Снимаю без
|
||
правки: раздел «УХ» ТЗ прямо утверждает «новых контролов и сообщений нет» —
|
||
изменение целиком в рендеринге Glow в View/kiosk, без нового
|
||
взаимодействия, а `docs/TOUCH-SUPPORT.md` требует паритета именно для
|
||
интерактивных путей View, которых здесь не появляется. Рендер одинаков на
|
||
любом указывающем устройстве; отдельно фиксировать «влияние: нет» было бы
|
||
формальностью, а не содержательной проверкой. Если автор всё же добавит эту
|
||
строку явно в ТЗ — это не будет считаться повторным циклом ревью.
|
||
|
||
## Что проверено и корректно
|
||
|
||
- все причинно-следственные утверждения ТЗ о текущей модели (`_lightBarriers`,
|
||
`openingAmount`, `PartitionOpeningCut`, LRU-границы, cover-контакты,
|
||
large-house-фикстура) подтверждены чтением кода, а не поверены на слово;
|
||
- контракт таблицы «Один коэффициент открытия» не противоречит текущему
|
||
поведению `openingAmount()` для известных/fallback случаев — расширяет его,
|
||
не переопределяя уже проверенный инвариант;
|
||
- не-скоуп корректно исключает наружный свет, tunnel fill, автоматическое
|
||
управление дверью и смену конфигурационной схемы — ни один пункт не
|
||
расширяет заявленный скоуп «мимоходом»;
|
||
- release-артефакты называют актуализацию `docs/LIGHT.md`, что необходимо:
|
||
канонический документ сейчас не описывает частичную апертуру и обязан
|
||
получить это описание в том же изменении;
|
||
- открытых продуктовых вопросов нет, что подтверждено собственным
|
||
комментарием владельца, а не заявлением автора ТЗ.
|
||
|
||
## Чего не проверял
|
||
|
||
- Не запускал `npm run typecheck`/`npm test`/`npm run build` — продуктового
|
||
кода в ветке нет, применять их не к чему на этой стадии.
|
||
- Не проверял производительность фактическим прогоном `benchmark_glow.mjs` —
|
||
AC9 сам относит это доказательство к предрелизному exact-SHA CI, а не к
|
||
этому циклу.
|
||
- Не проверял golden — сцена ещё не существует (AC10, план автотестов п.4),
|
||
проверять нечего до реализации.
|
||
- Не оценивал точную формулу сериализации `openingStateSignature` и место
|
||
файла aperture-хелпера — оба явно вынесены в блок «принято
|
||
предположительно, поменять свободно» и не являются предметом этого ревью.
|
||
|
||
## Вердикт
|
||
|
||
Зелёный. ТЗ готово к разработке.
|