diff --git a/docs/reviews/SPEC-REVIEW-360-r2.md b/docs/reviews/SPEC-REVIEW-360-r2.md new file mode 100644 index 00000000..444c589d --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-360-r2.md @@ -0,0 +1,123 @@ +# SPEC-REVIEW-360-r2 + +Issue: #360 · этап: spec (S4-spec-review) · трек: `small` (лёгкий) · заход: r2 · +блокирующих циклов израсходовано: 1 из 2 (лимит лёгкого трека, §4 — r1 был +жёлтым и потратил цикл, зелёный r1 бюджет бы не тратил, но r1 был жёлтым) + +Ревьюер: Claude (роль «ревьюер ТЗ»), отдельная сессия от r1 и от автора. +ТЗ по-прежнему живёт в теле issue #360 (revision 2), файл `docs/specs/` не +создаётся — верно для `small`. Кода нет: issue в `S4-spec-review`, Rule #1 не +разрешает трогать `src/**` раньше `S5-ready`, и на `dev` (HEAD `6ce42b33`) +изменений класса A по #360 нет. + +## Разбор по дельте (PROCESS.md §2.10) + +Второй заход — разбор ограничен дельтой revision 1 → revision 2, а не ТЗ +целиком. Дельта локальна: ни ребейза, ни смены контракта поведения, ни новой +подсистемы, объём дельты (два добавленных предложения) несопоставимо меньше +исходной задачи. Полный повторный разбор не требуется. + +**Как найдена дельта.** Тело issue не версionируется в git, поэтому вместо +`git diff ..HEAD` использован эквивалент для spec-этапа: GitHub +`userContentEdits` (GraphQL) с историей правок тела issue. Ревизия 1 (та, что +читал r1) — снимок тела issue непосредственно перед правкой в 08:00:23Z, без +слов «Touch editor» и без `_decorSaveShape`; это дословно совпадает с тем, что +процитировано в `docs/reviews/SPEC-REVIEW-360-r1.md`. Текущее тело (revision 2, +правка в 08:08:24Z) сверено с этим снимком построчным diff. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| **M1** — не названа обязательная формула туча из `docs/TOUCH-SUPPORT.md` («New editor feature specifications... must state one of: `Touch editor: supported` / `best effort / intentionally degraded` / `not exposed`») | Пункт 8 контракта поведения дополнен буквальной формулой | Тело issue, п.8: «**Touch editor: best effort / intentionally degraded.** Background editor сохраняет действующий desktop-first контракт; на touch View/kiosk нет изменений и регрессий.» — точное совпадение одного из трёх канонических вариантов `docs/TOUCH-SUPPORT.md:165-167` | +| **M2** — не описано, что сохранение properties-диалога существующего line/rect/ellipse/furniture перезаписывает тот же `_decorStyle`, который задача делает постоянно видимым | Новый п.9 контракта плюс расширение AC5 и шага 4 плана тестов | Тело issue, п.9: «Сохранение properties-диалога уже существующего line/rect/ellipse/furniture сохраняет текущую семантику `_decorSaveShape`: его `color`/`opacity` становятся новым `_decorStyle`... Это не ретроактивная перекраска других объектов и не новая побочная связь.»; AC5 добавлена фраза «сохранение нового цвета/opacity в properties-диалоге существующего line/rect/ellipse/furniture обновляет main picker по текущему контракту `_decorSaveShape`, и следующий объект получает последнее значение»; план тестов, шаг 4, добавлено «Затем сохранить новый цвет/opacity через properties-dialog уже существующих line, rect, ellipse и furniture и проверить main picker и стиль следующего объекта» | + +Обе находки закрыты добавлением текста без изменения архитектуры контракта или +номеров AC — ровно так, как r1 и предписывал. Других правок в теле issue между +ревизиями 1 и 2 нет: построчный diff (см. ниже) вне пп. 8, 9, AC5 и шага 4 +плана тестов состоит только из переноса строк markdown (тот же текст, другая +раскладка по ширине), без содержательных изменений. + +## Проверка дельты по коду (не только по формулировке) + +Обе добавленные фразы — не пересказ, а утверждения о поведении текущего кода, +которые обязаны быть сверены (это ровно тот класс, где ТЗ может выдать догадку +за решение): + +- **М1-текст.** Формула `Touch editor: best effort / intentionally degraded` + сверена дословно с `docs/TOUCH-SUPPORT.md:163-167` («Documentation rule») — + совпадает буква в букву, это один из трёх легальных вариантов, а не + собственная формулировка автора. +- **М2-текст.** Утверждение «сохранение properties-диалога существующего + line/rect/ellipse/furniture пишет color/opacity в общий `_decorStyle`» + сверено чтением `src/houseplan-editor-runtime.ts:4422-4485` (`_decorSaveShape`): + строки 4476–4480 действительно присваивают + `this.host._decorStyle = { ...style, fill/fillColor/fillOpacity сохраняются + из предыдущего _decorStyle кроме rect/ellipse }` — подтверждено. Функция + правит только элемент с `shape.id === d.id` (строка 4434), других + размещённых объектов не касается — подтверждает фразу «не ретроактивная + перекраска других объектов». +- Также проверено чтением, что `_decorSaveText` (`houseplan-editor-runtime.ts:4381-4419`, + диалог текста) **не** пишет в `_decorStyle` — то есть ограничение п.9 списком + «line/rect/ellipse/furniture» без text точное, а не случайно узкое. + +Обе фразы дельты — не догадка, а корректно сформулированный факт кода. + +## Унаследовано из r1 + +Без повторной проверки в этом раунде приняты все выводы +`docs/reviews/SPEC-REVIEW-360-r1.md` (заход r1, снимок тела issue на 08:00:23Z, +т.е. revision 1) — дельта их не затрагивает: + +- обязательные разделы §7.1 присутствуют (сценарий, «что человек увидит», + проблема, скоуп/не-скоуп, контракт, данные/i18n/совместимость, файлы, + AC1–AC8, план тестов, риски/откат, release-артефакты, принятые предположения); +- сверка утверждений ТЗ с деревом на SHA `0decce8d`: единый `_decorStyle` как + source для line/rect/ellipse/text/furniture, структура + `.decorbar`/`.editbar-tools`/`.editbar-end`, `flex-wrap` вместо скролла, + хрупкие тесты `demo/smoke_decor.mjs:132-134` и + `test/color-picker.test.mjs:57-62`, независимость `fillColor`/`fillOpacity`, + отсутствие новых i18n-ключей — все подтверждены и делтой не задеты; + `_decorStyle` со времени SHA `0decce8d` в этом файле не менялся (единственные + изменения на пути к `6ce42b33` — сам документ ревью и предыдущий golden/фикс + furniture-обводки, не относящиеся к decor-style contract), поэтому вывод + остаётся в силе и на текущем HEAD; +- product-question gate соблюдён, блокирующих продуктовых вопросов у автора нет; +- трек `small` подтверждён верно (одна поверхность, риск/сложность ≤3, нет + миграции, нет нового UX-контракта, лимит ревью ТЗ — 2 цикла); +- откат описан и достаточен; +- Low-находок сверх M1/M2 не было и не появилось. + +## Что проверено заново в этом раунде + +- Текст п.8 и п.9 (весь текст, добавленный дельтой); +- AC5 в новой редакции — единственный AC, чьё доказательство дельта расширяет; +- шаг 4 плана тестов в новой редакции; +- код `_decorSaveShape` и `_decorSaveText` (чтением, не исполнением — на этапе + spec кода задачи нет, поэтому запуск невозможен и не требуется). + +## Гейты + +Этап — spec, не code. `src/**` по issue #360 не изменялся (Rule #1: код +разрешён только из `S5-ready`), поэтому `typecheck`/`test`/`build`/ +`check-docs`/`model-invariants`/смоки к этому раунду неприменимы — гейты кода +запускаются на этапе код-ревью. Единственная проверка этого раунда — чтение +кода `_decorSaveShape`/`_decorSaveText` в текущем дереве `dev` (см. выше), +выполненное вручную. + +## Находки + +Новых High/Medium/Low находок в дельте revision 1 → revision 2 нет. Обе +Medium-находки r1 закрыты полностью и точно. + +## Чего не проверял + +- Реальную браузерную/визуальную проверку (кода нет, применимо к + код-ревью после реализации) — без изменений относительно r1; +- `demo/golden` и фактический рендер light/dark — неприменимо к ТЗ; +- соответствие итогового кода контракту — предмет отдельного код-ревью. + +## Вердикт + +Зелёный. High: 0. Medium: 0 (обе находки r1 закрыты, новых нет). Issue готов +к переходу в `S5-ready`.