13 KiB
SPEC-REVIEW-373-r1
Issue: #373 — Add a
fit-to-content / crop option for houseplan-space-card.
ТЗ: docs/specs/373-space-card-house-fit.md
Материал ревью (SHA): e7ba22c623f6e9c0e5493cfe2a1706443621184b (= текущий
HEAD, git rev-parse HEAD сверен перед выводом).
Заход: r1 · блокирующих циклов израсходовано 0 из 4 (первый заход, лимита ещё
нет; полный трек, лимит 4).
Скоуп проверки
Первый заход — разбор полный, дельты нет. Прочитано в порядке инструкции:
docs/SCOPE.md, PROCESS.md, тело issue #373 и все четыре комментария
(владелец → OUARZA → владелец → аналитика владельца → хендофф автора ТЗ),
docs/USER-GUIDE.md (раздел 18 «Static space card»), docs/CANVAS.md
целиком (§4, §4.1, §4.2, «every place that assumed the unit square»),
docs/TOUCH-SUPPORT.md, docs/CONFIG-COMPATIBILITY.md (фрагменты про
view_box/новые поля), docs/ARCHITECTURE.md (раздел про
houseplan-space-card), и сам файл ТЗ целиком.
Дополнительно сверено с текущим кодом, чтобы отличить факт от досочинённого поведения:
src/space-render.ts:260-316— подтверждает буквально описанный в ТЗ вызовspaceFrame(space, placed, o.compactTopFrame ? {...} : 0.05), включая сборzeroWalls,physicalBodyParts(...).all(drafts/partitions/columns) и device-маркеров как voter'ов текущего content frame;src/space-geometry.ts:382-446—contentFrame/spaceFrameреализуют ровно ту логику 5%-паддинга и outlier-голосования, которую ТЗ называет «текущим поведением» и явно исключает из новогоhouse-режима;src/render/opening-symbol.ts:53-150— подтверждает, что jamb/leaf/arc для door/window/gate — существующая, общая для static и full карточек геометрия, а не новая подсистема;src/space-card.ts:58-71,src/space-editor.ts:40-54— подтверждают формуSpaceCardConfig, паттернha-form/selector.select.dropdown(уже используется дляspace) и отсутствие конфликта имениfitс существующими полями;src/i18n/{en,ru,de,fr}.json— все четыре локали существуют, план i18n реалистичен;package.json—bundle:budget,bundle:syncсуществуют;demo/smoke_space_card.mjsсуществует (ls demo/smoke_*.mjs | wc -l= 203);docs/specs/README.mdиgit show <commit>для #372 (d696541a) и #373 (e7ba22c6) — сверка соглашения об индексе, см. находку L1 ниже.
Гейты в этом заходе не гонялись: этап — ревью ТЗ, кода к диффу нет (в ветке
задачи только новый файл docs/specs/373-space-card-house-fit.md, класс C).
typecheck/test/build не применимы к этапу spec-review.
Как проверялось
Не «согласился с автором», а состязательно: для каждого утверждения о
«текущем поведении» найдена конкретная строка кода, которая его подтверждает
(список выше). Для каждого продуктового решения — конкретный комментарий в
issue, который его фиксирует. Отдельно искал: (а) утверждения о поведении,
которого нет ни в одном документе и которое не помечено как предположение;
(б) технические вопросы, ошибочно поднятые как продуктовые к владельцу —
не найдено ни одного, все продуктовые вопросы уже закрыты перепиской
владелец↔OUARZA до аналитики; (в) несоответствие треку small/trivial —
аналитик обоснованно выбрал полный трек и назвал нарушенный критерий (новый
публичный UX-контракт).
Находки
L1 (Low) — docs/specs/README.md не обновлён
Коммит e7ba22c6, добавивший docs/specs/373-space-card-house-fit.md,
меняет только этот один файл. Действующее соглашение репозитория — индекс
docs/specs/README.md обновляется в том же коммите, что и сам файл ТЗ:
коммит d696541a (#372) правит одновременно новый файл ТЗ и
docs/specs/README.md (+1 строка). Для #373 такой строки в индексе нет —
grep -n "373" docs/specs/README.md не находит ничего.
Почему Low, не Medium. Не влияет ни на один AC, не меняет проверяемость и не продуктовое поведение — чисто индекс. Правится одной строкой в любой момент до слияния; не обязано блокировать переход в «Готово к разработке».
Что сделать: автор добавляет строку в таблицу docs/specs/README.md
(вероятно P2, судя по метке issue) в этом же ТЗ-коммите или в первом
коммите реализации. Не требует отдельного цикла ревью.
Проверено и корректно
- Продуктовая рамка (§7.1, первые два раздела). «Сценарий» называет
персону из
docs/SCOPE.md(домашний администратор встраиваетcustom:houseplan-space-cardв компактный dashboard) и поверхность (View/kiosk на планшете/телефоне). «Что человек увидит» сформулировано без терминов реализации. Задача закрывает J1 («компактная houseplan-space-card должна использовать ограниченную площадь dashboard») — соответствуетdocs/SCOPE.md, не задевает ни один пункт «Out of scope». - Продуктовые вопросы закрыты перепиской, не додуманы. Проверил дословно: владелец спросил, должен ли backdrop/объект-вне-комнат входить в кадр или только геометрия дома; OUARZA ответил категорично — «fitting bounds should use room/house geometry» (не только «вне комнат»), что и оправдывает контрактный пункт 8 ТЗ (исключение backdrop/decor/labels/markers/badges из голосования кадра как единого правила, а не частного случая «вне комнат»). Это не догадка, а прямое следствие ответа репортёра.
- Каждое утверждение о «текущем поведении» проверено по коду, а не принято на слово (список файлов/строк в разделе «Скоуп проверки» выше). Ни одного расхождения не найдено.
- AC1–AC8 однозначны и указывают способ доказательства (
unit/smoke/ code review), включая обратную совместимость (AC1), геометрию (AC2/AC3), безопасный fallback на вырожденных/пустых пространствах (AC4), редактор и i18n (AC5), touch/View паритет (AC6), перформанс (AC7), документацию и релиз (AC8). Каждый снабжён конкретной фикстурой или сценарием, а не общей фразой «работает корректно». - Раздел «Assumptions accepted provisionally» явно отделяет техническое
решение от продуктового и помечен как оспоримый ревьюером — ни одно из
семи предположений не маскирует продуктовое решение под техническое;
все семь — действительно нейтральные для пользователя технические выборы
(имена внутренних хелперов, аналитический envelope без
getBBox(), точные фикстуры тестов). - Не-скоуп корректно отсекает соседнее поведение: полная
custom:houseplan-card, её Fit all/zoom/pan/outlier-hint,title:""семантика #372, изменение модели/схемы/view_box, произвольный пользовательский паддинг — всё явно исключено, что не даёт диффу реализации расползтись за рамки одной карточки. - Данные/миграция/откат: новое поле живёт только в конфиге карточки
Lovelace, не в House Plan config/layout — обоснованно не требует ни
backend-схемы, ни миграции, ни отдельного compatibility-поля по
docs/CONFIG-COMPATIBILITY.md. Откат («убрать проекцию/опцию редактора») безопасен и не требует очистки данных. - i18n-план реалистичен: все четыре объявленных локали (
en/ru/de/fr) существуют вsrc/i18n/, паттерн добавления строк такой же, как для существующих ключей (editor.title,title.zoom_fitи т.д.). - Производительность и touch/themes разделы формулируют проверяемые
ограничения (без DOM-измерений/
getBBox(), одинviewBoxна все слои, без роста initial-бандла), согласованные сdocs/CANVAS.md§6 (тот жеiconUnit()/канонический подход к рамке) иdocs/TOUCH-SUPPORT.md(View — release-blocking, конкретные ширины 320/900 px).
Чего не проверял
- Реализуемость «zero-thickness room and independent wall axes» и «columns»
как voter'ов кадра проверена только чтением существующих функций
(
physicalBodyParts,resolveZeroWalls— уже используются вspace-render.ts), не исполнением: код для новогоhouse-режима ещё не написан, поэтому не могло быть ни unit-, ни smoke-прогона. - Golden/скриншоты,
bundle:budget, полный Validate — не гонялись: этап spec-review не производит diff поsrc/**; правки применимы к коду ревью, не к этому этапу. - Не оценивал трудозатраты/оценку сложности (5/10 в аналитике) — не входит в мандат ревью ТЗ.
- Не проверял финальные тексты en/de/fr переводов (они появятся в реализации) — только то, что файлы существуют и структура ключей совместима.
Вердикт
Только Low-находка, не блокирует. AC полны, продуктовые вопросы закрыты переговорами до ТЗ (не додуманы), контракт однозначен и проверяем, скоуп/не-скоуп корректно отсекают соседнее поведение, откат и i18n решены.
Вердикт: зелёный · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 0