Files
houseplan-card/docs/reviews/SPEC-REVIEW-271-r1.md
T
2026-08-23 21:06:00 +03:00

11 KiB
Raw Blame History

SPEC-REVIEW-271-r1

Issue: #271 — «Degree-3 узел достраивает короткий луч до 8×H и рисует несуществующую стену и тень» Этап: spec (PROCESS.md §2.4) Заход: r1 · блокирующих циклов израсходовано 0 из 4 ТЗ: docs/specs/271-finite-multiwall-rays.md, SHA 482b2be512b38cadb40855b79b710f6602d5eb54

Скоуп разбора

Первый заход — разбор полный. Проверено: docs/SCOPE.md, AGENTS.md, PROCESS.md (включая §2.4, §7.1, §4), тело issue #271 и оба комментария (аналитика + «ТЗ готово к ревью»), канонический docs/WALL-THICKNESS.md, сам ТЗ, исходный код src/wall-thickness.ts (интерфейс MultiWallNodeRay, buildMultiWallNodeMap, bevelMultiWallBody, константы MITRE_LIMIT, MULTI_WALL_JOIN_LIMIT), связанные issue #249/#261/#270/#272/#273 (заголовки и статусы — все закрыты либо остаются открытыми отдельными задачами, ни одна не дублирует #271).

