docs: review document for #223

Issue: #223
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-20 19:32:16 +00:00
parent fb6d7ea693
commit 603bb3647f
+168
View File
@@ -0,0 +1,168 @@
# SPEC-REVIEW-223-r3
- Issue: [#223](https://github.com/Matysh/houseplan-card/issues/223) «Оптимизировать планы» должна
канонизировать координаты, а не консервировать floating-point шум
- ТЗ: [`docs/specs/223-optimize-coordinate-canonicalization.md`](../specs/223-optimize-coordinate-canonicalization.md)
на коммите `8c9e5feae3503c086cc9f987d57f676e5435e537` (HEAD)
- Раунд: r3/4
- Вердикт: **зелёный**
## Скоуп ревью (по дельте, PROCESS.md §2.10)
Round r2 получен на `965711ee2005b8ec2587b9c70fb9b14735c7756e` (SHA назван в
самом документе `docs/reviews/SPEC-REVIEW-223-r2.md`, вердикт жёлтый, High: 0,
Medium: 1). Предмет этого раунда — `git diff 965711e..HEAD`. Диапазон состоит
из двух коммитов:
- `981d3d6` — публикация документа `docs/reviews/SPEC-REVIEW-223-r2.md`
(артефакт самого ревью, не правка ТЗ);
- `8c9e5fe` («docs: clarify optimize report terminology») — единственная
содержательная правка: 4 вставки / 4 удаления в
`docs/specs/223-optimize-coordinate-canonicalization.md`, три места —
§7 (текст диалога), строка AC6 и строка риска в §11. Меняется только слово
«нормализовано»/«normalized» → «обновлено»/«updated» для существующего
счётчика `c`; структура, семантика, доказательная матрица AC не затронуты.
Дельта локальна текстом (§2.10): нет ребейза, нет смены контракта поведения,
не задета новая подсистема, объём (8 строк) на порядок меньше и исходного ТЗ
(~230 строк), и даже правки r2 (42 строки). Полный разбор не открывается.
Отдельно проверено, не расширяет ли эта правка скоуп и не ломает ли AC,
которые r1/r2 уже приняли (§2.10 п.5, регрессия по образцу #102) — нет: правка
меняет исключительно пользовательскую метку одного и того же существующего
показателя `c`, не его состав, не структуру `OptimizeReport`, не AC4/AC5/§6/§8.
## Как проверялось
1. Восстановлен вердикт r2 и его SHA командой `gh issue view 223 --json
comments` — `965711e`, назван в документе r2 (в этом раунде замечание
«SHA не назван» не применимо — второй раунд подряд его исправно называет).
2. `git show 8c9e5fe` — построчный разбор правки, единственная содержательная
правка в диапазоне.
3. Проверено буквальное закрытие находки r2: `grep -in "нормализ|normali"
docs/specs/223-optimize-coordinate-canonicalization.md` — осталось ровно
два вхождения: (а) `§6`, «нормализованного числа» — легитимное употребление
термина в его устоявшемся во всём проекте значении (координата 0..1
холста, никак не связано со счётчиком `c`); (б) `§11`, строка риска, где
слово упомянуто явно как «занятый термин, не используемый для `c`» — то
есть подтверждение отказа от него, а не остаточное использование. Нового
употребления «нормализовано»/«normalized» как метки счётчика `c` не
осталось нигде.
4. Проверено, не создаёт ли выбранная замена («обновлено»/«updated») новую
коллизию того же класса, которую уже дважды находил этот цикл ревью
(находка r1 №2 — «канонизировано» дважды; находка r2 — «нормализовано»
занято координатной системой):
- `grep -rn "\bupdated\b" docs/CANVAS.md docs/ARCHITECTURE.md` — ноль
совпадений: слово не занято описанием координатной системы ни в одном
каноническом документе;
- `grep -rn "обновлен" docs/*.md` — единственное релевантное совпадение
вне `CHANGELOG.ru.md` (журнал, не термин) — `toast.room_updated` /
«Комната обновлена» (`src/i18n/ru.json:562`, `en.json:562`): это
обобщённое подтверждение сохранения формы редактора комнаты, не термин
геометрии и не соседствует с координатным текстом Optimize — коллизии
смысла нет;
- `docs/CANVAS.md` §9.5 (строка 421) — канонический документ фичи называет
операцию, которую считает `c`, термином «exact open-span
canonicalisation»; «обновлено»/«updated» нейтрально по отношению к этому
термину и не конкурирует с ним за то же слово, в отличие от отвергнутых
«канонизировано» и «нормализовано»;
- выбранное слово — буквально один из двух вариантов по умолчанию,
предложенных самим ревью r2 в качестве примера («например
"обновлено"/"updated"»); автор использовал предложенный дефолт, а не
самостоятельно ввёл новый термин, что снижает риск третьей итерации той
же коллизии.
5. Сверено, что правка синхронна во всех трёх местах (§7, AC6, риск §11) и в
обоих языках (RU/EN) — да, во всех трёх местах пара
«обновлено»/«обновлённые»/«spaces updated» согласована, расхождений между
местами нет.
6. Перечитаны комментарии issue #223 целиком на предмет незаявленного
расширения скоупа — не найдено; хендофф r2→r3 (комментарий 2026-08-20
19:13:25Z) точно описывает сделанную правку.
7. Проверено происхождение семантики `c` в коде: `src/plan-optimizer.ts:404-500`
— `canonicalized++` инкрементируется по каждому элементу цикла
`for (let i = 0; i < config.spaces.length; i++)`, то есть ровно по
пространствам (`space`), чьё сериализованное представление
`open_spans`/`open_to`/`walls` изменилось. Формулировка «обновлено
пространств: {c}» / «spaces updated: {c}» точно соответствует коду,
который считает счётчик.
Код не проверялся: реализация не написана, этап `spec`, ни один файл класса
A/B в диапазоне `965711e..HEAD` не менялся (`git diff --stat` — только
`docs/reviews/**` и `docs/specs/**`).
## Закрытие раунда r2
| Находка r2 | Чем закрыта | Где видно |
|---|---|---|
| Medium — замена «нормализовано»/«normalized» для `c` заново создаёт коллизию того же класса: слово устойчиво занято координатной системой 0..1 во всём проекте, включая канонический документ фичи (`CANVAS.md`), который к тому же называет саму операцию `c` термином «canonicalisation», а не «normalisation» | Термин «нормализовано»/«normalized» заменён на «обновлено»/«updated» во всех трёх местах — §7 (диалоговая строка), AC6 (доказательная формулировка), §11 (строка риска); слово выбрано ровно из набора дефолтов, предложенных самим ревью r2, и не пересекается ни с «канонизировано» (занято `p`), ни с «нормализовано» (занято координатной системой) | `docs/specs/223-optimize-coordinate-canonicalization.md` §7, AC6 (таблица §9), §11, коммит `8c9e5fe` |
Закрытие точное и полное: `grep` не находит остаточного использования слова
в роли пользовательской метки счётчика, а выбранная замена проверена на тот
же класс коллизии, который дважды всплывал в предыдущих раундах (r1 №2, r2),
и не воспроизводит его в третий раз.
## Находки
Новых находок нет. High: 0, Medium: 0.
## Что проверено и корректно
- Находка r2 закрыта буквально и без побочной коллизии (см. выше).
- Три места правки (§7/AC6/§11) синхронны между собой и с новой пользовательской
формулировкой; ни AC4/AC5/§6/§8/§9(остальные AC)/§10/§12/§13, ни структура
`OptimizeReport`/`AlignReport` дельтой не задеты.
- `c` семантически описан точно тому, что делает код (`plan-optimizer.ts:500`).
- Скоуп задачи не расширился и не сузился; продуктовых вопросов по-прежнему
нет, дельта чисто терминологическая.
- Обязательные разделы ТЗ по PROCESS.md §7.1 присутствуют полностью (не
повторная проверка формы — унаследовано, см. ниже, — но сам факт, что
правка не удалила и не сломала ни один раздел, проверен диффом).
## Чего не проверял
- Код реализации — не написан, этап `spec`.
- Гейты (`typecheck`/`test`/`build`) — не запускались; дельта не затрагивает
класс A/B (только `docs/specs/**` и `docs/reviews/**`), гейты для этапа
`spec` не требуются.
- Текст `docs/USER-GUIDE.ru.md`/`docs/CANVAS.md`/`docs/CHANGELOG*` после
будущей реализации — они по плану переписываются в реализации (AC9,
§12), не в ТЗ; r3 проверял только формулировку самого ТЗ.
- Все AC и разделы, которых дельта `965711e..HEAD` не касается (AC1, AC2,
AC3, AC4, AC5, AC7, AC8, AC9, AC10, §1–§6, §8, §10, §12, §13) —
унаследованы из r2 без повторной проверки, ниже.
## Унаследовано из r2
Принято без повторной проверки в этом раунде, по документу
`docs/reviews/SPEC-REVIEW-223-r2.md` на SHA `965711ee2005b8ec2587b9c70fb9b14735c7756e`:
- скоуп по `docs/SCOPE.md` (J6) и выбор обычного трека — не изменился, дельта
трек-критерии не затрагивает;
- обязательные разделы ТЗ по PROCESS.md §7.1 присутствуют и по форме верны
(подтверждено ещё в r1, дельта r2 и r3 разделов не удаляла);
- подтверждённая причина и порядок величин шума (issue, §3 ТЗ) — арифметика
`EPS`/`GRID_STEP_N` из `src/align-grid.ts:62-72`, не менялась ни в r2, ни
здесь;
- контракт снапа §6, идемпотентность (AC5), исключение проёмов из счётчика,
отсутствие вызовов `snapN()` вне `align-grid.ts`, отсутствие роста
`moved`/`maxShift*` от near-node замен — код и раздел §6 не входят в дельту
ни r2, ни r3;
- AC4/`partitions`/`wall_columns` (находка r1 №1) — закрыта в r2, дельта r3
этих разделов (§9 AC4, §10, §11 соответствующей строки риска) не касается;
- AC1, AC2, AC3, AC4, AC5, AC7, AC8, AC9, AC10 — доказательство ни одного из
них дельта r3 не задевает (правка только в §7-фрагменте, строке AC6 и
строке риска §11, причём даже внутри AC6 меняется только слово, а не сама
проверяемая формулировка контракта);
- ссылка issue ↔ ТЗ в `docs/specs/README.md`, release-артефакты §12 — не
входят в дельту;
- отсутствие продуктовых вопросов владельцу — подтверждено r1 и r2, дельта r3
чисто терминологическая правка одной пользовательской строки, новых
продуктовых вопросов не порождает.
## Вердикт
Вердикт: зелёный · цикл r3/4 · High: 0 · Medium: 0
Обе находки предыдущих раундов (r1 №1, r1 №2/r2) закрыты по существу, третья
попытка того же класса коллизии не воспроизвелась. ТЗ готово к переходу в
«Готово к разработке».