Ревью #682 r1, Medium: перенос добавляет документу уровень вложенности (`docs/reviews/X.md` → `legacy/reviews/<тег>/X.md`, `docs/specs/` → `legacy/specs/`), а относительные ссылки внутри перенесённых документов и в соседях, ссылавшихся на них, никто не пересчитывал — на `97d19268` 53 битые ссылки в 46 файлах (заявление «все 26 резолвятся» в `7feb6177` было верно только до переноса документов ревью). Гейты архив не смотрят. `reviews-archive.mjs`: `repairLinks` пересчитывает ссылку, если она не резолвится от нового места, а цель находится от нового или старого места через карту переносов; битая и до переноса ссылка не трогается. `--apply` делает это само, `--repair-links=<rev>` — для всех переименований `<rev>..HEAD`, `--check-links` печатает битые. Этим коммитом `--repair-links=origin/dev` переписал ровно 53 ссылки в 46 файлах; остались две прежние «...»-заглушки в CODE-REVIEW-448-r2 (битые и на dev). Тесты: перенесённый документ, сосед со ссылкой в архив, ТЗ со ссылкой на позже перенесённое ревью, битая-до-переноса не трогается, в `legacy/` битых нет; мутант `reviews-archive-links-from-new-place-only`. PROCESS §2.10 и DEVELOPMENT › Release называют переписывание и `--check-links`. Issue: #682 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
15 KiB
SPEC-REVIEW-223-r3
- Issue: #223 «Оптимизировать планы» должна канонизировать координаты, а не консервировать floating-point шум
- ТЗ:
docs/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.
Как проверялось
- Восстановлен вердикт r2 и его SHA командой
gh issue view 223 --json comments—965711e, назван в документе r2 (в этом раунде замечание «SHA не назван» не применимо — второй раунд подряд его исправно называет). git show 8c9e5fe— построчный разбор правки, единственная содержательная правка в диапазоне.- Проверено буквальное закрытие находки r2:
grep -in "нормализ|normali" docs/specs/223-optimize-coordinate-canonicalization.md— осталось ровно два вхождения: (а)§6, «нормализованного числа» — легитимное употребление термина в его устоявшемся во всём проекте значении (координата 0..1 холста, никак не связано со счётчикомc); (б)§11, строка риска, где слово упомянуто явно как «занятый термин, не используемый дляc» — то есть подтверждение отказа от него, а не остаточное использование. Нового употребления «нормализовано»/«normalized» как метки счётчикаcне осталось нигде. - Проверено, не создаёт ли выбранная замена («обновлено»/«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"»); автор использовал предложенный дефолт, а не самостоятельно ввёл новый термин, что снижает риск третьей итерации той же коллизии.
- Сверено, что правка синхронна во всех трёх местах (§7, AC6, риск §11) и в обоих языках (RU/EN) — да, во всех трёх местах пара «обновлено»/«обновлённые»/«spaces updated» согласована, расхождений между местами нет.
- Перечитаны комментарии issue #223 целиком на предмет незаявленного расширения скоупа — не найдено; хендофф r2→r3 (комментарий 2026-08-20 19:13:25Z) точно описывает сделанную правку.
- Проверено происхождение семантики
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) закрыты по существу, третья попытка того же класса коллизии не воспроизвелась. ТЗ готово к переходу в «Готово к разработке».