Files
houseplan-card/docs/reviews/SPEC-REVIEW-289-r2.md
T
2026-08-24 15:19:20 +03:00

14 KiB
Raw Blame History

SPEC-REVIEW-289-r2

  • Issue: https://github.com/Matysh/houseplan-card/issues/289
  • Артефакт ТЗ: docs/specs/289-no-mixed-role-resize.md
  • Ветка/коммит: issue/289-no-mixed-role-resize @ e02c282d (origin/dev + 2 коммита сверх r1: 1dae3b0c — документ ревью r1, e02c282d — правки автора; подтверждено git diff origin/dev..HEAD --stat — только два docs-файла, продуктовый код не тронут)
  • Заход: r2 · блокирующих циклов израсходовано 1 из 4
  • Вердикт: зелёный · High: 0 · Medium: 0 · Low: 1 (снят с запиской, не блокирует)

Скоуп ревью

Раунд r1 (см. docs/reviews/SPEC-REVIEW-289-r1.md, коммит 5e169f48) дал жёлтый вердикт: High 0, Medium 3 (M1 «Риски» отсутствует, M2 «Откат» отсутствует, M3 — 6 из 9 AC без способа доказательства), Low 2 (L1 терминология «рукоятка»/«ручка», L2 — i18n-ключ не назван буквально). Технический контракт §2–§4, AC1–AC9 по существу и границы скоупа §5 в r1 уже признаны корректными точным чтением кода и канона. Автор ответил правками в e02c282d («докcs: add evidence and rollback to resize spec») и сообщил в issue, что внёс все три Medium.

Эта дельта — предмет r2: git diff 5e169f48..e02c282d -- docs/specs/289-no-mixed-role-resize.md. Дельта локальна (добавление разделов и строк «Доказательство», без изменения самого контракта, AC-формулировок или скоупа) — полный повторный разбор продукта не требуется, объём разбора сокращён до делты и её последствий.

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

  1. Нашёл вердикт r1 в комментариях issue #289 (комментарий от 2026-08-24 10:48:29) и SHA, на котором он получен. В самом комментарии-вердикте SHA не назван — по инструкции это сигнал для проверки; но опубликованный документ docs/reviews/SPEC-REVIEW-289-r1.md:5 называет его явно: 5e169f48. Ложной тревоги нет, SHA подтверждён.
  2. git diff 5e169f48..e02c282d -- docs/specs/289-no-mixed-role-resize.md — построчно, каждый добавленный/изменённый хунк сверен с тем, какую находку r1 он должен закрывать (таблица ниже).
  3. git diff 5e169f48..e02c282d --stat (весь коммит, не только spec-файл) — подтвердил, что в дельте нет ничего кроме ожидаемого: сам spec-файл плюс документ ревью r1 (публикация предыдущего раунда, не предмет этого ревью).
  4. Пересчитал нумерацию разделов файла целиком (grep -n "^## [0-9]") — после вставки §8/§9 разделы 8–12 сдвинулись; последовательность 1…12 без пропусков и дублей, внутренних ссылок §N на старые номера в файле нет — реформат не оставил битых ссылок.
  5. Проверил заявление о каноническом термине: docs/USER-GUIDE.ru.md (раздел Resize, таблица сценариев) называет элемент управления «Ручка», слова «рукоятка» в проекте вне этого ТЗ нет — сверил актуальное количество вхождений в текущей редакции файла (grep -ni), а не унаследовал цифру из текста r1.
  6. Не прогонял typecheck/test/build/инварианты — git diff origin/dev..HEAD --stat показывает только два docs-файла (docs/specs/289-*.md, docs/reviews/SPEC-REVIEW-289-r1.md), продуктового кода на ветке всё ещё нет. Гейты класса A/B неприменимы к чисто документационному изменению на этапе ТЗ — тот же вывод, что и в r1, дельта его не меняет.

Закрытие раунда r1

Находка r1 Чем закрыта Где это видно
M1 — раздел «Риски» отсутствует полностью Добавлен раздел «8. Риски и меры»: три риска (чрезмерно строгий ownership → ложный disable легитимных жестов; чрезмерно мягкий → возврат mixed-role; расхождение owners между preview и commit), каждый со ссылкой на конкретный AC-барьер (AC3/AC4, AC1/AC5/AC8, AC6) docs/specs/289-no-mixed-role-resize.md:210-218
M2 — раздел «Откат» отсутствует полностью Добавлен раздел «9. Откат»: явно зафиксировано «чистый revert коммита», без флага/миграции, обосновано неизменностью persisted geometry/schema — то самое тривиальное решение, которое r1 предсказал, но потребовал записать явно docs/specs/289-no-mixed-role-resize.md:220-223
M3 — 6 из 9 AC (AC1–AC6) без способа доказательства Каждому AC1–AC6 добавлена строка «Доказательство: …» с конкретным инструментом (unit в test/resize.test.mjs, production-bundle smoke, scripts/model-invariants.mjs) — по одной на каждый docs/specs/289-no-mixed-role-resize.md:120-121,129-130,139-140,151-152,161-162,171-172
L2 — i18n-ключ не назван буквально В разделе «Ожидаемые файлы» ключ resize.disabled.partial-shared назван по имени, а не только как значение reason docs/specs/289-no-mixed-role-resize.md:231-232
L1 — «рукоятка» вместо канонической «ручка» Не исправлено. В §2 (строка 35) и §3 (строка 44) слово «рукоятка» осталось; правки касались только новых разделов и не задели прозу §2/§3 docs/specs/289-no-mixed-role-resize.md:35,44

