16 KiB
SPEC-REVIEW-282-r2
- Issue: #282 — Геометрия стен: сменить представление, а не чинить последствия
- Этап: spec (PROCESS.md §2.4)
- Заход: r2 · блокирующих циклов израсходовано 1 из 4 (§2.10, §4: зелёный вердикт r1 не был — r1 был жёлтым и потратил цикл 1; если этот заход зелёный, он сам цикла не образует)
- Артефакт ТЗ:
docs/specs/282-stable-wall-segment-identity.md - SHA ТЗ на момент этого ревью:
2f30c481(docs: address wall identity spec review) - SHA предыдущего ревью (r1):
8856fbda(docs: specify stable wall segment identity) - Документ r1:
docs/reviews/SPEC-REVIEW-282-r1.md, вердикт жёлтый, High: 0, Medium: 2 (обе в скоупе)
Скоуп ревью r2 — по дельте (PROCESS.md §2.10)
Между 8856fbda и 2f30c481 изменён только docs/specs/282-stable-wall-segment-identity.md
(git diff 8856fbda..HEAD --stat: 37 строк в одном файле; второй файл в diffstat —
сам docs/reviews/SPEC-REVIEW-282-r1.md, зафиксированный шагом публикации, не автором ТЗ).
Продуктовый код (src/**, custom_components/**) не тронут — его для #282 всё ещё нет.
Изменение целиком является прямым ответом на M1/M2 из r1: не рёбейз, не смена контракта,
не новая подсистема, объём дельты (37 строк из 663) несопоставим с объёмом задачи. Полный
разбор ТЗ заново не требуется — разбирается дельта плюс AC, которых она касается (AC1),
остальное наследуется из r1 без повторной проверки.
Как проверялось
- Найден вердикт r1 и SHA, на котором он получен (
8856fbda, указан в шапкеSPEC-REVIEW-282-r1.md— в отличие от типового риска этого пункта, здесь SHA был назван явно, задача «найти SHA» тривиальна). - Объявлена дельта:
git diff 8856fbda..HEAD— построчно прочитан весь diffdocs/specs/282-stable-wall-segment-identity.md(7 хансов). - По каждой находке r1 (M1, M2) проверено, чем именно она закрыта — конкретной строкой изменённого текста, а не комментарием автора «исправлено» (комментарий issue #282 от Matysh,
2f30c48, только заявляет закрытие; настоящая проверка — ниже). - Прочитан целиком раздел «§7 Атомизация и deterministic migration v7 → v8» (включая нетронутый §7.2) и «§9 Writers и единый identity barrier» в текущей редакции — чтобы убедиться, что новое определение
exactв §7.1 корректно распространяется на §7.2, который сам не редактировался. - Перечитан AC1 целиком (единственный AC, чей текст изменён) на предмет однозначности и проверяемости после правки.
- Проверена терминология нового i18n/UX-текста против источника интерфейса (PROCESS.md требует брать термины из
docs/USER-GUIDE.ru.md, не изобретать):grepпоsrc/i18n/ru.jsonподтвердилgs.align_all/gs.align_title= «Оптимизировать планы» — тот же лейбл, что и в новом тексте тоста и в §2;docs/USER-GUIDE.ru.md:998(backup.preserved_unresolved_hint) уже использует ровно ту же конструкцию «запустите «Оптимизировать планы»» — формулировка не придумана, а повторяет существующий паттерн продукта. - Проверено, что дельта не расширяет скоуп и не меняет контракт вне того, что закрывают M1/M2 (§4/§5/§6/§8/§10/§13/§14 кроме AC1/§15–§19 кроме п.5 не тронуты).
Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
M1 (Medium) — не специфицирован порядок атомизации Stage 1 относительно lattice-барьера #291, и какой из двух существующих допусков (1e-4 vs max(pitch·10⁻⁶,10⁻⁹)) применяется |
§7.1 получил абзац: канонизация #291 запускается до breakpoint-вычисления и до любых v8 ID/ref; порог принадлежит только #291 (LATTICE_NOISE_STEPS = 1e-4); слово exact везде в §7 означает побитовое равенство уже канонизированных координат; третий допуск не вводится. §9 добавил тот же порядок в описание barrier-пайплайна («сначала… canonicalizeConfigGeometry #291, затем… commitWallSegmentModel», «одна атомарная commit-транзакция»). §19 п.5 повторяет то же для момента миграции. AC1 расширен явным требованием: fixtures с шумом по обе стороны порога дают byte-equivalent v8 candidate, шум внутри порога канонизируется и не создаёт micro-segments, координата вне порога не схлопывается молча. |
docs/specs/282-stable-wall-segment-identity.md:199-205 (§7.1), :333-338 (§9), :655-657 (§19 п.5), :439-445 (AC1) |
M2 (Medium) — §2/§11 обещают тексту тоста конкретный совет («Optimize либо исправление»), но toast.wall_model_migration_blocked в §12 не содержал никакого действия |
§2 переформулирован под фактический текст: «предлагает сначала запустить «Оптимизировать планы», а при повторном отказе — исправить конфликтующую геометрию стен». §12 переписан в обе стороны (RU/EN): toast.wall_model_migration_blocked теперь буквально содержит «Запустите «Оптимизировать планы»; если ошибка повторится, исправьте конфликтующую геометрию стен.» / «Run "Optimize plans"; if the error repeats, fix the conflicting wall geometry.» — текст §2 и текст ключа теперь описывают одно и то же действие в одном порядке. |
docs/specs/282-stable-wall-segment-identity.md:32-34 (§2), :412 (§12, таблица i18n) |
Обе находки закрыты текстом, а не заявлением: конкретные строки процитированы выше и прочитаны целиком в контексте (см. «Как проверялось», пп. 3–4).
Дополнительная проверка терминологии (не отдельная находка, часть проверки закрытия M2)
Новая формулировка «Оптимизировать планы» — не изобретённый ревьюером или автором термин: это точное название существующей кнопки (gs.align_all/gs.align_title, src/i18n/ru.json:807-808) и уже употреблённый в docs/USER-GUIDE.ru.md:998 паттерн «запустите «Оптимизировать планы»» для родственного случая (нерешённые ссылки после импорта). Правка M2 не только закрывает находку, но и делает это в терминах, которые уже существуют в продукте — соответствует требованию PROCESS.md брать терминологию интерфейса из USER-GUIDE.ru.md, а не изобретать.
Что переразобрано в этом раунде (AC, которых касается дельта)
- AC1 — единственный AC с изменённым текстом. Новая формулировка добавляет случай
lattice-noise по обе стороны порога #291к уже существующему списку fixture-классов (outer/shared/partial-overlap/T/X/diagonal/open span/key-only/exact walls). Критерий остаётся однозначным и проверяемым тем же способом доказательства (TS migration unit matrix + golden/static path comparison + backend fixture parity): для шума ниже1e-4ожидается, что после канонизации #291 атомизация не порождает лишних микросегментов; для расхождения выше порога — coordinate не схлопывается. Оба утверждения формулируются как конкретные fixture-проверки (сравнение catalog до/после на данных внутри/вне порога), а не как качественное пожелание — критерий выполнимости не потерян правкой. - Остальные AC2–AC17 текстуально не изменились дельтой; их доказательство не зависит от порядка canonicalization/atomization (эта деталь относится только к самому механизму миграции, не к результату, который проверяют AC2 и далее) — повторный разбор не требуется, см. «Унаследовано» ниже.
Унаследовано из r1 (без повторной проверки)
Всё нижеперечисленное принято из docs/reviews/SPEC-REVIEW-282-r1.md на SHA 8856fbda, так как дельта r1→r2 их текста и логики не касается:
- Соответствие
docs/SCOPE.md/J6, отсутствие расширения UX/новой функциональности — §4/§5 не изменены дельтой. - Продуктовые разделы §1 «Сценарий» и §2 «Что человек увидит» присутствуют и различимы (PROCESS.md §7.1); §2 в этом раунде получил только точечную правку текста тоста-совета (см. M2 выше), структура и персона не менялись.
- Построчная сверка фактических утверждений ТЗ о текущей модели (v7,
MAX_ROOMS/MAX_POLY_POINTS=200000,host?: {kind:'partition',...},wallKey/rekeyWallsAfterMove/exactCoveringWall/edgeKinds/sharedSegsOf/atomicPolyForRoom, существованиеsrc/coordinate-canonicalization.ts/canonicalizeConfigGeometry/LATTICE_NOISE_STEPS, существование скриптовconfig-field-registry.mjs/model-invariants.mjs/mutation-gate.mjs/smoke-select.mjs, i18n-префиксыtoast.*/gs.*) — код в этих частях не менялся между r1 и r2, повторная сверка не требуется. - AC2–AC17 однозначны и проверяемы, каждый называет способ доказательства — текст этих AC не изменён дельтой.
- Не-скоуп (§5) корректно ограничивает риск, держит границу Stage 1 против Stage 2–4 — не изменён.
- Откат и release-артефакты (§17–18) реалистичны — не изменены.
- Ссылки на существующий тулинг и гейты (§10.4, §17) верны — не изменены.
- «Чего не проверял» из r1 (ARCHITECTURE.md/CANVAS.md/UX-MODES.md/TOUCH-SUPPORT.md целиком; история регрессионных issues из AC12 построчно; typecheck/test/build — кода нет; вероятность hash-коллизии §7.3 математически) — основания этих пропусков не изменились дельтой, пропуски наследуются на тех же условиях.
Чего не проверял в r2
- Не перечитывал целиком ADR
docs/adr/282-wall-geometry-representation.mdзаново — дельта его не касается, а r1 уже подтвердил соответствие ТЗ этому ADR. - Не гонял
npx tsc --noEmit/npm test/npm run build— дельта не касается ни одного файла класса A/B (толькоdocs/specs/*.md, класс C), продуктового кода для #282 по-прежнему нет; гонять эти гейты в этом раунде нечего. - Не проверял математически вероятность hash-коллизии §7.3 — не тронуто дельтой, унаследовано из r1.
- Не проверял согласованность нового текста тоста (M2) с фактическими лимитами длины UI-тоста/типографикой — это находится за пределами ТЗ-ревью (вопрос реализации/визуального QA на этапе код-ревью), а не критерий выполнимости ТЗ.
Вердикт
Обе Medium-находки r1 закрыты точечными, проверяемыми правками текста: M1 — явным порядком «канонизация #291 → атомизация» и запретом третьего допуска, с расширением AC1 под fixture с шумом по обе стороны порога; M2 — синхронизацией текста §2/§11 с фактическим i18n-ключом, использующей существующую терминологию интерфейса, а не изобретённую. Новых High- или Medium-находок дельта не создала. Дельта локальна (только текст ТЗ, 37 строк), полного повторного разбора не требует.
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0 · Документ: docs/reviews/SPEC-REVIEW-282-r2.md