19 KiB
SPEC-REVIEW-645-r2
Issue: #645 — «Plan editor: временно перемещать кнопку "Настройки комнаты", если она перекрывает элементы» (bug/polish, P2, полный трек — лёгкий трек аналитика отклонила: нарушен критерий §5 «нет нового UX-контракта», плюс задача трогает touch-контракт редактора). Заход: r2 · блокирующих циклов израсходовано 1 из 4.
Скоуп ревью
Предмет r2 — дельта к тексту ТЗ между r1 (жёлтый, M1+M2) и текущей редакцией
тела issue #645, а не текст целиком (PROCESS.md §2.10). Продуктовый код не
менялся: git log --oneline origin/dev..HEAD содержит только
76fc405b docs: review document for #645 (публикация документа r1), и
git diff --stat origin/dev...HEAD трогает исключительно
docs/reviews/INDEX.md и docs/reviews/SPEC-REVIEW-645-r1.md. Ни одного
файла класса A/B нет — это подтверждает и хендофф-комментарий автора
(«продуктовый код не менялся»). Диапазон origin/dev...HEAD для этого этапа
пуст по‑прежнему, разбирается только текст.
Материал: тело issue #645 на момент чтения (updated_at
2026-09-24T18:34:09Z, сразу после итогового комментария автора), метки
bug, P2, polish, S4-spec-review.
Как проверялось
- Найден вердикт и документ предыдущего раунда:
docs/reviews/SPEC-REVIEW-645-r1.md(жёлтый, High 0, Medium 2 — M1, M2), зафиксированный в дереве на76fc405bвместе с обновлениемdocs/reviews/INDEX.md. - Дельта объявлена по комментариям автора (
gh api repos/Matysh/houseplan-card/issues/645/comments): два новых комментария «Исправления по SPEC-REVIEW-645-r1» и «Сделано: …», оба датированы2026-09-24T18:34:0{6,7}Z, иupdated_atтела issue18:34:09Z— редакция тела произошла сразу после них, других правок текста между r1 и r2 не было. - Прочитано тело issue #645 целиком заново (раздел
## ТЗ, 258 строк) — не выборочно, чтобы отличить реальную правку от заявления автора «в тексте исправлено». - По каждой находке r1 показано, какой конкретный фрагмент текущего текста
её закрывает — см. «Закрытие раунда r1» ниже. Для M1 сверено дословное
совпадение добавленной строки с одним из трёх допустимых значений
docs/TOUCH-SUPPORT.md:221–223(Documentation rule). Для M2 повторно прочитан код, на который опирается находка, чтобы подтвердить, что он не менялся и предложенная формулировка контракта действительно закрывает именно эту связку:src/houseplan-editor-runtime.ts:3427—gearCenter: poleOfInaccessibility(poly)внутри_rszEdgeLabels, без условия на временную позицию — код идентичен цитате в SPEC-REVIEW-645-r1 (та же строка, тот же безусловный вызов).src/resize-labels.ts:25(ResizeAreaPlacementInput.gearCenter) иsrc/resize-labels.ts:97,113–116(gearScreen/overlapsпротивgearCenter) — сигнатура и использование параметра не изменились; значит контракт п.15 (единый эффективный центр для рендера кнопки и Resize-подписи) действительно закрывает разрыв, а не описывает уже исправленный код.
- Проверено, что новый AC11 и новый пункт «Затронутые модули»
(
src/resize-labels.ts) взаимно согласованы с планом автотестов (п.5 — «переместить кнопку… начать Resize стены… доказать, что подпись обходит фактическую капсулу») и с разделом «Риски» (новый пункт «live-подпись Resize может обходить старый автоматический центр… если render и Resize используют разные resolver» → явно назван закрытым AC11). - Проверено, что делта не переоткрывает ранее закрытые части r1: контракт
п.1–14, AC1–AC10, «Затронутые модули» (кроме добавленной строки),
«Не-скоуп», «Модель данных», i18n, «Производительность», «Откат»,
«Release-артефакты» текстуально не изменились относительно того, что
цитирует и разбирает
SPEC-REVIEW-645-r1.md(построчное сравнение с цитатами в разделе «Что проверено» этого документа). - Проверено на новую двусмысленность: не создаёт ли добавленный п.15 противоречия с п.11 (сброс временной позиции при изменении геометрии). П.11 регулирует финальную (закоммиченную) геометрию комнаты; п.15 явно говорит про preview-геометрию активного Resize «в этом же кадре» — разные моменты жизненного цикла, конфликта нет: если Resize отменяется без коммита, актуальная геометрия комнаты не меняется и валидность временной точки пересчитывается по-прежнему через п.11.
- Перечитан
docs/TOUCH-SUPPORT.mdцеликом ещё раз (Documentation rule, строки 214–226) — требуемый формат не изменился со времени r1.
Этап spec: тяжёлые/browser-гейты не запускались — код по-прежнему не
написан (см. п.1 «Скоуп ревью»), прогон tsc/test/build/
check-docs.mjs на этом этапе бессмыслен, диапазон класса A/B пуст.
Закрытие раунда r1
| Находка (r1) | Чем закрыта | Где это видно |
|---|---|---|
M1 — нет обязательной строки Touch editor: … из docs/TOUCH-SUPPORT.md |
Добавлена строка **Touch editor: best effort / intentionally degraded.** в начало раздела ### UX и доступность, дословно совпадает с одним из трёх допустимых значений |
Тело issue #645, раздел «UX и доступность», первая строка; docs/TOUCH-SUPPORT.md:222 — точное совпадение формулировки |
| M2 — Resize-подписи уклоняются от старого автоматического центра, а не от фактической (перетащенной) позиции кнопки; риск воспроизвести исходный дефект в паре «подпись ↔ кнопка» | Новый пункт контракта 15 требует единого эффективного центра для рендера кнопки и _rszEdgeLabels/placeResizeAreaLabel, явно запрещает обход «старого» poleOfInaccessibility(poly), определяет поведение при недопустимой preview-точке; src/resize-labels.ts добавлен в «Затронутые модули»; добавлен AC11 с доказательством unit + browser smoke; в «Риски» — явный пункт про расхождение resolver, закрытый AC11 |
Тело issue #645: контракт «15. Согласованность с Resize»; «Затронутые модули», строка про src/resize-labels.ts; «Критерии приёмки», AC11; «Риски», предпоследний пункт; «Принято предположительно», пункт про «место общего resolver эффективного центра» |
Обе находки r1 закрыты текстом ТЗ; новых пробелов при проверке закрытия не обнаружено (см. «Как проверялось», пп. 4–7).
Унаследовано из r1 (без повторной проверки)
Ниже — то, что дельта не задевает и что принимается по документу
docs/reviews/SPEC-REVIEW-645-r1.md (материал: тело issue #645 на момент
r1, код на 2b3959e55bcb139b6ad872a312ad212de36f44db, вердикт жёлтый,
High 0, Medium 2):
- Обоснованность полного трека (нарушенный критерий §5) и отсутствие дубликатов — из «Аналитики» автора, не менялось.
- Полнота обязательных разделов
PROCESS.md§7.1 (кроме добавленной строки Touch editor и пункта 15 — они дельта и перепроверены выше). - Точность фактических заявлений ТЗ о существующем коде:
_renderRoomGear(),poleOfInaccessibility(room.poly),.rlgearbtn/pointer-events: auto(src/houseplan-editor-runtime.ts:10276–10300), порог 3 CSS px в_pointerMoveNow(src/houseplan-card.ts:7031), существующий паттерн_suppressClick, наличиеpointInPolygonвsrc/logic.ts, терминологияroom.settings_title/room.settings_short(src/i18n/ru.json:765,800,docs/USER-GUIDE.ru.md:1621) — код с r1 не менялся (см. «Скоуп ревью»), переоснований для пересмотра нет. - Покрытие контракта п.1–14 критериями AC1–AC10 построчно (таблица в r1, раздел «Что проверено и корректно») — тексты пунктов 1–14 и AC1–AC10 не менялись.
- Оценка модели данных/миграции/i18n/производительности/отката/
release-артефактов как полных и корректных — тексты этих разделов (кроме
«Затронутые модули», куда добавлена одна строка про
resize-labels.ts) не менялись. - Отсутствие открытых продуктовых вопросов владельцу.
- Low-находка «не поднимаю отдельно» про
lostpointercapturevs штатныйpointerup(раздел «Чего не проверял» r1) — техническая, отнесена к «Принято предположительно», статус не изменился.
Находки
Находок нет — ни High, ни Medium, ни Low. Обе Medium-находки r1 закрыты (см. таблицу выше), новых пробелов делта не создала.
Что проверено и корректно
- M1 закрыта корректно: формулировка дословно совпадает с допустимым
значением
docs/TOUCH-SUPPORT.md, расположена в предметно верном месте (открывает «UX и доступность», рядом с остальными touch-оговорками), что и было предложено r1 как один из вариантов. - M2 закрыта содержательно, не формальной отпиской: выбран первый из двух вариантов, предложенных r1 («явно включить в скоуп»), с добавлением AC, правкой «Затронутые модули» и явным описанием поведения на границе (недопустимая preview-точка → синхронный откат кнопки и подписи на автоматический центр). Формулировка учитывает разницу между финальной и preview-геометрией (см. «Как проверялось», п.7) — типичная ошибка «просто добавили AC, не подумав о моменте применения» не воспроизведена.
- Новый AC11 однозначен и несёт способ доказательства (
unit placeResizeAreaLabel/resolver + browser smoke), согласован с пунктом 5 плана автотестов, который был обновлён синхронно с добавлением AC11. - Делта не тронула ничего вне заявленного двух-пунктового исправления:
сверка текста контракта 1–14, AC1–AC10, «Не-скоуп», i18n,
«Производительность», «Откат», «Release-артефакты» с цитатами
SPEC-REVIEW-645-r1.mdне выявила расхождений. - Продуктовый код действительно не менялся между r1 и r2 —
git diff --stat origin/dev...HEADсодержит только два файла документации (сама публикация r1), что делает «унаследовано без перепроверки» по коду формально обоснованным, а не предположением.
Чего не проверял и почему
- Реализацию — её по-прежнему нет; этап spec, код не написан.
npx tsc --noEmit/npm test/npm run build/node scripts/check-docs.mjs— не гонял: диапазон класса A/B пуст, прогон гейтов на этапе ревью ТЗ бессмыслен (§2.4 их не требует), это же было верно для r1.- Browser smoke / golden / инварианты модели / performance — код, который они бы проверяли, ещё не существует; план автотестов ТЗ (включая обновлённый п.5 про Resize-сценарий) оценён на реалистичность чтением, не исполнением.
- Полный повторный аудит всех разделов ТЗ «с нуля» — сознательно не
делал:
PROCESS.md§2.10 предписывает объём по дельте, когда дельта локальна (здесь — да: два точечных добавления, подтверждённых комментариями автора иupdated_at); неизменные разделы приняты из документа r1 с указанием SHA материала (раздел «Унаследовано из r1»). docs/CANVAS.md,docs/WALL-THICKNESS.md,docs/LIGHT.md,docs/SUN.md— не читал, как и в r1: не канонические документы для этой предметной области;resize-labels.tsзатрагивает геометрию Resize, но не эти подсистемы напрямую (нет собственной канонической страницы, кроме уже прочитанногоdocs/TOUCH-SUPPORT.md/docs/UX-MODES.md).
Материал раунда
- Issue: #645, метки на момент ревью:
bug,P2,polish,S4-spec-review. - ТЗ: раздел
## ТЗтела issue #645, редакция после правок r1 (updated_at:2026-09-24T18:34:09Z). - Комментарии, учтённые дополнительно к r1: «Исправления по
SPEC-REVIEW-645-r1» (
2026-09-24T18:34:06Z), «Сделано: внесены обе Medium-правки r1 в ТЗ…» (2026-09-24T18:34:07Z). - Рабочее дерево репозитория на момент чтения кода:
76fc405b2c6c566c8654019c373fa9fb4e878a18(HEAD, справочно — для проверки, что фактические заявления ТЗ о текущем коде и находка M2 по-прежнему опираются на неизменившийся код; продуктовый код между r1 и r2 не менялся). - Материал предыдущего раунда:
docs/reviews/SPEC-REVIEW-645-r1.md, вердикт жёлтый, High 0, Medium 2 (M1, M2), код на2b3959e55bcb139b6ad872a312ad212de36f44db.
Вердикт
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0
Обе Medium-находки r1 закрыты содержательно, без формальных отписок и без
новых пробелов (см. «Закрытие раунда r1»). Делта не переоткрывает ранее
принятые разделы. ТЗ готово к DoR/переходу в S5-ready.
Материал раунда
- Ветка:
issue/645-room-settings-button-drag, коммит76fc405b2c6c— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
ff8460bad9ebe36cd0bb9ebfe7eb75688a327997git log --all --format='%H %T' | grep ff8460bad9eb - Тело issue:
1cfefdd93db1946a31ecfd2bc15198fd49ae0e9031bd1b6b9751e50258aa0a46 - Вердикт конвейера:
green· High 0