Files
houseplan-card/legacy/reviews/v1.63.0/SPEC-REVIEW-89-r1.md
T
Claudeandclaude[bot] 0991c45374 fix(tools): архив переписывает относительные ссылки перенесённых документов (#682)
Ревью #682 r1, Medium: перенос добавляет документу уровень вложенности
(`docs/reviews/X.md` → `legacy/reviews/<тег>/X.md`, `docs/specs/` →
`legacy/specs/`), а относительные ссылки внутри перенесённых документов и в
соседях, ссылавшихся на них, никто не пересчитывал — на `97d19268` 53 битые
ссылки в 46 файлах (заявление «все 26 резолвятся» в `7feb6177` было верно
только до переноса документов ревью). Гейты архив не смотрят.

`reviews-archive.mjs`: `repairLinks` пересчитывает ссылку, если она не
резолвится от нового места, а цель находится от нового или старого места
через карту переносов; битая и до переноса ссылка не трогается. `--apply`
делает это само, `--repair-links=<rev>` — для всех переименований
`<rev>..HEAD`, `--check-links` печатает битые. Этим коммитом
`--repair-links=origin/dev` переписал ровно 53 ссылки в 46 файлах; остались
две прежние «...»-заглушки в CODE-REVIEW-448-r2 (битые и на dev). Тесты:
перенесённый документ, сосед со ссылкой в архив, ТЗ со ссылкой на позже
перенесённое ревью, битая-до-переноса не трогается, в `legacy/` битых нет;
мутант `reviews-archive-links-from-new-place-only`. PROCESS §2.10 и
DEVELOPMENT › Release называют переписывание и `--check-links`.

Issue: #682
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-27 22:10:47 +00:00

233 lines
20 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-89-r1 — #89, этап 1: объёмный вид за флагом Labs
- Issue: [#89](https://github.com/Matysh/houseplan-card/issues/89)
- Этап: `spec` (PROCESS.md §2.4)
- ТЗ под ревью: [`docs/specs/089-isometric-view-stage1.md`](../../../docs/specs/089-isometric-view-stage1.md), ревизия 3
- Диапазон: `origin/dev...74b08df` (ветка `issue/89-isometric-stage1`, детач `HEAD`)
- Цикл: **r1/4** (первый независимый ревью-артефакт этой задачи в `docs/reviews/`;
«историческое ревью ревизии 1», упомянутое в теле issue и в самом ТЗ, честно
помечено автором как недоступный артефакт репозитория и не засчитывается)
- Вердикт: **зелёный**
## Скоуп ревью
Диапазон коммитов `origin/dev...HEAD` содержит только:
- `docs/SCOPE.md` — узкое исключение для #89 в разделе Out-of-scope;
- `docs/specs/089-isometric-view-stage1.md` — нормативное ТЗ этапа 1 (ревизия 3);
- `docs/specs/README.md` — обновление строки статуса ТЗ.
Продуктовый код, тесты, бандлы и changelog не менялись (`git diff --stat`).
Коммит `74b08df` несёт трейлеры `Issue: #89` / `User-Visible: no`, что верно для
документации без изменения поведения.
Референсный контекст, прочитанный до вердикта: `docs/SCOPE.md`, `AGENTS.md`,
`PROCESS.md` (§1–§9, §12), тело issue #89 и все 7 комментариев (включая
`PSEUDO_3D_SPECIFICATION.md`, приложенный владельцем, и решения владельца
Q1–Q6/O1–O6), `docs/CANVAS.md`, `docs/WALL-THICKNESS.md`, `docs/LIGHT.md`,
`docs/UX-MODES.md`, `docs/TOUCH-SUPPORT.md`, `docs/WARM-REMOUNT.md`,
`docs/CONFIG-COMPATIBILITY.md`, родительский `docs/specs/089-isometric-view.md`.
## Как проверялось
Это ревью ТЗ, не ревью кода: гейты `npm test`/`npm run build`/`npm ci` не
запускались — изменение класса C (документация), продуктовый и тестовый код не
затронуты, самостоятельный техдолг-issue на гейт не требуется. Проверено:
| Проверка | Результат |
|---|---|
| `git diff --check origin/dev...HEAD` | green (0 конфликтов/пробельных ошибок) |
| Провенанс коммита `74b08df` (`Issue:`/`User-Visible:`) | корректны для класса C |
| Обязательные разделы ТЗ по PROCESS.md §7.1 | см. таблицу ниже |
| Каждый AC1–AC15 — однозначность + способ доказательства | см. «AC» ниже |
| Технические утверждения ТЗ против реального кода/канонических доков | см. «Верификация фактов» — заняло основную часть ревью |
| Ссылки на issue (#82, #73, #50, #85, #83, #52, #92, #93, #95) | все существуют, тематика совпадает с тем, как на них ссылается ТЗ |
| Признаки «догадка выдана за решение» без пометки предположения | целевой поиск, см. ниже |
### Обязательные разделы ТЗ (PROCESS.md §7.1)
| Раздел | Есть | Где |
|---|---|---|
| Проблема | да (через job/персону/issue) | §1, тело issue |
| Скоуп и не-скоуп | да | §1 (входит/не входит), §14 |
| Контракт поведения | да, избыточно подробно | §2–§9 |
| UX | да (сведён к минимуму по решению D1) | §3, §7 |
| Модель данных и миграция | да | §10 |
| i18n | да | §13.4 |
| AC1…ACn с доказательством | да, с отдельной матрицей проверки ревьюера | §11.6, §12 |
| План автотестов | да, очень подробный (unit/smoke/golden/mutation/a11y) | §11 |
| Риски | **распределены по документу, не собраны в отдельный раздел** — см. находку L1 | §0.2 (B1–B8), §8.2, §9, §13.5 |
| Откат | да, полный (флаг + code revert) | §13.5 |
| Release-артефакты | да (внутренние — согласовано с D1/D7) | §13.2, §13.3 |
### Верификация фактов (проверка «догадка выдана за решение»)
ТЗ делает десятки конкретных технических утверждений о существующем коде и
канонических документах. Каждое проверено, поскольку неверное утверждение,
поданное как факт, — именно тот дефект, который должен убить ревью:
- `.hdr.kioskhide { display: none }` — подтверждено, `src/styles.ts:976`,
`src/houseplan-card.ts:13686`. Утверждение B5 («кнопки в киоске нет и быть не
может») технически верно.
- `_hashSpace()` и её единственный regex-парсер — подтверждено,
`src/houseplan-card.ts:1607` и использования далее.
- `mix-blend-mode: screen` для Glow — подтверждено, `src/styles.ts:550`,
`src/glow-blend.ts`.
- `filter: brightness(...)` на `.zoomwrap` для day/night — подтверждено по духу
(`src/houseplan-card.ts:13785`, переходная яркость на том же слое); формулировка
ТЗ не переоценивает механизм.
- `wallBodiesGeometry()` в `src/wall-thickness.ts`, используется в
`src/houseplan-card.ts` и разделяется с моделью света — подтверждено, совпадает
с `docs/LIGHT.md` («barriers… wallBodiesGeometry»).
- `NORM_W = 1000` в `src/space-geometry.ts`, pivot `[NORM_W/2, NORM_W/2]` —
константа подтверждена; выбор пивота обоснован ровно тем риском, который
описывает `docs/CANVAS.md` (`_showFar`/`_baseVb()` меняют кадр, а не
геометрию).
- `_cfgEpoch`, `_showFar`, `_svgPoint()` — все подтверждены в
`src/houseplan-card.ts`; предупреждение D5 («кэш по эпохе уже ломался на
барьерах света») — прямая цитата реального прошлого дефекта, не спекуляция.
- `localStorage` ключи-соседи `houseplan_card_layout_v1`, `houseplan_card_cfg_v1`
— подтверждены в `src/houseplan-card.ts` / `src/config-store.ts`.
- `docs/WARM-REMOUNT.md`: `_view`, `_viewModeSnap`, `_showFar`, `warmBoot`,
правило «воскрешаем черновик, не воскрешаем решение» — расширение контракта в
§7.1 ТЗ (проекция + логический центр в слоте) непротиворечиво накладывается на
существующую модель слотов, не переопределяет её.
- `docs/CANVAS.md`: диапазон `±5000` (`CANVAS_LIMIT`), `_baseVb()`/`spaceFrame()`
— оба факта, на которые ссылается ТЗ (B1: «`_baseVb()` не знает про поднятые
грани»), подтверждаются текстом канона.
- `docs/TOUCH-SUPPORT.md`: требование явно писать «Touch editor:
supported/best effort/not exposed» в спеке нового фичи — ТЗ соблюдает это
буквально (§7: «Touch editor: не exposed»).
- Отсутствие зависимости `semver` в проекте (утверждение §2.4, M3) —
подтверждено по `package.json`: только `lit`, `polyclip-ts` в
`dependencies`.
- `demo/performance/budgets-*.json`, `demo/golden/harness.mjs`,
`GOLDEN_MATRIX_VERSION` (`demo/golden/matrix.mjs:4`), `test/golden-matrix.test.mjs`
— все существуют; переиспользование инфраструктуры (M6, M7) не изобретает
несуществующие точки расширения.
- Ссылки на #82 (P2 feature, камера/zoom-fit), #73 (закрыт, мигание при
возврате на вкладку), #50 (закрыт, экспорт/импорт конфигурации), #85
(тесты/infra, «смок должен уметь падать»), #83 (P2 feature, «Сводка дома»,
кандидат на Labs), #52 (S4-spec-review, размеры на плане, кандидат на Labs) —
все существуют и совпадают по теме с тем, как на них ссылается ТЗ.
- Камера `rotDeg = 0`, наклон `18–22°` (§4.2) — это не догадка автора, а
буквальная рекомендация из `PSEUDO_3D_SPECIFICATION.md`, приложенного
владельцем к issue (комментарий владельца от 2026-08-13, раздел 6:
«Рекомендуемый наклон от вида строго сверху: 18–22°»). Формулировка ТЗ
корректно оставляет точное значение внутри диапазона решению ADR (§13.1),
не выдаёт его за уже принятое число.
Не найдено ни одного утверждения о поведении карточки, которое не имело бы
основания в коде, в каноническом документе или в материалах владельца и не
было бы при этом явно помечено как решение ADR/предположение (§15). Это
отличает документ от типичного ТЗ такого объёма.
## Находки
Ни одной **High**. Ни одной **Medium**. Две **Low** — обе разобраны и сняты
здесь же с записью, отдельные issue не заводятся (PROCESS.md §2.4: на этапе ТЗ
Low «либо правится, либо снимается решением ревьюера с записью в документе»).
### L1 — риски не собраны в отдельный раздел
PROCESS.md §7.1 перечисляет «риски» как самостоятельный обязательный раздел
ТЗ, отдельно от AC и от «откат». В `089-isometric-view-stage1.md` риски не
собраны под одним заголовком: они распределены по §0.2 (таблица находок
B1–B8, каждая — с формулировкой риска и тем, куда внесено исправление), §8.2
(риск деградации perf на больших планах), §9 (риск падения renderer) и §13.5
(риск, что этап 1 сломает flat-путь — с явным следствием «issue возвращается в
S6, бета блокируется»). Содержательно риски перечислены и снабжены мерами;
не хватает одного места, где их видно списком.
**Вердикт по находке:** снимается с записью. Материал присутствует и
проверяем; отсутствие заголовка не делает ТЗ неисполнимым или
непроверяемым — это единственный критерий блокировки на этом этапе.
Рекомендация автору на будущее (не обязательна для этой ревизии): свести
таблицу B1–B8 плюс §8.2/§9/§13.5 в один поднумерованный список «Риски»,
чтобы не заставлять читателя собирать его по документу вручную.
### L2 — «нормативная» таблица слоёв формально противоречит собственному запрету ТЗ на новый оконный элемент
§6 ТЗ открывается фразой «Поведение слоёв — таблица §6 исследования
[`089-isometric-view.md`], она нормативна», а затем добавляет булиты «как
обязательный контракт Stage 1». Строка «Окно» в этой внешней таблице
буквально обещает «Разрыв объёма с **отдельным стилизованным оконным
элементом**»; булиты этажа 1 сразу же запрещают именно это: «вертикальные
створки, светлые оконные вставки и **новый оконный свет не появляются**».
Решение владельца O5 (комментарий от 2026-08-13) и AC13 подтверждают, что
запрет — это то, что реально должно быть реализовано; формулировка «таблица
нормативна» без явной оговорки «кроме строки Окно, которую переопределяет
§6/O5/AC13» создаёт секундное разночтение для читателя, который сверяется
только с внешней таблицей.
**Вердикт по находке:** снимается с записью, поскольку фактическое
поведение однозначно зафиксировано трижды в самом ТЗ (булиты §6, AC13, §14
п.3 «Полировка дверей, окон и ворот… — этап 2») и в решении владельца O5 — не
только в спорной внешней таблице. Реализация и код-ревью не могут выбрать
неверный вариант, читая только ТЗ. Рекомендация автору на будущее: одна
фраза («кроме строки Окно/Ворота — см. булиты ниже») сняла бы вопрос совсем.
## Что проверено и корректно
- Обязательные разделы ТЗ по PROCESS.md §7.1 присутствуют (кроме
консолидации рисков — L1, снята).
- Все 15 AC пронумерованы, для каждого указан способ доказательства
(`unit`/`smoke`/`golden`/`performance`/код-ревью), и матрица §11.6
дополнительно предписывает ревьюеру кода конкретную проверку исполнением —
это закрывает будущий провал типа T1 («смок должен уметь падать»), на
который прямо ссылается #85.
- Каждое технически-конкретное утверждение (имена функций, констант, CSS
правил, файлов инфраструктуры, номера issue) проверено против реального
кода/документов и подтвердилось — см. «Верификация фактов». Догадок, не
помеченных как предположение, не найдено.
- Границы этапа (D1, O1–O6) корректно и без потери смысла перенесены из
решений владельца (issue-комментарии Q1–Q6/ответы) в нормативный текст ТЗ.
- Раздел «Принятые предположения» (§15) корректно отделяет то, что автор
вправе менять свободно (имена модулей, точные числовые константы внутри
диапазона, версионирование localStorage-ключей), от продуктовых решений.
Технические вопросы в issue не встречаются — автор не выносил владельцу то,
что должен решать сам (в отличие от типичной ошибки, которую просит искать
этот процесс).
- Touch/kiosk-контракт сформулирован по правилам `docs/TOUCH-SUPPORT.md`
(явная строка `Touch editor: не exposed`, конкретный touch target 44×44 CSS
px, release-blocking пункт для View/kiosk).
- Совместимость с `docs/CONFIG-COMPATIBILITY.md`: формат конфигурации не
меняется, новых полей нет, `localStorage`-ключ версионирован суффиксом
`_v1` — не требует записи в реестр совместимости (реестр покрывает только
серверный конфиг).
- Откат (§13.5) полный: аварийный пользовательский путь без пересборки
(`?hp-labs=-iso`/`off`) и полный code rollback (revert + удаление флага из
реестра) без обратной миграции данных.
- Именование файла ТЗ (`089-isometric-view-stage1.md`) соответствует правилу
PROCESS.md §2.3 для многоэтапной задачи (`<NN>-<slug>-stage<N>.md`).
- Не найдено расширение скоупа сверх решённого владельцем: этап 1 явно
ограничен Stage 1 Labs/spike+renderer (O4), Stage 2 вынесен в будущий issue.
## Чего не проверял
- Гейты `npm ci`/`npm test`/`npm run build`/`golden`/`performance` не
запускались — на этом коммите нет изменений класса A/B/D, запускать их
было бы проверкой пустого множества.
- Не проверялась реализуемость точных числовых бюджетов perf (§8.2, «20%
относительный допуск») на реальном большом плане — это по определению
проверяется на этапе code review профилем `large-house-isometric-v1`,
которого пока не существует.
- Не проверялось поведение в Safari/WebKit и Firefox для заявленных
filter/clip/mix-blend рисков (§13.1 ADR) — согласно самому ТЗ, это предмет
ADR/spike, а не текста спеки.
- Не оценивался остаточный риск того, что технический пользователь найдёт
`?hp-labs=iso` в живом бандле раньше Stage 2 (сам механизм URL-флага по
конструкции обнаруживаем через чтение бандла/консоли). Это осознанный
побочный эффект многократно переиспользуемого механизма Labs (D2, O3),
одобренного владельцем для будущих #82/#83/#52 — не специфичный для #89
риск, который стоило бы решать в рамках этой задачи.
## Вердикт
**Зелёный · цикл r1/4 · High: 0 · Medium: 0 → нет новых issue.**
ТЗ проверяемо, однозначно по каждому AC, границы этапа зафиксированы решением
владельца, а технические утверждения выдерживают проверку против кода и
канонических документов. Обе Low-находки сняты с записью в этом документе.
Следующий статус — «Готово к разработке» (`S5-к-разработке` / `S5-ready`).