mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
committed by
Sergey Matyunin
parent
0bca6dfb14
commit
2ad20dca2b
@@ -0,0 +1,141 @@
|
||||
# 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 без повторной проверки (дельта их не касается). ТЗ готово к
|
||||
разработке.
|
||||
Reference in New Issue
Block a user