Files
houseplan-card/legacy/reviews/v1.68.0/SPEC-REVIEW-223-r2.md
T
Claudeandclaude[bot] 0991c45374 fix(tools): архив переписывает относительные ссылки перенесённых документов (#682)
Ревью #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
2026-09-27 22:10:47 +00:00

18 KiB
Raw Blame History

SPEC-REVIEW-223-r2

  • Issue: #223 «Оптимизировать планы» должна канонизировать координаты, а не консервировать floating-point шум
  • ТЗ: docs/specs/223-optimize-coordinate-canonicalization.md на коммите 965711ee2005b8ec2587b9c70fb9b14735c7756e (HEAD)
  • Раунд: r2/4
  • Вердикт: жёлтый

Скоуп ревью (по дельте, PROCESS.md §2.10)

Round r1 получен на c0fff33 (документ docs/reviews/SPEC-REVIEW-223-r1.md, вердикт жёлтый, High: 0, Medium: 2). Предмет этого раунда — git diff c0fff33..965711e: правки только в docs/specs/223-optimize-coordinate-canonicalization.md, 27 добавлений / 15 удалений, разделы §7 (UX/запись), AC4, AC6, §10 (план реализации), §11 (риски), §13 (принятые предположения). Ни код, ни другие документы, ни тело issue в дельте не участвуют — дельта локальна текстом ТЗ, разбор полным не открывается (критерии §2.10 «дельта не локальна» не выполнены: нет ребейза, нет смены контракта, не задета новая подсистема, объём дельты — 42 строки против ~230 строк исходного ТЗ).

Отдельно проверено: не расширился ли скоуп задачи и не сломан ли этой правкой какой-либо AC, который r1 уже принял (§2.10 п.5, регрессия по образцу #102) — см. «Унаследовано из r1» ниже.

Как проверялось

  1. Восстановлен вердикт r1 и его SHA командой gh issue view 223 --comments — c0fff33, назван в самом документе r1 (в этом раунде SHA назван, замечание предыдущего цикла о неназванном SHA сюда не относится).
  2. git diff c0fff33..965711e — построчный разбор всех правок (полный текст выше в тред-контексте инструмента).
  3. По каждой из двух находок r1 — проверено текстовое место закрытия (см. таблицу ниже), не только заявление автора в хендофф-комментарии.
  4. Для находки №2 (терминологическая коллизия) — проверено, не создаёт ли выбранная замена термина новую коллизию: grep по нормализ|normali в docs/*.md и src/i18n/*.json показал, что «normalised/нормализовано» уже плотно занято во всём проекте другим, устоявшимся значением — координата в диапазоне 0..1 холста (docs/CANVAS.md:12,20,333,489,539, docs/ARCHITECTURE.md:345,356 и др.), и что канонический документ самой этой фичи (docs/CANVAS.md §9.5, строка 421) уже называет ровно ту операцию, которую считает счётчик c (rekey open_spans/open_to), термином «canonicalisation», а не «normalisation». Разбор ниже.
  5. AC4/AC6/§10/§11/§13 в новой редакции сверены на внутреннюю непротиворечивость (совпадение формулировки контракта, доказательной матрицы и риска для каждого изменения).
  6. Комментарии issue #223 целиком, включая хендофф r1→r2, прочитаны заново на предмет незаявленных изменений скоупа — не найдено.

Код не проверялся: реализация не написана, этап spec.

Закрытие раунда r1

Находка r1 Чем закрыта Где видно
Medium 1 — AC4 не покрывает partitions/wall_columns, наивная tracked-обёртка на входе засчитает отклонённый snap партиции AC4 расширен явным требованием: «Принятая партиция и wall_column учитываются; у партиции с hostedFit = false вычисленный, но не записанный snap не учитывается и noisy endpoints сохраняются», доказательная матрица AC4 включает «применённой и отклонённой partition, wall column»; §10 переписан — вклад в coordsCanonicalized подтверждается «только в месте фактической записи значения в candidate», явно расписана ветка snappedLength > EPS && hostedFit и её else-ветвь; §11 получил строку риска «Отклонённый snap партиции попадает в отчёт» с мерой docs/specs/223-optimize-coordinate-canonicalization.md §9 (AC4), §10, §11, коммит 965711e
Medium 2 — новый показатель делит корень «канонизировано» с существующим c в одной строке диалога §7 переписан: c получил метку «нормализовано пространств» / «spaces normalized», p — «устранён шум координат» / «noisy coordinate values removed»; текст явно называет оба значения раздельно и утверждает «два разных показателя не используют один термин "канонизировано" в одном предложении»; AC6 и §11 обновлены синхронно; §13 добавил пункт 3 о том, что переименование c затрагивает только текст, не структуру отчёта docs/specs/223-optimize-coordinate-canonicalization.md §7, §9 (AC6), §11, §13, коммит 965711e

Буквальная коллизия слова «канонизировано» действительно устранена. Но выбор замены для находки 2 создаёт новую проблему того же класса — см. находку ниже: закрытие частично, регресс того же типа воспроизвёлся другим словом.

Находки

Medium (в скоупе задачи) — замена термина для находки r1 №2 меняет одну коллизию на другую: «нормализовано»/«normalized» уже устойчиво означает координатную систему 0..1, а не эту операцию

docs/specs/223-optimize-coordinate-canonicalization.md §7 (правка этого раунда): существующий показатель c (OptimizeReport.canonicalized — число пространств, где переписано JSON-представление open_spans/open_to/walls после rekey) получает пользовательскую метку RU «нормализовано пространств», EN «spaces normalized».

Ровно это слово уже занято в проекте другим, никак не связанным значением — координата в диапазоне 0..1 холста, а не операция над JSON-представлением пространства:

  • docs/CANVAS.md:12 «the whole plan… as if the normalised unit square»;
  • docs/CANVAS.md:20 «device positions are still stored normalised»;
  • docs/CANVAS.md:333,489,539 — то же значение ещё трижды в том же файле;
  • docs/ARCHITECTURE.md:345 «All coordinates are normalized (0..1 of the canvas)»; :356 то же для layout v2.

Хуже: канонический документ именно этой фичи (docs/CANVAS.md §9.5, строка 421 — «Оптимизировать планы» explicit whole-plan maintenance, ровно тот пассаж, который описывает проход, считаемый показателем c) уже называет эту операцию своим устоявшимся именем — «exact open-span canonicalisation», не «normalisation». ТЗ заменяет пользовательскую метку операции с одного слова, конфликтовавшего с p в том же предложении («канонизировано» дважды), на слово, конфликтующее с устоявшимся термином координатной системы в том же каноническом документе и во всём проекте — и одновременно расходящееся с тем, как канонический документ называет саму эту операцию.

Почему это не гипотетика, а конкретный сценарий чтения. Строка диалога после правки — «нормализовано пространств: {c}; устранён шум координат: {p}» — это два счётчика в одном предложении о геометрии/координатах, один из которых называется словом, которое во всей остальной документации означает «координата приведена к 0..1». Администратор, читающий предпросмотр Optimize рядом с формулировкой issue («канонизировать координаты») или с docs/CANVAS.md (где то же слово стоит для другого понятия дважды на расстоянии нескольких строк от «canonicalisation»), может прочитать «нормализовано пространств» как третий, ещё один вид работы с координатами — то есть тот же класс путаницы, который находка r1 №2 уже описывала для слова «канонизировано», просто с новым словом. docs/CANVAS.md §9.5 и комментарий AUD-158B1-01 в шапке align-grid.ts (процитирован в ревью r1) требуют точности этого отчёта как условия доверия — новый термин это условие не выполняет лучше старого.

Фикс (в скоупе, решает автор): не использовать «нормализовано»/«normalized» для c — слово занято координатной системой во всём проекте, включая канонический документ самой этой фичи. Канонический термин для операции, которую считает c, уже есть в docs/CANVAS.md §9.5 — «canonicalisation» (open-span); задача может либо оставить c на этом корне и развести его с p через уточняющее существительное (что именно канонизировано — представление связей пространства, а не координаты: например RU «пространств приведено к каноническому представлению: {c}» / EN «spaces re-canonicalised: {c}»), либо выбрать нейтральное слово без занятого во всём проекте значения (например «обновлено»/«updated», «перелинковано»/«relinked»). Любой вариант закрывает находку без создания новой при условии, что слово не совпадает ни с «канонизировано» (уже занято p), ни с «нормализовано»/«normalized» (уже занято координатной системой).

Что проверено и корректно

  • Находка r1 №1 (AC4/partitions/wall_columns) закрыта по существу — контракт §6 п.3 («результат действительно записан в candidate») теперь дословно отражён в AC4 и в плане реализации §10 с указанием точной ветки (snappedLength > EPS && hostedFit); риск-таблица получила отдельную строку. Ни один тест из новой доказательной матрицы не назван расплывчато.
  • Идемпотентность, контракт снапа §6, исключение проёмов, границы scope/non-scope, release-артефакты, отсутствие продуктовых вопросов — не затронуты дельтой этого раунда, проверка не повторялась (см. «Унаследовано из r1»).
  • Нумерация принятых предположений в §13 — после вставки нового пункта 3 весь список перенумерован без дублей и разрывов (1…6), проверено построчно.
  • Формулировка §7 больше не содержит самоссылки — прежний текст перечислял «счётчики миграций/планов/стен/виртуальных фрагментов» рядом с полем, которое само и есть «планов»; новая редакция убрала слово из перечисления (осталось «миграций/стен/виртуальных фрагментов») — мелкая, но корректная правка, не нёсшая отдельного вреда, если бы её не сделали.
  • AC6 согласован с §7 построчно — оба места одинаково называют оба показателя и одинаково описывают случай moved=0.

Чего не проверял

  • Код реализации — не написан, этап spec.
  • Гейты (typecheck/test/build) — не запускались; для этапа spec не требуются (правка не затрагивает класс A/B, только docs/specs/**).
  • Собственно текст docs/USER-GUIDE.ru.md/docs/CANVAS.md после будущей реализации — они пока не переписаны (AC9 это будущая работа реализации), r2 проверял только формулировку самого ТЗ и её согласованность с уже существующим текстом канонических документов.
  • Все AC, не задетые дельтой (AC1, AC2, AC3, AC5, AC7, AC8, AC9, AC10) — унаследованы из r1 без повторной проверки, ниже.

Унаследовано из r1

Принято без повторной проверки в этом раунде, по документу docs/reviews/SPEC-REVIEW-223-r1.md на SHA c0fff33:

  • скоуп по docs/SCOPE.md (J6) и выбор обычного трека — не изменился, дельта трек-критерии не затрагивает;
  • обязательные разделы ТЗ по PROCESS.md §7.1 присутствуют и по форме верны;
  • подтверждённая причина и порядок величин шума (issue, §3 ТЗ) — арифметика EPS/GRID_STEP_N из src/align-grid.ts:62-72, не менялась;
  • контракт снапа §6, идемпотентность (AC5), исключение проёмов из счётчика, отсутствие вызовов snapN() вне align-grid.ts, отсутствие роста moved/maxShift* от near-node замен — код и раздел §6 не входят в дельту этого раунда;
  • AC1, AC2, AC3, AC5, AC7, AC8, AC9, AC10 — доказательство ни одного из них дельта не задевает (правки только в AC4/AC6/§7/§10/§11/§13);
  • ссылка issue ↔ ТЗ в docs/specs/README.md, release-артефакты §12 — не входят в дельту;
  • отсутствие продуктовых вопросов владельцу — подтверждено r1, дельта чисто техническая (формулировка отчёта и план реализации), новых продуктовых вопросов не порождает.

Вердикт

Вердикт: жёлтый · цикл r2/4 · High: 0 · Medium: 1 → в задаче

Находка Medium в скоупе текущего issue (правит ту же i18n-строку gs.optimize_changes и тот же §7 ТЗ, что и вся задача) — чинится в этом ТЗ без отдельного issue (владелец, 2026-08-19, #202).