Files
houseplan-card/docs/reviews/SPEC-REVIEW-521-r1.md
T
2026-09-10 18:49:42 +00:00

17 KiB
Raw Blame History

SPEC-REVIEW — issue #521 — заход r1

Этап: S4-spec-review (PROCESS.md §2.4) · Трек: полный (нарушен критерий §5 «нет влияния на производительность и на touch-контракт», названо самим автором) · Заход: r1 (первый) · Бюджет циклов: 0/4 израсходовано до этого вердикта.

Скоуп ревью

Материал — тело issue #521, раздел ## ТЗ (артефакт по решению владельца 2026-09-10, #517; docs/specs/ архивирован, новый файл не создаётся). Тема: регресс направляющих выравнивания (.alignline/.aligndot, слой .alignguides) во всех трёх живых жестах редактора (devices, decor, plan) после перевода взаимодействия на «живой» путь src/live-editor.ts (#451, c0d61ca3). Задача — вернуть направляющие в живой шаблон, перевести точку выравнивания устройства на живую позицию, подавить дублирующий осевой слой и переписать свидетеля на настоящие PointerEvent вместо фабрикации _deviceDrag/_decorDraft.

Продукт: docs/SCOPE.md J6 («keep the plan true… drag/resize»), персона — администратор дома, поверхность — три десктопных редактора (референсная среда по docs/TOUCH-SUPPORT.md, строки 23–25, процитированы в ТЗ верно).

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

Ревью только по тексту ТЗ — продуктового кода не менял, ничего не запускал (этап spec, гейты код-ревью здесь не применяются). Проверено:

  • полный текст тела issue #521 и оба комментария (аналитика S2, хендофф «ТЗ готово — на ревью») — оба от Matysh, второй такой аккаунт объясняется ролью владельца/публикующей автоматизации в этом репозитории, не находка;
  • docs/SCOPE.md, PROCESS.md §§1–10, AGENTS.md, docs/TOUCH-SUPPORT.md, docs/USER-GUIDE.ru.md (полнотекстовый grep на align, выравнивани, направляющ, магнит, пунктир, точка-якор — см. находку ниже), docs/CANVAS.md, docs/STYLING-HOOKS.md;
  • сверка каждого технического утверждения ТЗ с текущим кодом на dev (c50bc725), чтобы отличить корректную диагностику от догадки:
    • src/live-editor.ts:273-285 (editorTemplate) — подтверждено: режим devices не входит ни в одну ветку и возвращает nothing; decor рисует _renderDecorLayer/_renderBackdropFrame/_renderTextFrame без направляющих; plan через planTemplate тоже не рисует .alignguides;
    • src/houseplan-card.ts:12892-12895 (_alignPoint, режим devices) — подтверждено: путь через this._pos(d), не _livePos;
    • src/houseplan-card.ts:11698-11701 — подтверждено: осевой слой направляющих и слой разметки используют один и тот же класс .hp-editor-only-layer;
    • src/live-editor.ts:342-354 (paintHouseplanEditor) — подтверждено: подавление .hp-editor-only-layer:not(.hp-plan-snap-layer) сегодня выполняется только в ветке _mode === 'plan'; для decor гасятся лишь .dtframe, .backdropframe, для devices не гасится ничего — контракт п.3 действительно требует новой работы, а не переиспользования;
    • src/houseplan-editor-runtime.ts:11282-11300 (_renderAlignGuides) — подтверждено: классы alignguides/alignline/aligndot существуют ровно в заявленном виде;
    • demo/smoke_align_guides.mjs:38-43,55-57,71 — подтверждено: сценарии devices/decor присваивают c._deviceDrag = {…} / c._decorDraft = {…} напрямую и зовут c.requestUpdate(), ровно то, что ТЗ называет фабрикацией; сценарий #400 (devGuideComesFromAnotherMarker) и noneInView действительно уже существуют — AC7 не выдумывает новых гарантий;
    • package.json — benchmark:large-house-interaction и benchmark:compare существуют; demo/performance/budgets-large-house-interaction.json существует — профиль в AC9 назван верно и соответствует правилу PROCESS.md §8/#473 (правка houseplan-card.ts/src/live-* → профиль large-house-interaction-v1);
    • demo/smoke_isometric_live_touch.mjs, demo/smoke_touch_tips.mjs — существуют, ссылка в разделе «Риски» точна;
    • установленный паттерн настоящих PointerEvent в других смоках (smoke_decor.mjs, smoke_active_chain_ink.mjs и др.) — подтверждает, что требование AC1–AC4 «настоящий жест» технически осуществимо, не фантазия.

Находки

Medium — заявленный источник поведения не существует в названном документе

Файл: тело issue #521, раздел ## ТЗ → ### Продуктовая рамка.

Формулировка: «Ничего нового не появляется: восстанавливается ровно то поведение, которое описано в docs/USER-GUIDE.ru.md для выравнивания.» Это утверждение о задокументированном поведении, поданное как факт, не помеченное как предположение.

Почему это находка. Полнотекстовый поиск docs/USER-GUIDE.ru.md (2241 строка) по align, выравнивани, направляющ, точка-якор, пунктир (в контексте выравнивания) даёт ноль совпадений на первые три запроса — направляющие выравнивания (дашированная линия + точка-якорь при перетаскивании значка/фигуры/курсора) в этом документе не описаны вовсе, ни под этим именем, ни под каким-либо другим. Раздел «Редактор устройств» (строка 977) описывает только привязку центра маркера к узлу сетки, но не визуальную направляющую к другому значку. Раздел про декор (строка 1502) описывает «лёгкий магнит к углам, серединам, центрам и рёбрам» — это про геометрический магнит подложки, а не про то, что пользователь видит (линию/точку), и явно исключает устройства из целей магнита («устройства… не являются целями магнита» — что не то же самое, что и «направляющая от устройства к устройству»).

