Files
houseplan-card/docs/reviews/CODE-REVIEW-533-r3.md
T
2026-09-11 16:55:33 +00:00

12 KiB

Код-ревью #533 — заход r3

Материал: 11ccd5b0 (Ревью r2: лейблы доставки называют свой сценарий), рабочая копия на нём. Предыдущий вердикт — r2, жёлтый, на 73c13e37 (SHA автором явно не назван, найден по git log и телу issue). Дельта раунда: 73c13e37..11ccd5b0, один файл demo/smoke_room_resize.mjs, +4/-4. Диапазон origin/dev...HEAD в целом: demo/smoke_room_resize.mjs (+133/-64 суммарно за все три коммита) плюс два файла docs/reviews/CODE-REVIEW-533-r{1,2}.md, добавленные конвейером публикации. Продуктовый код не тронут — соответствует «Вне объёма» из ТЗ.

Дельта локальна: переименование двух меток без изменения логики, объём (4 строки) несопоставим с исходной задачей и не задевает новую подсистему. Разбор сокращён по дельте, но строгость — нет: помимо закрытия находки r2 проверено, что делта не сломала ничего из ранее принятого (полный прогон смока, а не только чтение диффа).

Закрытие r2

находка r2 чем закрыта где это видно
Medium: demo/smoke_room_resize.mjs:212 — блок aria-disabled-ручки (проверки safe_resize.disabled_*) обёрнут как sent('owner_boundary.pointerdown_sent', ...) строка 212 переименована в sent('disabled.pointerdown_sent', ...) git diff 73c13e37..11ccd5b0 — единственное изменение строки 212; подтверждено экспериментом ниже
Medium: demo/smoke_room_resize.mjs:263-265 — блок с проверками safe_resize.owner_boundary_* обёрнут как sent('range_role.*', ...) три строки 263-265 переименованы в sent('owner_boundary.pointerdown/pointermove/pointerup_sent', ...) тот же diff; подтверждено экспериментом ниже

Дельта — ровно эти 4 строки, других изменений в файле нет.

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

  1. Полный список меток sent() против соседних check(). Прочитал файл (grep -n "sent(\|check(") и сверил префикс каждой метки sent() со сценарием, к которому относится следующий за ней блок check():

    • safe_resize.down/move/up_sent → главный сценарий (safe_resize.drag_started, preview_moved...) — совпадает;
    • disabled.pointerdown_sent → safe_resize.disabled_* — совпадает (было owner_boundary, находка r2);
    • mixed_role.* → safe_resize.mixed_role_* — совпадает (не менялось в этой дельте);
    • owner_boundary.* → safe_resize.owner_boundary_* — совпадает (было range_role, находка r2);
    • corner_clamped.* → safe_resize.corner_clamped/corner_topology — совпадает;
    • preflight.* → safe_resize.preflight_* — совпадает;
    • commit_preflight.* → safe_resize.commit_preflight_* — совпадает;
    • cancel.* → safe_resize.cancel_* — совпадает. Все 23 метки теперь однозначно читаются глазами с красной строки раннера — заявленная цель правки достигнута полностью, новых несовпадений дельта не внесла.
  2. Исполнение, не только чтение. Локальный dist был устаревший (демо не грузилось — EXC Failed to fetch dynamically imported module), выполнил npm run bundle:sync (tsc --noEmit && rollup -c + копирование в demo/srv/assets). После этого node demo/smoke_room_resize.mjs — зелёный (OK), mapping_stable сошёлся, safeResizeResult верный.

  3. Дисциплина «тест должен уметь падать» — по обеим переименованным меткам.

    • Сломал цель pointerdown в disabled-блоке (cx/cy: 331,245 → 999,999, строка 212): смок покраснел ровно на disabled.pointerdown_sent: expected true, got false — метка называет тот сценарий, который действительно сломан. Файл восстановлен (git status чист после проверки).
    • Аналогично сломал pointerdown в owner_boundary-блоке (строка 263): покраснело owner_boundary.pointerdown_sent (и, ожидаемо, зависимая геометрическая проверка safe_resize.owner_boundary_clamped) — снова верная метка. Файл восстановлен. Это ровно тот эксперимент, которым r1 и r2 добывали находки, применённый к обеим точкам правки r3 — до фикса эти же эксперименты давали красную строку с чужим именем сценария.
  4. Трейлеры. Issue: #533, User-Visible: no — верно: правка не продуктовая и не пользовательская, ченджлог не требуется.

