16 KiB
Ревью ТЗ — 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) - Трек: обычный (владелец явно снял
small2026-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» не применяется.
Как проверялось
- Прочитаны
docs/SCOPE.md,AGENTS.md,PROCESS.md(§2.3–2.10, §7.1, §7.2) целиком. - Прочитано тело issue #20 и все четыре комментария владельца.
- Прочитан файл ТЗ
020-glow-open-door-spill.mdцеликом (224 строки). - Прочитан канонический
docs/LIGHT.mdцеликом — источник истины для модели света, на которую ТЗ явно ссылается. - Проверена терминология в
docs/USER-GUIDE.ru.md(Glow, ворота как аналог двери, «стены не пропускают Glow») — используемые в ТЗ слова не изобретены, они те же, что видит пользователь в интерфейсе. - Независимо сверены с кодом все технические утверждения ТЗ, которые могли
бы оказаться недоказанной догадкой, выданной за факт:
_lightBarriers()(src/houseplan-card.ts:10261-10392) — подтверждена фильтрацияpassagesчерезisInteriorLightOpeningType(allowlistdoor | gate | passage), проверка пола по обе стороны (onFloor), разделение контурных вырезов (roomPassages/cuts) и партиций (_partitionOpeningCuts→PartitionOpeningCut), кэш-ключcontentFingerprint([raw, cellCm, gridPitch])— сейчас не содержит состояние проёмов, что и есть повод для задачи;openingAmount()(src/logic.ts:316-324) — подтверждён текущий бинарный контракт (0/1, fallback1для двери/ворот без датчика,unavailable/unknownне меняютсяinvert) — ровно то, что таблица ТЗ §"Контракт поведения / 1" описывает как сохраняемый инвариант для известного/fallback случая; расширение подcurrent_positioncover — заявленная новая работа, не выдаётся за существующую;_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, ничего вымышленного.
- Проверено соответствие
docs/SCOPE.md: владелец уже классифицировал задачу как «пространственная правдивость света» (комментарий 2026-08-15) — это часть J1 («живой пространственный обзор») и общей заявки миссии «live, tappable map»; ревью не переоткрывает уже принятое владельцем scope-решение. - Проверены незакрытые продуктовые вопросы: их нет — владелец прямо подтвердил в комментарии 2026-08-15, что поведение без contact entity и fallback уже определено; в ТЗ нет ни одного утверждения о видимом поведении, помеченного как решённое, но не подтверждённого ни одним документом или существующим кодом.
- Код не запускался, гейты §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-хелпера — оба явно вынесены в блок «принято предположительно, поменять свободно» и не являются предметом этого ревью.
Вердикт
Зелёный. ТЗ готово к разработке.