Уточнение по L1: текст r1 указывал «использовано 5 раз (§2, §3, §4.2×3)» — это не подтвердилось. В §4.2 (строки 64–78) на самом деле используется английское слово handle (та же RU/EN смесь технических терминов, что и у «moving edge»/«side edges» по всему документу, которую сам r1 признал соответствующей канону), а не «рукоятка». Фактическое количество вхождений слова «рукоятка» в редакции 5e169f48 и в текущей e02c282d одинаково — 2, не 5, и дельта r2 в этом месте нулевая. Обе строки чисто описательные (не согласованный с владельцем disabled-текст AC2, который дословно совпадает с решением владельца и не содержит «рукоятка»/«ручка»). Расхождение с каноническим термином реально, но не влияет на реализуемость или проверяемость ни одного AC — снимаю как Low с запиской, не требую четвёртого цикла ради двух слов в прозе.

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

Без повторной проверки в r2 принято на основании docs/reviews/SPEC-REVIEW-289-r1.md (документ на SHA 5e169f48), так как дельта 5e169f48..e02c282d не касается этих утверждений:

  • Технический контракт §1/§4 (ownership-модель, запрещённая смена роли, thickness preservation) — соответствие resolveSafeResize()/ validateSafeResize() в src/resize.ts подтверждено чтением кода в r1; дельта не меняет ни одной строки §1/§4.
  • Симметричность контракта §4.2 (оба направления жеста небезопасны в exact-репро, mixed-role у соседней комнаты при укорачивании) — геометрически проверено в r1; текст §4.2 не менялся.
  • AC1–AC9 по существу (что каждый критерий требует) — проверено в r1 построчно против кода и канона; дельта добавила только строки «Доказательство:», не изменив ни одной формулировки требования.
  • Существование и семантика инструментов: checkMixedRoleRecords, checkWallRecordsPreserved, checkWallKeys, checkReferences, checkPhysicalGeometry (scripts/model-invariants.mjs), resize.disabled.partial-shared и resize.commit_failed (оба i18n-файла) — подтверждено чтением исходников в r1, дельта их не касается.
  • Границы скоупа §5 (не входит: разрез записи, смена толщины, каскад топологии, рефактор #264, ретро-починка через Optimize, #288, #290) — сверено с историей issue в r1, текст §5 не менялся.
  • Продуктовое решение §2 соответствует ответу владельца на Q1 — сверено в r1 слово в слово, текст §2 (кроме уже учтённого L1) не менялся.
  • Совместимость §7 (schema/model version не меняются, touch — best effort, безопасный pointermove-путь) — сверено в r1 с docs/CONFIG-COMPATIBILITY.md и docs/TOUCH-SUPPORT.md, текст §7 не менялся.

Что проверено и корректно в этом раунде (не находка, а подтверждение)

  • Все три Medium из r1 закрыты предметно, а не декларативно: каждая правка — конкретный текст в конкретной строке, а не общая фраза «риски учтены» (проверено построчным диффом, см. таблицу выше).
  • Реформат нумерации разделов (8→10, 9→11, 10→12) не оставил битых внутренних ссылок и не изменил порядок обязательных по §7.1 PROCESS.md разделов.
  • Раздел «Риски» не декоративен: каждый из трёх рисков привязан к конкретному AC-барьеру, который его закрывает, а не общей фразой «риски будут обнаружены на код-ревью».
  • Раздел «Откат» согласован с остальным документом: «schema/model version не меняются» из §7 и «persisted-данные не переписываются» из §4.3 — одно и то же утверждение, не новое допущение, придуманное только для раздела 9.

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

  • Продуктовый код и тесты — на ветке их всё ещё нет (git diff origin/dev..HEAD --stat показывает только два docs-файла); гейты typecheck/test/build/ invariants/смоки неприменимы на этапе ТЗ, как и в r1.
  • Всё, что унаследовано из r1 и перечислено выше отдельным разделом, — не перепроверялось повторно, так как дельта его не задевает.
  • Формулировка Low L1 не эскалирована владельцу — это стилистическая правка внутри уже принятого текста, не продуктовый вопрос.

Итог

High: 0. Medium: 0 — все три Medium-находки r1 закрыты предметно в e02c282d. Low: 1 из двух устранён (L2), один (L1, «рукоятка»/«ручка») остаётся, но снят решением ревьюера с запиской: расхождение только в описательной прозе §2/§3, не в согласованном с владельцем disabled-тексте AC2, и не влияет на реализуемость ни одного AC. Технический контракт, AC1–AC9 и границы скоупа наследуются из r1 без повторной проверки (дельта их не касается). ТЗ готово к разработке.