Files
houseplan-card/docs/reviews/SPEC-REVIEW-223-r3.md
T
2026-08-20 19:32:16 +00:00

169 lines
15 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-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) закрыты по существу, третья
попытка того же класса коллизии не воспроизвелась. ТЗ готово к переходу в
«Готово к разработке».