Унаследовано из r2

Документ r2: docs/reviews/CODE-REVIEW-533-r2.md, вывод получен на 73c13e37.

  • AC1 (перевод координат в момент события, доставка проверяется у всех 22/23 вызовов pointer()) — принято без повторной проверки логики перевода; дельта r3 не касается ни pointer(), ни screenPt-эквивалента, только строковые литералы аргумента sent().
  • AC2 (safe_resize.mapping_stable, допуск 1e-6, диагностика в имени) — принято без повторной проверки; дельта не касается расчёта scale. Пересмотрено лишь мимоходом — прогон смока в п.2 выше подтвердил mapping_stable сходится и на текущем SHA.
  • AC3 (мутанты safe-resize-commit-preflight-bypassed и resize-preview-reject-silent по-прежнему ловятся; Validate зелёный) — принято по ссылке на Validate 11ccd5b0: https://github.com/Matysh/houseplan-card/actions/runs/34624024169 (success), названной в постановке этого раунда. Сам мутационный прогон в r3 не повторял — дельта (переименование строковых литералов) не может повлиять на срабатывание мутанта, который проверяет обход preflight-заслона в продуктовом коде.

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

  • Обе находки r2 закрыты именно тем способом, который был предписан («переименовать две строки-лейблы, без изменения логики») — диффом это ровно 4 изменённые строки, логика (pointer(), координаты, pointerId, значения nudge) не тронута.
  • Полный список меток самосогласован — других расхождений имя/сценарий в файле нет (проверено по всем 23 меткам, не только по двум починенным).
  • Продуктовый код и любые другие файлы в дельте не участвуют — git diff --stat origin/dev...HEAD показывает только demo/smoke_room_resize.mjs и артефакты предыдущих ревью.
  • Трейлеры корректны, ченджлог обоснованно не тронут.

Гейты: что прогнал, что нет и почему

  • npx tsc --noEmit, npm test, npm run build — не перегонял отдельно: Validate зелёный на этом самом SHA 11ccd5b0 (https://github.com/Matysh/houseplan-card/actions/runs/34624024169), названо в постановке раунда как уже подтверждённое. npm run build фактически выполнился как часть npm run bundle:sync, понадобившегося для локального прогона смока, и прошёл без ошибок.
  • node scripts/check-docs.mjs — не запускал: diff не трогает src/**.
  • Инварианты модели (npm run invariants) — не запускал: diff не трогает геометрию, layout, marker.space, open_spans ни в каком виде — это переименование строковых меток в тестовом свидетеле.
  • demo/smoke_room_resize.mjs — прогнан целиком дважды (чистый прогон и после двух точечных «порч» с восстановлением), это единственный смок, которого касается diff, и AC3 требует именно его.
  • node scripts/smoke-select.mjs — не запускал отдельно: единственный тронутый файл — сам смок-свидетель, других смоков в выборке для этой дельты быть не может.
  • npm run golden:verify — не запускал: diff не меняет рендер/геометрию/стили/слои, только тестовый скрипт.
  • python -m pytest tests_backend -q — не запускал: custom_components/**/*.py не тронут.
  • Perf-профили — не запускал: не названы в AC, чувствительные к перфу пути не тронуты.

Вывод

Обе находки r2 закрыты корректно, точечно и без побочных эффектов. Новых находок в дельте r3 нет. AC1–AC3 наследуются из r1/r2 без пересмотра логики (дельта их не задевает) и подтверждены заново только там, где дельта дотягивается: полный зелёный прогон смока и негативные эксперименты на обеих переименованных метках.

Вердикт: зелёный.


Материал раунда

  • Ветка: issue/533-resize-witness-mapping, коммит 11ccd5b09548 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: a1646075cce15fa130d1513e88bf776bdc34a169
    git log --all --format='%H %T' | grep a1646075cce1
    
  • Тело issue: ae465893153dbb7ba1b9d991e2d5cf4a05c8f526b51ae2f2b74e6e2c566805d9
  • Вердикт конвейера: green · High 0