Как проверялось

  1. Сверил числа из таблицы issue/ТЗ (реальная длина луча vs. текущий rebuild) с формулой в коде: radius = MITRE_LIMIT * node.halfDepth + eps*2, extent = radius * 2 (src/wall-thickness.ts:2032-2033) — при MITRE_LIMIT=4 это ровно 8×halfDepth. Пример узла 2 (2404.167, 1245.833): H=62.5 → 8×62.5=500.000, совпадает с «Текущий rebuild» в таблице ТЗ. Формула и цифры не выдуманы, а прослеживаются до реального кода.
  2. Проверил, что MultiWallNodeRay (src/wall-thickness.ts:51-54) действительно хранит только {u, halfDepth} без длины — корневая причина, заявленная в §3 ТЗ, подтверждена чтением, не только цитированием issue.
  3. Сверил каждый обязательный раздел ТЗ с перечнем PROCESS.md §7.1: сценарий, что человек увидит, проблема, скоуп/не-скоуп, контракт, UX, модель данных/миграция, i18n, AC1…ACn с доказательством, план автотестов, риски, откат, release-артефакты — присутствуют все.
  4. Прочитал все девять AC на однозначность и способ доказательства; для каждого проверил, что критерий формулирует наблюдаемое условие (геометрия/присутствие material), а не расплывчатое «стало лучше».
  5. Проверил список «не входит» (§5) против реально открытых соседних issue (#272 — белые треугольные дыры вне probe #261; #273 — sub-grid островок при Optimize) — границы скоупа корректны, чужого не захватывают.
  6. Проверил путь ТЗ (docs/specs/271-finite-multiwall-rays.md) — issue не помечен small, файл обязателен и создан по имени <NN>-<slug>.md, что соответствует правилу.
  7. Проверил, что упомянутые файлы существуют: test/wall-thickness.test.mjs, docs/ARCHITECTURE.md, docs/TESTING.md, docs/CONFIG-COMPATIBILITY.md — все на месте, ссылки не битые.

Гейты кода в этом раунде не гоняются — стадия spec, продуктовый код не менялся (единственный коммит раунда — docs(spec): ..., класс C). npm test/typecheck /build не относятся к предмету ревью ТЗ и не запускались.

Находки

Нет. Ни одной High или Medium находки — ни в скоупе, ни вне его.

Разобрано отдельно и отклонено как находка:

  • Полнота списка документации (§9). ТЗ включает docs/USER-GUIDE.md / docs/USER-GUIDE.ru.md в список документов на обновление, хотя пользователю не добавляется ни один новый видимый термин или контрол. Это не дефект: раз видимая геометрия меняется (User-Visible: yes в §10), а требование AGENTS.md — обновлять UI-терминологию из USER-GUIDE при изменении видимого поведения — включение файла в список консервативно и не создаёт риска; решение оставить формулировку в тексте или сократить список — на усмотрение автора при реализации, Low, не фиксирую отдельно.
  • Отсутствие имени конкретного нового smoke-файла в AC4/AC5. Смок ещё не существует (создаётся в реализации), поэтому называть файл в ТЗ не требуется — PROCESS.md §7.1/2.5 просит указать категорию доказательства (smoke), а не имя ещё не написанного файла. Не находка.

Что проверено и корректно

  • Корневая причина (§3 ТЗ) совпадает с кодом посимвольно: MultiWallNodeRay теряет длину, bevelMultiWallBody перестраивает луч на 8×H. Не догадка — прослежено до строк кода.
  • Сценарий и персона (§1): администратор нажимает Optimize → Plan/View, видит несуществующую стену/тень — прямая связь с J1 («правдиво показывать дом») и J6 (одна геометрия для всех потребителей), обе строки есть в docs/SCOPE.md.
  • Скоуп/не-скоуп (§5) явно исключает соседние открытые дефекты (#272 белые дыры, #273 sub-grid островок, форма #249 bevel, MITRE_LIMIT/ MULTI_WALL_JOIN_LIMIT) — задача не разрастается на смежные баги.
  • Контракт §6 формулирует финитность луча через проверяемые условия: локальная полоса существует только на t ∈ [0, length]; правило дедупликации co-directional дубликатов явно запрещает «перекрыть зазор» присутствием соседнего короткого/толстого дубликата (типичная ловушка, которую легко упустить) — прямо закрыто текстом контракта.
  • AC1-AC9 — каждый формулирует наблюдаемое состояние геометрии (присутствие/отсутствие material в конкретной точке, конкретные числа 20.833 → не 500, 12.5 → не 110) и называет способ доказательства (unit / geometry unit / targeted smoke / golden semantic probe / mutation). AC7 отдельно требует, чтобы мутант уронил AC2 или AC4 — то есть тест на фальсифицируемость заложен в само ТЗ, а не оставлен на усмотрение код-ревью.
  • Технические предположения (§13) помечены явно как «assumed, change freely» и действительно являются техническими (внутреннее представление finite support), а не спрятанным продуктовым решением. Предположение про wall_columns унаследовано от собственного анализа владельца в комментарии аналитики, а не изобретено автором ТЗ.
  • Совместимость/UX/perf/touch (§7): персистентная модель не меняется, миграции нет, новых контролов/i18n/HA-вызовов нет, touch явно назван («новых keyboard/touch/focus/ARIA... нет»), perf ограничен явным запретом нового глобального O(E²) прохода.
  • Откат (§12) запрещает частичный откат только тестов — учтён урок, из-за которого регрессия становится снова невидимой.
  • Продуктовых вопросов владельцу нет и не должно быть: единственное решение задачи («физическое тело не может продолжаться дальше конца отрезка») уже прямо следует из J1 и не требует выбора между персонами или трактовки пограничного случая.

Чего не проверял

  • Не проверял реализацию (её нет — это стадия spec, код не менялся).
  • Не прогонял typecheck/test/build/check-docs — не относится к этому этапу, диапазон изменений раунда состоит из одного документного коммита.
  • Не воспроизводил приватные 1.json/2.json владельца — они не в репозитории по правилу «не коммитить пользовательские данные»; проверка ограничилась числами, которые ТЗ и issue цитируют, и сверкой формулы в коде.
  • Не оценивал, оптимальна ли выбранная будущая технической реализация (union конечных spans vs. clipped polygon) — это по §13 оставлено автору реализации и будет предметом код-ревью.

Вердикт

Все обязательные разделы (PROCESS.md §7.1) присутствуют, каждый AC однозначен и называет способ доказательства, корневая причина подтверждена чтением кода, а не выдана за факт без опоры. Открытых продуктовых вопросов нет и не должно быть.

Зелёный.