AGENTS.md («Read this first») требует ровно обратного для видимых изменений: «interface wording comes from there and is not invented, or the UI starts speaking developer» — то есть ссылка на USER-GUIDE.ru.md в ТЗ должна быть проверяемой, а не общим местом.

Существенно, но не блокирует. Само восстанавливаемое поведение не выдумано — оно подтверждается независимо: кодом (_renderAlignGuides, .alignline/.aligndot, исключение перетаскиваемого маркера по #400, существующий до регрессии смок) и собственным измерением владельца в комментарии S2 на живых pointerdown/pointermove. AC1–AC9 не опираются на эту фразу — они проверяемы сами по себе, независимо от того, где именно описано прежнее поведение. Поэтому находка не про то, что контракт неверен, а про то, что ТЗ ссылается на несуществующий источник вместо корректного («восстанавливает поведение, вывезенное #451 и подтверждённое диагностикой в этом же issue» — так и есть на самом деле).

Чем закрывается. Правка одной фразы в «Продуктовая рамка»: убрать ссылку на docs/USER-GUIDE.ru.md либо заменить её на точную (код/тесты/коммит c0d61ca3/диагностика в issue). Технической правки контракта, AC или кода не требует.

Что проверено и признано корректным

  • Диагноз и причинность. Оба слома (слой не рисуется в живом шаблоне; _alignPoint читает замороженный _pos вместо _livePos) подтверждены построчно в текущем коде, независимо от текста ТЗ.
  • Контракт п.1–п.6 — каждый пункт технически осуществим, ни один не описывает несуществующий API; ссылки на существующие _renderAlignGuides(), _livePos, scheduleHouseplanEditor, makeTransparent точны.
  • Продуктовая рамка (без обсуждаемой находки) отвечает на оба обязательных вопроса §7.1: персона/поверхность/момент и что человек увидит до/после, без терминов реализации.
  • AC1–AC9 — каждый однозначен и называет способ доказательства (смок- сценарий или performance-профиль) и мутацию/пробу, от которой он краснеет; таблица «AC · чем доказан · чем краснеет» заполнена по всем девяти пунктам без пустых ячеек — требование #435 (в применении к будущему код-ревью) выполнимо уже на этом ТЗ.
    • AC6 (один расчёт кандидатов на кадр) — механизм, а не наблюдаемое поведение; автор сам вынес это на спор в комментарии «ТЗ готово». Считаю обоснованным: это единственная защита от перф-регресса, ради устранения которого #451 и вводил живой путь, и у него есть доказательство и мутация. Не меняю.
    • Ссылки на существующие мутанты/сценарии для AC7 (#400, noneInView) подтверждены как реально существующие, не выдуманные заново.
  • Откат — один revert, данных/конфига/публичных контрактов не касается; соответствует тому, что диагноз описывает чисто рантайм-регрессию.
  • Release-артефакты — User-Visible: yes с текстами обоих changelog названы дословно; фактический прирост пользовательской ценности («вернули то, что было») сформулирован без придуманной новой функциональности.
  • Перф и touch — раздел «Риски» называет ровно то, что требует чек-лист DoR (§2.5): влияние на производительность (AC9 + риск «кадр жеста») и на touch (существующие touch-смоки должны остаться зелёными) — не «нет влияния», а явно описанный риск с проверкой, что и требуется при нарушенном критерии small.
  • Объём задачи (все три жеста в одной issue). Это ровно тот вид продуктового вопроса, который решает владелец (§7.1: «какой объём видимых изменений входит в этот issue»), и автор задал его в установленной форме — что неясно, дефолт, приглашение возразить — без блокировки статуса. Это не нарушение процесса: жёсткая блокировка нужна для вопросов, без ответа на которые писать ТЗ нельзя, а здесь дефолт обоснован (общая причина, общий слой) и обратим (владелец может разделить после чтения).

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

  • Не запускал tsc/test/build/смоки — на этапе spec-review код ещё не писан, гейты §8 к этому этапу не относятся; они предмет код-ревью.
  • Не проверял, действительно ли добавление подавления .hp-editor-only-layer для режимов devices/decor (которого сегодня нет — см. «Как проверялось») реализуемо без дополнительных побочных эффектов на другие слои того же класса (hp-editor-only-layer также несёт _renderMarkupLayer для режима plan) — это станет предметом код-ревью и AC5 там же.
  • Не оценивал, войдёт ли новая механика тестового счётчика «осевых циклов» (нужна для AC1/AC3/AC4/AC6, готового счётчика в продукте сегодня нет — есть только _liveEditorPaintCount, который считает живые, а не осевые перерисовки) в бюджет test/**/demo/** без нового продуктового кода — технический вопрос авторской реализации, не продуктовая неоднозначность.
  • Не связывался с владельцем по вопросу объёма (все три жеста в одной задаче) — автор уже задал его в тексте в установленной форме; повторный запрос от ревьюера был бы дублированием.

Вердикт

Единственная находка — Medium, в скоупе задачи (текстовая правка одной фразы в теле ТЗ), без High. По PROCESS.md §2.4/§4 это жёлтый вердикт: автор правит ТЗ, фикс проходит следующий заход ревью по дельте (§2.10).

Вердикт: жёлтый · заход r1 · блокирующих циклов 1/4 · High: 0 · Medium: 1 → в задаче


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

  • Ветка: dev, коммит c50bc725c895 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 75ed6503e9310b9c7f0971f82a69d361a4eaee4a
    git log --all --format='%H %T' | grep 75ed6503e931
    
  • Тело issue: bf26b17118240771206ed2a7f26f10c82783ea586679def63cbc17e538c38cfe
  • Вердикт конвейера: yellow · High 0