21 KiB
SPEC-REVIEW-122-r1
- Issue: https://github.com/Matysh/houseplan-card/issues/122
- ТЗ под ревью:
docs/specs/122-isometric-stage2.md(коммит76ce755, веткаissue/122-isometric-stage2) - Роль: ревьюер ТЗ (не автор), этап
S4-spec-review - Трек: обычный (не
small) — аналитика владельца оценила сложность и риск 9/10, поверхностей больше одной (рендер/геометрия/UX/perf); лёгкий трек корректно не применён,docs/specs/<NN>-*.mdприсутствует - Цикл: r1/4 (полный трек, лимит 4)
Скоуп ревью
Проверялось соответствие ТЗ:
docs/SCOPE.md— попадание в Core user jobs (J1/J2/J3), узкое owner-approved исключение из фотореалистичного/3D-запрета, инвариант lock;PROCESS.md§2.4/§2.5 (DoR), §7.1 (обязательные разделы ТЗ), §12 (запреты), §3 (правила 1, 2, 6, 9);AGENTS.md— классы файлов (толькоdocs/**в этом коммите), ветка, трейлеры;- нормативному предшественнику
docs/specs/089-isometric-view-stage1.mdиdocs/adr/089-isometric-stage1-renderer.md— что Stage 2 не переписывает принятые решения Stage 1 задним числом; - каноническим документам затронутой подсистемы:
docs/ISOMETRIC.md,docs/WALL-THICKNESS.md,docs/LIGHT.md,docs/TOUCH-SUPPORT.md,docs/UX-MODES.md; docs/USER-GUIDE.ru.md— что видимого пользователю текста не появляется и документ не должен меняться;- фактическому состоянию кода (
src/render/opening-symbol.ts,src/logic.ts,src/labs.ts,demo/golden/matrix.mjs) — на предмет того, что технические утверждения ТЗ не являются непроверенной догадкой; - треду issue #122 целиком, включая аналитику S2, вопросы владельца Q0–Q6 и их принятие, а также связанному issue #124 (performance-блокер).
Как проверялось
- Прочитан весь тред issue #122: аналитика (ценность 7/10, P2, сложность 9/10), пакет вопросов владельцу Q0–Q6 с default-вариантами, принятие всех default'ов владельцем 2026-08-13, хендофф автора «ТЗ готово к ревью». Подтверждено, что ни один вопрос не был техническим, замаскированным под продуктовый: Q0 (приоритет/ценность), Q1 (объём видимого сравнения Stage1/Stage2 — второй флаг или нет), Q2 (что задают референсы: материал или замена содержимого), Q3 (визуальное представление проёмов), Q4 (новый декоративный свет — да/нет), Q5 (floor edge/тени), Q6 (деградация) — все про то, что видит пользователь, и про объём этого issue.
- Сверены обязательные разделы ТЗ (§7.1
PROCESS.md) — таблица ниже. - Прочитан
docs/specs/089-isometric-view-stage1.mdцеликом иdocs/ISOMETRIC.md— подтверждено, что Stage 2 ссылается на реальные решения Stage 1 (wallBodiesGeometry(), единая проекция, fingerprint без_cfgEpoch/HA state, LRU-кэш на 8 сцен, latched flat fallback,projectedFrame(), Labs-грамматикаiso/since 1.62.0/expires 1.65.0) и не выдаёт их за собственное изобретение и не переписывает Stage 1 задним числом (ADR-89 не трогается, заводится новыйdocs/adr/122-*.md). - Прочитан
src/labs.ts(since: '1.62.0',expires: '1.65.0') иpackage.json(version: 1.63.0) — утверждение ТЗ «expiry не расширяется,1.65.0-beta.1уже мёртв» технически корректно и согласуется с описанным вdocs/ISOMETRIC.mdчисловым сравнением ядра версии. - Прочитан
src/render/opening-symbol.ts— подтверждены буквально: gate открывается ровно на 10° (10 * amount,docs/specs/122:213-215противopening-symbol.ts:97), window — двухстворчатый casement (rotate(${-90*amount})/rotate(${90*amount}),opening-symbol.ts:83-89против §6.5 «two-leaf/casement»). Это не догадка автора, а точное описание существующего кода. - Прочитан
openingAmount()вsrc/logic.ts:316-323— подтверждено поведение «no contact → door/gate open (1), window closed (0)», которое ТЗ называет «static-open default when no contact exists» (§6.5, Door/Gate). - Прочитан
docs/LIGHT.mdиdocs/WALL-THICKNESS.md— подтверждено, что «один регион света на источник», «wallBodiesGeometry как единственный источник тела стены», «exterior silhouette из union центральных линий» — реальные, а не придуманные инварианты, на которые ТЗ ссылается в §6.3, §6.7, §7. - Прочитан
docs/TOUCH-SUPPORT.mdцеликом — формулировки ТЗ §6.8 («pointer/focus/ARIA inert», «View и kiosk остаются полностью поддерживаемыми», «touch-only failure — product defect») дословно отражают контракт, а не изобретены заново. - Прочитан
docs/USER-GUIDE.ru.md— поиском подтверждено отсутствие каких- либо упоминаний изометрии/объёмного вида; утверждение ТЗ §9 «документ остаётся молчащим про скрытый Iso» верно на текущий момент. - Проверено существование golden-сцены
isometric-no-borders-darkвdemo/golden/matrix.mjs:23— AC15/§12.3 ссылаются на реальный, а не вымышленный сценарий. - Прочитан issue #124 (
gh issue view 124) — подтверждено: воспроизводимый performance-регрессviewToggleMs.median 192.8мсvs лимит131.7мсна exact-SHA профилеlarge-house-isometric-v1, статусS1-new(ещё не проанализирован). ТЗ §10 корректно описывает его как DoR-блокер реализации (не ревью), с двумя явными путями снятия (закрытие #124 или отдельное явное решение владельца) — ни то, ни другое не подменяет и не ослабляет существующий бюджет. - Проверено
docs/specs/README.md:80— строка на #122 добавлена в том же коммите, ссылка issue ↔ ТЗ двусторонняя. - Проверены трейлеры коммита
76ce755:Issue: #122,User-Visible: no;git show --statподтверждает изменение толькоdocs/specs/122-*.mdиdocs/specs/README.md— класс C, продуктовый код (класс A) не менялся, правило №1AGENTS.md/PROCESS.mdсоблюдено на этапеspec.
Обязательные разделы (§7.1 PROCESS.md)
| Раздел | Есть | Комментарий |
|---|---|---|
| Сценарий (персона/поверхность/момент) | ✅ | §1 |
| Что человек увидит до/после (без терминов реализации) | ✅ | §1, одной фразой |
| Проблема | ✅ | §2 |
| Скоуп / не-скоуп | ✅ | §4 / §5 |
| Контракт поведения | ✅ | §6 (8 подразделов) |
| UX | ✅ | §9 (явно: нет нового UI/i18n) |
| Модель данных и миграция | ✅ | §8 |
| i18n | ✅ | §9 (пусто, обосновано) |
| AC1…ACn с доказательством | ✅ | §11, 16 штук, каждый с типом |
| План автотестов | ✅ | §12 (unit/smoke/golden/performance/backend) |
| Риски | ✅ | §14, 12 строк с вероятностью/impact/mitigation |
| Откат | ✅ | §15 |
| Release-артефакты | ✅ | §13 |
Все обязательные разделы присутствуют и содержательны. Дополнительно присутствуют продуктовые под-разделы §7.1 (персона/поверхность/момент внутри §1) и явный блок §16 «принятые технические предположения — можно менять без пересмотра продукта», корректно отделённый от решений владельца §3.
Находки
Находок уровня High и Medium нет.
Low-1 — отсутствует буквальная декларация «Touch editor: …»
Файл: docs/specs/122-isometric-stage2.md (весь документ)
docs/TOUCH-SUPPORT.md («Documentation rule») требует от новых спецификаций
редакторных фич явно указывать одно из: Touch editor: supported / best effort / intentionally degraded / not exposed. Предшественник, Stage 1
(docs/specs/089-isometric-view-stage1.md, §7 «Touch editor: не exposed»),
эту декларацию давал буквально, хотя ситуация идентична — редакторы Stage 2
не касается вовсе (§6.1 «Editors and houseplan-space-card stay Flat»). Stage 2
такой буквальной строки не содержит, хотя по содержанию §6.1/§6.8 поведение
однозначно совпадает с «not exposed» — реальной неоднозначности для
разработчика или ревьюера кода нет.
Решение ревьюера: Low, не блокирует. Формально Stage 2 не вводит новую
редакторную фичу (правило TOUCH-SUPPORT.md адресовано именно им), а
содержательно контракт «редакторы не меняются» зафиксирован дважды (§6.1,
§9). Оставляю на усмотрение автора — можно добавить строку Touch editor: not exposed при следующей правке для единообразия с Stage 1, можно снять этой
записью.
Low-2 — три AC используют тип доказательства вне буквального перечня §2.5
Файл: docs/specs/122-isometric-stage2.md:445-457 (AC13, AC15, AC16)
DoR (PROCESS.md §2.5) перечисляет типы доказательства как unit / backend
/ smoke / golden / «ревью кода». AC13 помечен только (performance),
AC15 — (golden + documentation review), AC16 — (typecheck + unit + build).
Буквально performance, typecheck, build и documentation review в этот
перечень не входят. По существу все три доказуемы существующими механизмами:
performance_smoke/Full Performance и typecheck/build — реальные
release-blocking гейты PROCESS.md §8, а «documentation review» — часть
обычного код-ревью (§2.7). Тот же паттерн уже был отмечен как Low-1 в
SPEC-REVIEW-123-r1 и оставлен автору без блокировки цикла.
Решение ревьюера: Low, не блокирует. Переформулировка в термины §2.5 (например,
«ревью кода со ссылкой на performance_smoke/exact-SHA Full Performance» и
«ревью кода со ссылкой на зелёный typecheck/test/build») повысила бы
буквальную трассируемость, но не меняет, чем на практике будет доказан
критерий. Оставляю на усмотрение автора или снимаю этой записью.
Что проверено и корректно
- Соответствие
docs/SCOPE.md: задача закрывает J1/J2/J3, остаётся внутри узкого owner-approved исключения (2.5D, не фотореализм/не свободная камера/ не interior editor), не трогает единственную санкционированную поверхность actuation замков (docs/SCOPE.md«The lock invariant»). - Все вопросы владельцу (Q0–Q6) — продуктовые (видимое поведение, объём видимых изменений), ни один технический вопрос не был переадресован владельцу; все ответы получены и внесены в ТЗ без расширения скоупа.
- ТЗ явно наследует, а не переопределяет Stage 1: проекция,
wallBodiesGeometry, fingerprint без_cfgEpoch/HA-состояния, LRU-кэш 8 сцен, latched flat fallback, Labs-грамматикаiso/1.62.0/1.65.0— все повторно использованы корректно, ни одно принятое решение Stage 1 не переписывается задним числом (историческая ADR-89 остаётся неприкосновенной, заводится новаяdocs/adr/122-isometric-stage2-composition.md). - Технические утверждения о существующем коде (10° gate, two-leaf window,
static-open default при отсутствии contact, один регион света на источник,
wallBodiesGeometryкак единственный источник геометрии стен) подтверждены чтением реального кода, а не приняты на слово автора. - Скоуп/не-скоуп (§4/§5) корректно отсекает публичный rollout, второй флаг
iso2, свободную камеру/#82, новые material-настройки, объёмные редакторы иhouseplan-space-card, схемные поля высоты/подоконника, WebGL/Three.js — все типичные места, где скоуп мог бы незаметно расшириться, явно закрыты. - Зависимость от #124 обработана корректно: не как продуктовое решение
Q0–Q6 (не переоткрывает их), а как отдельный DoR-блокер реализации (§10) с
двумя явными путями снятия; ревью ТЗ по правилам
PROCESS.md§10 разрешено вести, пока #124 открыт. - i18n/UX (§9): подтверждено отсутствием новых строк, README/CHANGELOG/
USER-GUIDE не обещают публичную функцию — соответствует
User-Visible: noконтракту для всей будущей реализации. - Модель данных и совместимость (§8): подтверждено отсутствием новых
схемных полей, ключей
localStorageверсий и compatibility-записей; откат (§15) не требует миграции и работает немедленно через?hp-labs=-iso/off, как и в Stage 1. - AC1–AC16 однозначны, у каждого указан тип доказательства (за вычетом Low-2) и план автотестов (§12) даёт конкретный, воспроизводимый по коду маршрут; §12.1 явно требует, чтобы каждый unit-мутант «умел падать» (удаление внешнего edge, сдвиг leaf с jamb, включение HA-состояния в cache key, дублирование floor symbol, лишний light layer).
- Не найдено ни одного продуктового утверждения о поведении, которое не следует ни из канонических документов, ни из решений владельца Q0–Q6, ни из чтения существующего кода, и при этом не помечено как предположение; раздел §16 корректно отделяет свободно изменяемые технические детали (именование модулей, точные проценты высоты панелей, число SVG-корней) от зафиксированных владельцем решений.
- Реестр
docs/specs/README.mdобновлён тем же коммитом, коммит несёт корректные трейлеры (Issue: #122,User-Visible: no) и не содержит изменений класса A — правило №1 соблюдено на этапеspec.
Чего не проверял
- Не проверял реализуемость конкретной геометрической декомпозиции
(
iso-openings.ts/iso-scene.ts, точные проценты высоты панелей, число SVG-defs) — по правилам ТЗ (§16) это свободно изменяемое техническое предположение автора кода, не предмет ревью ТЗ. - Не проверял реальный performance-профиль
large-house-isometric-v1и не прогонял #124 — на этапеspecэто не требуется; факт открытости и статус #124 (S1-new) проверен черезgh issue view, не исполнением бенчмарка. - Не запускал никаких автотестов, golden или смоков — на этапе
specэто не требуется; существование референсных артефактов (isometric-no-borders-darkвdemo/golden/matrix.mjs) проверено чтением файла, не исполнением. - Не проверял содержимое
docs/adr/089-isometric-stage1-renderer.mdпострочно на полное покрытие всех констант камеры — доверился ссылке ТЗ иdocs/ISOMETRIC.mdкак согласованному пересказу; расхождений при чтении обоих источников не обнаружено. - Не оценивал субъективную эстетическую адекватность референсов владельца (issue #89, комментарий с изображениями) — это продуктовое решение, принятое владельцем через Q2 и не подлежащее пересмотру ревьюером ТЗ.
Вердикт
Зелёный. High: 0, Medium: 0. Две находки Low (отсутствие буквальной
декларации Touch editor: … и три AC с типом доказательства вне буквального
перечня §2.5) — не блокируют, оставлены автору на усмотрение с записью в этом
документе; при желании их можно поправить в этом же цикле без возврата в
S3-spec.