15 KiB
SPEC-REVIEW-302-r1
- Issue: #302 — «Артефакты на стыках стен: дыры в union-геометрии. Переработка механизма стыков + полноценный сет скриншот-тестов»
- ТЗ:
docs/specs/302-junction-node-material.md - Ветка:
issue/302-junction-node-material, ревьюемый SHA:3b19111aa5894f624e608b9f7fef31736a4ecdf5(родитель4b8f17ba, ровно вершинаdevна момент написания ТЗ) - Заход: r1 · блокирующих циклов израсходовано 0/4
- Класс изменения: A (продукт), трек: обычный (не
small) — корректно, задача явно затрагивает perf-бюджет и переработку подсистемы, критерии лёгкого трека не выполняются - Вердикт: зелёный
Скоуп ревью
Первый заход, разбор полный (§2.9 не применяется — нет r0). Проверялись:
тело issue #302 и единственный комментарий автора, docs/specs/302-junction-node-material.md
целиком, docs/SCOPE.md, PROCESS.md §1–§9, docs/WALL-THICKNESS.md целиком,
исходник src/wall-thickness.ts (4145 строк) — выборочно, по каждому
идентификатору и утверждению ТЗ, требующему проверки на существование/точность.
Как проверялось
- Продуктовая рамка.
docs/SCOPE.md— задача улинии с миссией («live spatial overview») через качество геометрии плана; это не новая фича, а устранение искажений в самом визуальном представлении дома — прямое следствие J1. Конфликта со SCOPE нет. - Процесс. Issue помечен
S4-spec-review, что и запускает этот этап; размер задачи (обычный) обоснован — трогаетsrc/wall-thickness.tsцеликом, влияет на perf-бюджет, не подходит под критерииsmall(§5 PROCESS.md требует «нет влияния на производительность» — здесь влияние прямо названо в §10 ТЗ). - Фактчекинг утверждений о коде и истории, чтобы отделить подтверждённые
факты от гипотез, выданных за решение (обязательный пункт инструкции):
MITRE_LIMIT,openEps,buildMultiWallNodeMap,wallIntervals,multiWallNodeAt,outsetContour/insetContour,bevelMultiWallBody/bevelMultiWallPaper,unionJunctionPatches,linearWallJoinPatches,stableJunctionPatch,wallBodiesGeometry,wallBodiesUnionPath— все существуют вsrc/wall-thickness.tsровно с тем поведением, которое им приписывает ТЗ (grep + прочтение сигнатур).EPS_NODE = openEps × 4— совпадает буквально с вызовом вmultiWallNodesForGeometry(wall-thickness.ts:2035-2036).wallBodiesUnionPathдействительно единственная точка входа для обоих рендереров:src/houseplan-card.ts:11687(Full/Plan) иsrc/space-render.ts:432(Static) — вызывают именно её. Утверждение §2 ТЗ «оба рендерера получают результат из одного и того же кода» не догадка, а факт.- Ссылки на прежние ТЗ (#141, #172, #197, #229, #249, #271, #272, #275,
#279, #288, #290, #296) сверены с содержанием
docs/WALL-THICKNESS.md— каждая деталь («R = 1.25×H»,NEAR_AXIS_MAX_DEGREES = 0.25, «near-orthogonal», «short ray handoff», сращивание коллинеарных равных стен из #229) находит буквальное соответствие в каноническом документе подсистемы либо в исходнике (src/near-axis.ts:6-7). - Все девять смоков из AC9 (
smoke_wall_junctions,smoke_junction_patch_resilience,smoke_split_corner_wall,smoke_zero_divider_taper,smoke_wall_thickness*) иsmoke_render_perf(AC8) существуют вdemo/. demo/golden/matrix.mjsсуществует и это действительно data-only каталог golden-фикстур (GOLDEN_MATRIX_VERSION), куда естественно ложится новый сет из §13.- Нового «детектора дыр» и
isPointInPath-инструментария в репозитории сейчас нет (grepпусто) — заявка «новый чистый модуль» корректна, это не дублирование существующего. - SHA
4b8f17b, на котором получены цифры 359/360 дыр, существует в истории и совпадает с прямым родителем ревьюемого коммита — воспроизвести довод «дыры родились в базовой фазе» можно на том же дереве.
- Смысловая проверка контракта §8, а не только буквенная. Рассмотрены
вырожденные и граничные случаи: узел из 2 лучей (веер строится на обеих
угловых секторах — внутренней и внешней стороне, поскольку у двух лучей при
круговом обходе ровно два соседства); дегенерат mitre при малом угле
(обрезается
MITRE_LIMIT, переходит в bevel — предотвращает уход материала в бесконечность); связь с историческим классом дефектов «короткий луч короче радиуса ремонта» (#271/#288) — новая механика по построению не продолжает луч вдоль его оси вовсе («конец полосы» — точка ровно у узла, офсетная по перпендикуляру, а не отложенная на расстояниеMITRE_LIMITвдоль луча), поэтому класс дефектов «репэйр перерос короткий луч» не имеет аналога в новой механике — не пробел ТЗ, а архитектурное упрощение, которое стоит явно назвать в фиксации, но не блокирует ревью. - Проверка DoR-состава (§2.5, §7.1 PROCESS.md): сценарий ✓, «что человек увидит» ✓, проблема/причина ✓ (§3 с исполненным доказательством), скоуп и не-скоуп ✓ (§6–7), контракт поведения ✓ (§8), данные/i18n/a11y/privacy ✓ (§9, всё «не меняется» — обосновано отсутствием миграции конфига), perf ✓ (§10, бюджет назван), риски ✓ (§11, три риска с конкретными мерами), AC ✓ (§12, 9 штук, пронумерованы), план автотестов ✓ (§13–14), откат ✓ (§16), release-артефакты ✓ (§15).
Находки
Ни одной находки уровня High или Medium. Два пункта Low — решение ревьюера: сняты с записью, правки не требуют.
- Low — способ доказательства AC не продублирован буквально на каждой
строке §12. AC1–AC5, AC8 описывают ожидаемый результат словами
(«детектор §8.4», «попиксельное совпадение», «смок сверяет пути»), а не
явным тегом
unit/golden/smokeпри каждом пункте, как того просит буква §2.5 PROCESS.md. Решение: снимается без правки — §13 однозначно называет механику («каждая сцена: golden крупным планом + детектор §8.4», «юниты: чистые функции веера... и детектора»), и разработчик/ревьюер кода не может трактовать способ доказательства иначе. Формальный тег ничего не добавил бы к однозначности. - Low — нет отдельного раздела «UX». Шаблон §7.1 называет UX отдельным разделом; в этом ТЗ его содержание разнесено между шапкой («Touch editor: not exposed») и §2 («Что человек увидит до и после»). Решение: снимается — задача не меняет ни одного интерактивного пути (только геометрия отрисовки тел стен), содержательно вопрос закрыт, отдельный заголовок был бы пустой формальностью.
Открытых продуктовых вопросов к владельцу нет и это обоснованно: контракт поведения продиктован самим владельцем в комментарии к issue (кандидат-алгоритм из тела issue почти буквально формализован в §8.2), формальные константы детектора отмечены как техническое предположение в §17 с направлением уточнения («только в сторону строгости»), стадийность демонтажа старых слоёв — там же, помечено как свободное для реализации техническое решение. Это редкий случай, когда молчание не является риском: сам факт задачи и её решение исходят от одного и того же человека.
Что проверено и корректно
- Соответствие SCOPE.md — задача в рамках мандата, не расширяет функциональность.
- Соответствие процессу — статус, класс изменения, трек, обязательные разделы, трейлеры/release-артефакты названы верно.
- Все технические идентификаторы, числа и ссылки на историю, на которые
опирается контракт §8, проверены на существование и точность прямым чтением
кода и
docs/WALL-THICKNESS.md, а не приняты на слово. - Контракт §8.2–8.4 логически замкнут: покрывает все перечисленные в §8.3
вырожденные случаи, не оставляет геометрического механизма для дыры между
соседними веерами (общая вершина — узел, дуги секторов покрывают полный
оборот), и делает объективно проверяемым единственное новое утверждение
(«нет дыр») через детектор с собственной самопроверкой на дырявой фикстуре
(мутант
hole-detector-blind). - AC9 корректно называет регрессионный периметр — все перечисленные смоки существуют и по названию действительно покрывают стыковую механику.
- Откат (§16), release-артефакты (§15) и риски golden-переснятия (§11.1) учитывают процессные уроки #230/#235 именно так, как того требует PROCESS.md.
Чего не проверял
- Я не запускал никакие гейты (
tsc,npm test,npm run build,golden:verify, смоки) — на этапе ревью ТЗ кода ещё нет, гейты этапа относятся к код-ревью (§2.7 PROCESS.md), а не к ревью ТЗ (§2.4). - Не проверял геометрию mitre/bevel численно (не строил прототип и не считал вручную пересечения офсетных прямых) — на этапе ТЗ это не требуется: контракт верифицируется исполнением на код-ревью через детектор §8.4 и golden, а не через ручной пересчёт геометрии ревьюером ТЗ.
- Не читал полностью весь
src/wall-thickness.ts(4145 строк) построчно — прочитаны и сверены только фрагменты, релевантные утверждениям ТЗ (сигнатуры функций, константы, точки вызоваwallBodiesUnionPath). - Не проверял содержание единственного комментария к issue построчно на предмет более ранних версий ТЗ — комментарий один, зафиксированное решение соответствует финальному ТЗ.
Итог
docs/specs/302-junction-node-material.md готово к переходу в S5-ready.
Продуктовая рамка ясна, контракт поведения проверяем объективным детектором и
golden-эталонами, риски демонтажа старого стека названы и покрыты
регрессионным периметром (AC9), технические предположения отделены от решения
и помечены как свободные к изменению.