Files
houseplan-card/docs/reviews/SPEC-REVIEW-277-r2.md
T
2026-08-24 06:31:15 +03:00

149 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-277-r2
- **Issue:** https://github.com/Matysh/houseplan-card/issues/277
- **Этап:** ТЗ на ревью (PROCESS.md §2.4)
- **Заход:** r2 · блокирующих циклов израсходовано 1 из 4
- **Документ ТЗ:** `docs/specs/277-safe-resize.md`
- **HEAD ревью:** `4ed94a52c9eaaf062ab033f6325e4bee8964bb41`
## Скоуп раунда
r2 — не полный повторный разбор, а разбор по дельте (PROCESS.md §2.10,
issue #214).
1. **Вердикт r1:** жёлтый · High 0 · Medium 3 (M1, M2, M3), опубликован в
`docs/reviews/SPEC-REVIEW-277-r1.md`, комментарий
https://github.com/Matysh/houseplan-card/issues/277#issuecomment-5389 (id
`IC_kwDOTOcLQM8AAAABQUJ7Dw`).
2. **SHA r1 не назван в вердикте** — это находка процесса, зафиксирована ниже
как L1. Восстановлен по дереву: последний коммит спеки перед коммитом
ревью-документа — `6436eafb3022bb53e58c6f89bdf7be53b16ce052` («docs: specify
safe fixed-topology resize», 2026-08-24 04:50:51+03:00); ревью-документ
`docs/reviews/SPEC-REVIEW-277-r1.md` добавлен отдельным коммитом
`4a16ddeb` в 01:59:09 UTC того же дня. Значит r1 разобран на
`6436eafb`.
3. **Дельта:** `git diff 6436eafb..4ed94a52 -- docs/specs/277-safe-resize.md`
— единственный коммит `4ed94a52` («docs: address safe resize spec
review»), 31 добавленных строки, 0 удалённых, правки только в
`docs/specs/277-safe-resize.md`. Диапазон затронутых участков: новый
подраздел «Что человек увидит до и после» в §1, новый раздел «12.1. Риски и
меры», новый AC17 и три новых пункта плана тестов в §16, новый пункт 6 в §18
«Принятые технические предположения».
4. **Не тронуто дельтой:** §2 (решения владельца, Q1/Q2), §3–§11 (термины,
eligibility, non-shared/shared transform, stops, preview/commit,
удаляемое поведение, скоуп/не-скоуп), §12 (архитектура, без счёта рисков),
§13–§15 (перформанс, touch, AC1–AC16 кроме новой AC17), §17 (release-
артефакты/rollback). Класс изменения — C (`docs/**`), диапазон не задевает
`src/**`, поэтому дешёвые гейты (`typecheck`/`test`/`build`) и
`check-docs` не запускались — как и в r1, ровно по тому же основанию (диф
не содержит кода).
Дельта локальна (не ребейз на ушедший вперёд `dev`, не смена контракта
поведения, не новая подсистема, объём — 31 строка против 322 исходных) —
полный повторный разбор не требуется по правилу §2.10 «разбор остаётся
полным, если...». Разбирались только: (а) закрытие M1–M3 построчно, (б) все
AC/разделы, которые дельта физически задевает — §1 сценарий, §12.1, AC17,
§16, §18.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** — нет раздела «риски», не назван риск параллельной работы над #264/#276/#278 | Добавлен раздел «## 12.1. Риски и меры» — таблица из 10 строк риск/мера. Отдельно назван риск #264 («второй controller boundary») с мерой «#264 не начинается параллельно, после #277 обязан rebase и refactor-only parity» и риск #276/#278 («меняют соседние geometry helpers») с мерой «порядок merge #276 → #277 → #278». | `docs/specs/277-safe-resize.md:252-265` |
| **M2** — нет фразы «что человек увидит до/после» без терминов реализации; §1 целиком на терминах `room polygon`/`vertex`/`segment` | Добавлен подраздел «### Что человек увидит до и после» с двумя пользовательскими предложениями («До: … стена может стать визуально толще или тоньше…»; «После: выбранная стена двигается, а всё остальное на плане остаётся как было; … стена видимо упирается…»). Формулировка почти буквально повторяет пример из вердикта r1. | `docs/specs/277-safe-resize.md:29-36` |
| **M3** — из «Обязательных тестов» issue выпал пункт про анонимизированную before/after fixture реального плана; ни один AC на него не ссылался | Добавлен AC17 (fixture provenance test + production-bundle smoke + model invariants), три новых пункта плана тестов про `test/fixtures/resize-safe-regression.json` (минимизация/анонимизация, provenance-комментарий, smoke проигрывает исходную последовательность жестов, а не подставляет готовый after), новая строка риска в §12.1 («Thickness/open spans расходятся при переносе… реальная fixture AC17») и новый пункт 6 в §18, явно решающий, как реальная fixture попадает в репозиторий без утечки пользовательских данных. | `docs/specs/277-safe-resize.md:261, 284-320, 352-353` (AC17: строка 304) |
Все три Medium закрыты по существу, а не декларативно: каждая правка — новый
текст, читаемый построчно, а не ссылка на намерение автора.
## Находки нового раунда
**L1 (Low, снята с записью).** Новое пользовательское предложение из M2
(«…и рядом с её handle написана причина», `docs/specs/277-safe-resize.md:36`)
использует непереведённое `handle` в ровно том месте, которое по требованию
AGENTS.md/PROCESS §7.1 должно быть «одной фразой без терминов реализации».
`docs/USER-GUIDE.ru.md` уже знает русский термин для точно такого
UI-элемента — «ручка» (угловые/поворотные ручки подложки и линии,
`docs/USER-GUIDE.ru.md:1133,1138,1161,1203`), а «маркер» в этом документе занят
под значок устройства (`docs/USER-GUIDE.ru.md:60` и далее) и был бы
двусмысленным выбором. Слово `handle` в технических разделах (§2, §4) не
проблема — это внутренний рабочий термин спеки, ровно как и в r1, где
терминология была сверена с `RESIZE.md` и признана согласованной. Проблема
только в новой пользовательской фразе.
Не блокирует: единственное слово, не меняет ни один AC и не создаёт
неоднозначности пользовательского сценария — оба соседних предложения того же
абзаца уже сформулированы по-русски и понятны без перевода термина. Снимаю
Low с записью: при следующей правке файла заменить `handle` на `ручка` (или
иной согласованный с `USER-GUIDE.ru.md` термин) в пользовательском абзаце;
блокирующего цикла ради одного слова не открываю.
**L2 (Low, процессная, снята с записью).** Вердикт r1 не называл SHA, на
котором получен (см. п.2 «Скоуп раунда» выше) — ровно тот случай, который
PROCESS.md §2.10 прямо называет находкой. Восстановлен однозначно по времени
коммитов, дельта от восстановленного SHA не оставляет разночтений, отдельного
возврата не требует. Отмечаю для инфраструктурного шага публикации: вердикт
код/спец-ревью должен называть SHA явно.
Ни одной находки, задевающей продуктовое поведение, AC или проверяемость, в
дельте не найдено.
## Что проверено и корректно (сверх закрытия r1)
- AC17 однозначен и проверяем: падение теста возможно (не сохранены walls/
extras/openings либо `global wall-null` — конкретные, механически
проверяемые инварианты), способ доказательства назван (fixture provenance
test + production-bundle smoke + model invariants), нет догадки, выданной за
решение — двойной исход «либо безопасно завершает жест, либо clamp/disabled»
сознательно оставлен открытым, потому что сама природа воспроизводимого
бага (старый Resize допускал небезопасный ход) не позволяет заранее
утверждать, какой из двух исходов даст новый безопасный контракт именно на
этой fixture — и это явно не продуктовый вопрос, а технический, решённый
автором, не переброшенный владельцу.
- §18 п.6 корректно ставит границу «assumed, change freely»: реальная fixture
обязательна, но публикуется только после минимизации/анонимизации — это
прямое согласие с телом issue («Реальный экспорт исследован локально и не
публикуется из-за пользовательских данных») и не оставляет открытого
продуктового вопроса.
- Риск-таблица §12.1 не расходится с §18 п.5 и с телом issue: порядок
«#276 → #277 → #278» упомянут дважды одинаково, никакой новой
зависимости от #264 не введено (наоборот, зависимость явно исключена).
- Новый текст не расширяет и не сужает скоуп/не-скоуп (§10/§11 не менялись),
не переопределяет ни одного из AC1–AC16, не противоречит решениям владельца
по Q1/Q2 (§2, не тронуто дельтой).
## Унаследовано из r1
Разделы, которые дельта не затронула, и AC, чьё доказательство дельта не
меняет, приняты без повторной проверки в этом раунде — на основании
`docs/reviews/SPEC-REVIEW-277-r1.md`, разобранного на SHA `6436eafb`:
- Q1/Q2 (§2) закрыты точно по решению владельца, без угадывания.
- AC1–AC16 однозначны, у каждого указан способ доказательства.
- Технические ссылки на текущий код (`applyRoomScale`, `clampRoomScale`,
`shiftSharedSpans`, `_rszApplyPreview`, `src/plan-geometry-preflight.ts` из
#199) подтверждены в дереве.
- Терминология §3–§12 согласована с `RESIZE.md`/`WALL-THICKNESS.md`/
`CANVAS.md`/`UX-MODES.md`.
- Скоуп/не-скоуп (§10/§11) корректно разграничивают #277 от #253/#264/#276/
#278.
- Откат и release-артефакты (§17) описаны полно.
- Математическая полнота формул safe range (§3, §7) не разбиралась построчно
ни в r1, ни в r2 — по-прежнему предмет код-ревью, когда появятся тесты на
конкретных fixtures; дельта r2 эти разделы не трогала.
## Чего не проверял
- Гейты (`typecheck`/`test`/`build`/`check-docs`/`model-invariants`) —
диф класса C, только `docs/specs/277-safe-resize.md`, кода нет; то же
основание, что и в r1.
- Реальный воспроизводящий экспорт — не публикуется по условиям issue, как и
в r1.
- Полный повторный разбор §3–§11, §13–§15 — не требуется правилом «разбор по
дельте», дельта не задевает их доказательство (см. «Унаследовано из r1»).
## Вердикт
Зелёный. 0 High, 0 Medium. Обе оставшиеся находки — Low, сняты с записью
выше, без открытия нового блокирующего цикла.