11 KiB
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).
Как проверялось
- Сверил числа из таблицы 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» в таблице ТЗ. Формула и цифры не выдуманы, а прослеживаются до реального кода. - Проверил, что
MultiWallNodeRay(src/wall-thickness.ts:51-54) действительно хранит только{u, halfDepth}без длины — корневая причина, заявленная в §3 ТЗ, подтверждена чтением, не только цитированием issue. - Сверил каждый обязательный раздел ТЗ с перечнем PROCESS.md §7.1: сценарий, что человек увидит, проблема, скоуп/не-скоуп, контракт, UX, модель данных/миграция, i18n, AC1…ACn с доказательством, план автотестов, риски, откат, release-артефакты — присутствуют все.
- Прочитал все девять AC на однозначность и способ доказательства; для каждого проверил, что критерий формулирует наблюдаемое условие (геометрия/присутствие material), а не расплывчатое «стало лучше».
- Проверил список «не входит» (§5) против реально открытых соседних issue (#272 — белые треугольные дыры вне probe #261; #273 — sub-grid островок при Optimize) — границы скоупа корректны, чужого не захватывают.
- Проверил путь ТЗ (
docs/specs/271-finite-multiwall-rays.md) — issue не помеченsmall, файл обязателен и создан по имени<NN>-<slug>.md, что соответствует правилу. - Проверил, что упомянутые файлы существуют:
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 однозначен и называет способ доказательства, корневая причина подтверждена чтением кода, а не выдана за факт без опоры. Открытых продуктовых вопросов нет и не должно быть.
Зелёный.