From 916a42e33af1411eab3320d25636abab0d583b9d Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 07:32:04 +0000 Subject: [PATCH] docs: review document for #306 Issue: #306 User-Visible: no --- docs/reviews/SPEC-REVIEW-306-r1.md | 376 +++++++++++++++++++---------- 1 file changed, 250 insertions(+), 126 deletions(-) diff --git a/docs/reviews/SPEC-REVIEW-306-r1.md b/docs/reviews/SPEC-REVIEW-306-r1.md index 564b240f..cadf7a98 100644 --- a/docs/reviews/SPEC-REVIEW-306-r1.md +++ b/docs/reviews/SPEC-REVIEW-306-r1.md @@ -1,152 +1,276 @@ -# SPEC-REVIEW-306-r2 +# SPEC-REVIEW-306-r3 - **Issue:** [#306](https://github.com/Matysh/houseplan-card/issues/306) — Редактор плана: заменить виртуальные стены обычными стенами толщиной 0 - **Этап:** ревью ТЗ (PROCESS.md §2.4, повторный раунд — §2.10) -- **Заход:** r2 · блокирующих циклов израсходовано 1 из 4 -- **ТЗ:** `docs/specs/306-zero-thickness-walls.md`, HEAD ветки `2c801bf539ed81bf7b4239c0b71ba12c514efc59` («docs: address zero-wall spec review») -- **Метка issue:** `S4-spec-review` (полный трек) +- **Заход:** r3 · блокирующих циклов израсходовано (до этого вердикта) 1 из 4 +- **ТЗ:** `docs/specs/306-zero-thickness-walls.md`, HEAD ветки `issue/306-zero-thickness-walls` = `abbd4904641b196ab9c2ed841600e2b260c75653` («docs: adapt zero-wall spec to model v8») +- **Метка issue:** `S4-spec-review` (полный трек, не `small`/`trivial`) -## Расхождение метаданных задачи с фактическим состоянием (зафиксировано, не блокирует) +## Расхождение метаданных запуска с фактическим состоянием issue (процессная находка, не по ТЗ) -Метаданные этого запуска ревью утверждали «Заход: r1 · блокирующих циклов -израсходовано 0 из 4». Это не соответствует GitHub: `docs/reviews/SPEC-REVIEW-306-r1.md` -уже существует (коммит `ec76d3b1`), вердикт по нему опубликован комментарием -issue #306 (жёлтый · заход r1 · циклов 1/4 · High 0 · Medium 3), автор внёс -правки коммитом `2c801bf5` и сам передал задачу «на delta-review r2/4» -(комментарий issue от 16:52:05Z). Метка на issue остаётся `S4-spec-review`, -GitHub — приоритетный источник правды (PROCESS.md, преамбула). Провожу этот -разбор как **r2** по §2.10, с бюджетом 1/4 (жёлтый r1 цикл потратил), а не как -первый заход. Это находка процесса инфраструктуры запуска ревью, а не находка -по ТЗ #306 — упомянута для трассируемости, отдельный issue не заводится (не -продуктовый дефект, а несовпадение параметра одного прогона). +Входные метаданные этого запуска указывали «Заход: r1 · блокирующих циклов +израсходовано 0 из 4». Фактическое состояние по GitHub и репозиторию другое — +и это тот же класс расхождения, который уже фиксировал `SPEC-REVIEW-306-r2.md` +для своего запуска: -## Закрытие раунда r1 +- `docs/reviews/SPEC-REVIEW-306-r1.md` (SHA `904c47e4`) — вердикт жёлтый, + High 0, Medium 3, опубликован комментарием issue (2026-08-25T16:49:42Z); +- `docs/reviews/SPEC-REVIEW-306-r2.md` (SHA `2c801bf5`) — вердикт зелёный, + High 0, Medium 0 (2026-08-25T16:57:24Z), спущен цикл §4 не тратил; +- после зелёного r2 задача ушла в разработку («Взял: Codex», 16:58:32Z), но + после rebase на `dev` реализация нашла продуктовый конфликт с только что + слитым #282 (comment 2026-08-26T00:18:24Z: model v8 уже материализует + каждый contour atom, включая старые тонкие стены, как `wall_segments[].cm=0`, + и единый default стиля по этому единственному `cm:0` бьёт по одной из двух + групп старых планов); +- владелец принял решение не вводить `zero_kind`/compatibility-marker + (2026-08-26T07:15:44Z) — стены неотличимы по происхождению, а не по решению + спецификации; +- автор переписал ТЗ под target model v9 на authoritative `wall_segments[]` + и явно передал «на независимое spec-review r3/4» (2026-08-26T07:22:47Z). -Вердикт r1 (документ `docs/reviews/SPEC-REVIEW-306-r1.md`, SHA `904c47e4`): -жёлтый, High 0, Medium 3, все в скоупе. - -| Находка r1 | Чем закрыта | Где это видно | -|---|---|---| -| **M1** — отсутствуют обязательные первые разделы «Сценарий» и «Что человек увидит до и после» (PROCESS.md §7.1) | Добавлены разделы 1 и 2 с персоной (администратор дома), поверхностью (Plan editor, десктоп), моментом (рисование/толщина/настройка пространства) и однофразовым «до/после» без терминов реализации, со ссылкой на J4/J6 `docs/SCOPE.md` | `docs/specs/306-zero-thickness-walls.md:9-25` | -| **M2** — `docs/USER-GUIDE.ru.md` не назван в §14/§17 (старая нумерация) | RU user-guide явно добавлен в список затронутых модулей и в release-артефакты | `docs/specs/306-zero-thickness-walls.md:444-445` (§16) и `:634` (§19) | -| **M3** — §4.2 предлагал несуществующие статусы реестра `project-in-memory`/`migrate-on-structural-write` | Текст заменён на существующие статусы `deprecated-read` (compatibility-read) и `migrate-on-write` (structural-write/Optimize/import); проверено против `docs/CONFIG-COMPATIBILITY.md` («Status meanings», строки 37-46) и `scripts/config-field-registry.mjs` (`CONFIG_FIELD_STATUSES`, строки 278-284; прецедент `open_to` уже зарегистрирован как `deprecated-read`, прецедент `settings.show_all` — как `migrate-on-write` с идентичным паттерном «read until materialisation, затем удаление») | `docs/specs/306-zero-thickness-walls.md:153-156` (§6.2) | - -Все три Medium закрыты по содержанию, не декларативно. Побочный эффект -правки — весь документ перенумерован (вставка двух разделов в начало сдвинула -остальные на +2); проверено построчно (`grep '^## '`), что нумерация -последовательна 1…21 без дублей и пропусков, а все внутренние ссылки `§13`, -`§15`, `§17` (было `§11`, `§13`, `§15`) обновлены синхронно и указывают на -верные разделы (Производительность, i18n, Acceptance criteria -соответственно). Это ровно тот случай из §2.10, когда правка по замечанию -может незаметно сломать нечто, признанное верным в r1 — здесь не сломала. - -## Унаследовано из r1 - -Без повторной проверки в этом раунде принято (документ -`docs/reviews/SPEC-REVIEW-306-r1.md`, SHA `904c47e4`, полный разбор был первым -заходом, §2.10 неприменим к нему самому): - -- соответствие `docs/SCOPE.md` (J4/J6), отсутствие конфликта с out-of-scope; -- фактические утверждения ТЗ о текущей системе — диапазоны `cm` в - `validation.py` (1..100 для walls/room_drafts/partitions, 1..150 для - wall_columns), `PLAN_MODEL_VERSION=7`, лимиты `MAX_* = 500`, состав - существующих модулей §16 (кроме новой строки про `USER-GUIDE.ru.md`, которая - не техническое утверждение, а release-чеклист, закрыта в этом раунде выше); -- соответствие `docs/LIGHT.md` (opaque/transparent boundary), `docs/TOUCH-SUPPORT.md` - (editors desktop-first, View/kiosk blocking floor), полный учёт обоих - комментариев владельца (таблица светового режима §4 п.4, единый resolver - §5.3/§9.1); -- однозначность и проверяемость AC1–AC18 — содержание AC не менялось в этой - правке (менялись только номера разделов, на которые AC ссылаются, и они - проверены выше как согласованные); -- отсутствие открытых продуктовых вопросов к владельцу. - -Дельта этого раунда не задевает доказательства AC1–AC18 по существу (их текст -не тронут), поэтому они не разбирались заново по существу, только сверка -пересчитанных ссылок на разделы, что сделано. +Возврат в работу между r2 и этим запуском не был вердиктом ревью с +блокирующими находками — он вызван конфликтом, обнаруженным в реализации +после слияния #282, поэтому по определению цикла (§4: «отправка на ревью → +вердикт с блокирующими находками → возврат») бюджет циклов между r2 и этим +запуском не тратится. Итого до этого вердикта: 1 цикл израсходован (жёлтый +r1), r2 — зелёный, не тратит. Провожу разбор как **r3** по фактическому +состоянию GitHub, а не как первый заход. Это находка процесса запуска +ревью, а не находка по содержанию ТЗ #306 — отдельный issue не заводится +(параметр одного прогона, не продуктовый дефект). ## Скоуп этого раунда -Предмет — дельта `git diff 904c47e4..HEAD -- docs/specs/306-zero-thickness-walls.md` -(112 строк изменено из 654 исходных: три точечные правки плюс механический -сдвиг нумерации разделов). Дельта локальна: не ребейз (issue-ветка не -отставала от `dev` на этом файле), не смена контракта поведения, не новая -подсистема, объём — 17% документа, не сопоставим с исходной задачей. Полный -повторный разбор не требуется по критериям §2.10. +Дельта между r2 (`2c801bf5`) и текущим HEAD (`abbd4904`) — **не локальна** по +критерию §2.10: `git diff 2c801bf5..abbd4904 -- docs/specs/306-zero-thickness-walls.md` +даёт 136 добавленных / 87 удалённых строк (≈31% документа), и это правка, +которая **задевает новую подсистему** — целевую модель хранения меняет с +плоской `space.walls[]`/`open_spans` (v7) на authoritative +`space.wall_segments[]` со stable ID (v8, реализовано #282), а целевая версия +документа поднята с v8 до v9. Меняется контракт identity, миграции, лимитов и +нормализации — ровно тот случай, где §2.10 прямо предписывает полный разбор, +а не разбор по дельте. Провожу разбор целиком, с явным наследованием тех +частей r1/r2, которые модель v8/v9 не затронула по существу (см. раздел +«Унаследовано» ниже). ## Как проверялось -- `git diff 904c47e4..HEAD -- docs/specs/306-zero-thickness-walls.md` — - построчная сверка правки с текстом трёх находок r1. -- `grep -n '§[0-9]' docs/specs/306-zero-thickness-walls.md` и - `grep -n '^## '` — все перекрёстные ссылки на разделы после перенумерации - указывают на правильные заголовки (§13 Производительность, §15 i18n, §17 - Acceptance criteria); последовательность заголовков 1…21 без дублей/пропусков. -- `docs/CONFIG-COMPATIBILITY.md:37-46` и `scripts/config-field-registry.mjs` - (полный файл) — подтверждено, что `deprecated-read`/`migrate-on-write` - существуют в `CONFIG_FIELD_STATUSES` и что использование этой пары для - `open_spans`/`open_to` соответствует реальному прецеденту в реестре - (`spaces[].rooms[].open_to` уже `deprecated-read`; `settings.show_all` — - `migrate-on-write` с аналогичным жизненным циклом read-until-materialise). -- `docs/specs/306-zero-thickness-walls.md:444-445,634` — прямая проверка - присутствия `docs/USER-GUIDE.ru.md` в обоих списках. -- `node --test test/docs-accept.test.mjs test/process-gate.test.mjs` — 38 - passed, 0 failed, 0 skipped (на Linux; автор указал 37 passed + 1 - Windows-only expected skip — тот же тест, различие чисто по площадке, не - расхождение). -- `gh issue view 306 --repo Matysh/houseplan-card --json ...,comments` — - прочитаны все 5 комментариев целиком, включая хендофф правок r1 (16:52:05Z). -- `git log --oneline`, `git show --stat` на `ec76d3b1` и `2c801bf5` — оба - коммита содержат только заявленные файлы (сам ТЗ; предыдущий раунд — только - документ ревью), трейлеры `Issue: #306` / `User-Visible: no` корректны для - документации. -- Продуктовое рассуждение: перечитаны оба комментария владельца и сверены с - текущим текстом ТЗ построчно (единый resolver, оба световых контура, - атомарность настройки на пространство, отсутствие фиктивной толщины, - parity View/iso/export, i18n-копия, тестовая матрица) — все восемь пунктов - дополнения владельца отражены в разделах §5.3, §7.4, §8.1, §9, §14, §15 и - AC1–AC18. +Технические утверждения ТЗ о текущей системе проверены по коду и документам, +не приняты со слов автора: + +- `git show --stat` / `git log --follow` на историю issue #306: коммиты + `dc6d0aaf`, `41469d0a`, `0436850d`, `20070a75`, `abbd4904` и все 11 + комментариев issue прочитаны целиком (`gh issue view 306 --json body,comments`); +- `custom_components/houseplan/const.py:54` и `src/plan-optimizer.ts:42` — + `PLAN_MODEL_VERSION = 8` подтверждён как текущий (не 7, как было на момент + r1) — согласуется с заявленным ТЗ переходом «v8 → v9»; +- `src/wall-thickness.ts:215` — `clampWallCm` существует, используется в + местах, которые ТЗ требует сделать zero-aware (АС2/АС11); +- `custom_components/houseplan/validation.py:1394-1405` — + `WALL_SEGMENT_SCHEMA.cm` уже `Range(min=0, max=100)` (backend принимает + `cm:0` для `wall_segments[]` уже сейчас, после #282); `ROOM_DRAFT_SCHEMA` + (:1425) и `PARTITION_SCHEMA` (:1448) — всё ещё `Range(min=1, max=100)`, + `WALL_COLUMN_SCHEMA` (:1471) — `Range(min=1, max=150)`. Формулировка §6.1 + ТЗ («Backend принимает cm: 0..100 для wall_segments[], room_drafts[] и + partitions[]») соответствует действительности как целевое состояние: часть + уже верна, часть (`room_drafts`, `partitions`) требует правки — ТЗ не + выдаёт частично готовое за полностью новое; +- `custom_components/houseplan/validation.py:1038-1070` — прямая проверка + лимитов, см. находку M1 ниже; +- `docs/specs/282-stable-wall-segment-identity.md` (§6.5, AC7, разделы про + `walls[]` compatibility projection) — подтверждает заявления ТЗ §5.2 о том, + что `space.walls[]` уже сейчас генерируемая проекция, а не источник истины, + и что `wall_segments[]` уже authoritative для identity; +- `scripts/config-field-registry.mjs:206-219` и + `docs/CONFIG-COMPATIBILITY.md:37-46` — `spaces[].rooms[].open_to` уже + зарегистрирован как `deprecated-read`; статусы `deprecated-read`/ + `migrate-on-write`, на которые ссылается §6.2 ТЗ, существуют в реестре; +- `docs/USER-GUIDE.ru.md` — grep `Граница` подтверждает, что инструмент + документирован (строки 432, 483, 537, 1510 и др.) и требует правки, что ТЗ + фиксирует в §16/§19; +- `docs/TOUCH-SUPPORT.md` — формулировки «desktop-first», «best effort» + совпадают с §14 ТЗ; +- `src/open-spans.ts` (781 строк) и `sharedBoundary` (найден в 5 файлах, + включая `src/logic.ts`) существуют — ссылки §5.3/§10 п.2 на существующий + resolver не выдуманы; +- `node --test test/docs-accept.test.mjs test/process-gate.test.mjs` — 40 + passed, 0 failed, 0 skipped (Linux; ближе к последней ревизии автора, + который называл 37/39 passed + ожидаемый Windows-skip — разница чисто по + площадке и времени, не расхождение); +- `ls demo/smoke_*.mjs | wc -l` = 192 — для справки; новых смоков в этом ТЗ + не требуется прогонять (спецификация, не код), упомянуто в §17/§18 ТЗ как + будущий gate код-ревью. + +## Закрытие раунда r2 + +r2 (`docs/reviews/SPEC-REVIEW-306-r2.md`, SHA `2c801bf5`) был **зелёным**, +High 0, Medium 0 — открытых находок к закрытию в этом раунде нет. Все три +находки r1 (M1 разделы «Сценарий»/«Что человек увидит», M2 отсутствие +`USER-GUIDE.ru.md`, M3 несуществующие статусы реестра) были закрыты уже в r2 +и остаются закрытыми: соответствующий текст (§1-2, §16/§19 упоминания +`USER-GUIDE.ru.md`, §6.2 статусы `deprecated-read`/`migrate-on-write`) +присутствует и в текущей ревизии `abbd4904` — переработка под model v8 не +откатила ни одну из трёх правок (проверено построчно по текущему файлу, +номера строк указаны в разделе «Унаследовано»). + +## Унаследовано из r1/r2 + +Без повторной проверки по существу в этом раунде принято — переработка под +model v8 не касалась этих частей текстуально и по содержанию: + +- продуктовые решения владельца по световому режиму (таблица dashed/solid, + запрет фиктивной толщины, единый resolver для Glow и солнца, инвалидация + кэшей при переключении, RU/EN copy под селектором) — документы + `SPEC-REVIEW-306-r1.md`/`r2.md`, полностью проверены на SHA `904c47e4`/`2c801bf5`, + текст §4 п.4-7, §9.1, §15 текущей ревизии не отличается по смыслу; +- соответствие `docs/SCOPE.md` (J4/J6) и отсутствие конфликта с + out-of-scope — раздел 1 ТЗ не менялся по сути между r2 и r3; +- присутствие `docs/USER-GUIDE.ru.md` в §16/§19 (M2 r1) — строки 483-484, 682 + текущей ревизии; +- статусы compatibility-реестра `deprecated-read`/`migrate-on-write` (M3 r1) — + §6.2, строки 172-175 текущей ревизии, повторно подтверждены и в этом раунде + прямой проверкой реестра (см. «Как проверялось»), а не только по наследству; +- i18n-таблица §15 (ключи `space.zero_wall_*`, `toast.zero_wall_*`, + `gs.zero_walls_migrated`) — не менялась между r2 и r3, RU/EN парность есть; +- touch/accessibility требования §14 — не менялись по существу. + +Дельта r2→r3 не касается доказательств AC1, AC2, AC5, AC6, AC7, AC14, AC16 — +их текст либо не менялся, либо менялся только терминологически (ссылки на +`wall_segments[]` вместо `walls[]`) без изменения проверяемого поведения; они +не переразбирались заново по существу. AC3, AC4, AC8, AC9, AC10, AC11, AC12, +AC13, AC15, AC17 разобраны заново ниже, так как их доказательство прямо +зависит от модели v8/v9, миграции и лимитов. ## Находки -Нет находок уровня High или Medium в этом раунде. Все три Medium из r1 -закрыты по существу (см. таблицу выше), новых находок делта не вносит. +### M1 (Medium, в скоупе) — лимит `wall_segments[]` в ТЗ устарел и противоречит уже слитому #282 -Low, снятая ревьюером без правки: r1 отметил отсутствие консолидированного -блока «принято предположительно, поменять свободно» — в r2 он также не -появился отдельным блоком, но оставшиеся технические допущения (имя модуля -`src/zero-walls.ts`, разбиение `houseplan-card.ts`) явно помечены в тексте как -свободные для изменения (§5.3, §16). Дальнейшая консолидация не даёт -дополнительной проверяемости — снимаю находку окончательно, как и в r1. +ТЗ трижды называет лимит записей числом **500**: + +- §10 шаг 10: «При превышении 500 `wall_segments[]` или любого лимита отказать целиком» (`docs/specs/306-zero-thickness-walls.md:352`); +- §13: «Лимит записей остаётся 500; результат не truncates» (`:423`); +- §17 AC13: «Лимит 500, invalid span, opening conflict или revision conflict отклоняет весь candidate» (`:604`); +- §20, риск «Atomization превысит лимит» → «atomic failure, no truncation» — привязан к той же цифре. + +Фактический предел `MAX_WALL_SEGMENTS` в `custom_components/houseplan/validation.py:1048` +равен **200 000**, не 500. Это не опечатка автора, а устаревший факт: до #282 +`MAX_WALLS` действительно был `500` (подтверждено `git log -p -S +"MAX_WALL_SEGMENTS"`, коммит `b336eee9`: `-MAX_WALLS = 500` / +`+MAX_WALLS = 200_000` / `+MAX_WALL_SEGMENTS = 200_000`, с комментарием в коде +«v8 atomises room boundaries» — лимит был поднят именно потому, что +атомизация контура увеличивает число записей). Ревью r1 (2026-08-25T16:49, +до слияния #282 в `dev`) корректно зафиксировало «лимиты `MAX_* = 500`» как +факт **на тот момент**. #306 переписан под model v8 (после слияния #282, +комментарий 2026-08-26T00:18) и в остальном тексте последовательно опирается +на `wall_segments[]` как authoritative-каталог (§5.2, §6.1, §16) — но +конкретно эту цифру ревизия «adapt to model v8» не обновила ни в одном из +четырёх мест. + +Отдельно — `MAX_OPEN_SPANS = 500` (:1056) действительно равен 500, но это +предел удаляемого этим же ТЗ поля `open_spans`, а не `wall_segments[]`; ни +`docs/specs/282-stable-wall-segment-identity.md`, ни код не подтверждают +цифру 500 для итогового каталога — собственный perf-бенчмарк #282 оперирует +масштабом 10 000 атомов (`docs/specs/282-...md:431`), на два порядка выше. + +**Почему это Medium, а не Low:** формулировка не «уточнить», а прямое +техническое утверждение, встроенное в проверяемый AC13 и в шаг миграции §10 — +если реализовать буквально, миграция/Optimize начнёт отказывать легитимным +пространствам, которые #282 уже поддерживает (200 000 записей), то есть ТЗ, +как написано, предписывает регресс уже принятой возможности. Это не открытый +продуктовый вопрос (владельцу нечего решать — предел объективно другой), и не +блокирует понимание архитектуры документа — значит, не High. Правка +механическая: заменить «500» ссылкой на актуальный `MAX_WALL_SEGMENTS` +(200 000) или убрать конкретное число из §10/§13/§20 и оставить «действующий +лимит записей», сохранив только в AC13 существующее поведение «превышение +лимита отклоняет весь candidate целиком». + +### Снято с записью (Low, не требует правки) + +Как и в r1, в документе нет одного консолидированного блока «принято +предположительно, поменять свободно» (PROCESS.md §7.1) — часть технических +допущений оформлена инлайн с пометками свободы («имя можно уточнить без +изменения контракта», §5.3), часть — как явные решения с обоснованием. Ревью +r1 уже приняло этот формат как достаточный при отсутствии открытых +продуктовых вопросов; в этом раунде замечание не переоткрывается. + +## AC, разобранные заново (затронуты моделью v8/v9) + +- **AC3** (единая семантика всех `cm:0`) — соответствует принятому владельцем + 2026-08-26T07:15:44Z решению не вводить `zero_kind`; текст АС и §5.2/§10 + п.5 согласованы, критерий проверяемый (source-contract + смешанная v8 + fixture). +- **AC4, AC8, AC9, AC11** — используют authoritative `wall_segments[]` и + lineage #282 корректно (§8.1, §8.3, §10 п.3-4); ссылки на «lineage #282» + соответствуют реально реализованному identity barrier (`docs/specs/282-...md` + §6.5 и далее). +- **AC10** — защита проёмов на миграции распространена на **все** итоговые + `cm:0` (§10 п.6), не только на бывшие legacy spans — корректно закрывает + edge case, который отдельно требовала аналитика (comment 0, «Перевод + физического участка с уже размещённым проёмом»). +- **AC12** — read-only и mutation-gate формулировка не изменилась по смыслу + относительно v7-версии, применима к v8/v9 без правок. +- **AC13** — проверена выше в M1: текст в остальном (atomic transaction, no + partial apply, one-deep Undo) корректен и соответствует §10.1; конкретная + цифра лимита — единственный дефект. +- **AC15** — соответствует текущему backend-состоянию (см. «Как проверялось»): + `wall_segments[]` уже принимает `cm:0`, `room_drafts`/`partitions` требуют + правки диапазона — AC формулирует именно это, без завышения того, что уже + сделано. +- **AC17** — бюджеты §13 корректно исключают лимит 500 из перф-раздела нет, + see M1; сам перф-контракт (fingerprint по `space id + geometry revision + + zero_wall_style`, отсутствие rebuild на HA state tick) сформулирован + однозначно и проверяем benchmark-артефактом. ## Что проверено и корректно -- Все три Medium-находки r1 закрыты содержательно, а не декларативно — - проверено чтением кода/документации-источника (`validation.py`, - `config-field-registry.mjs`, `CONFIG-COMPATIBILITY.md`), а не доверием - тексту ТЗ. -- Перенумерация разделов не создала битых перекрёстных ссылок и не задела - содержание AC1–AC18. -- Документ по-прежнему полностью отвечает DoR §2.5: пронумерованные AC с - доказательством, миграция и compatibility решены (теперь корректно), i18n - RU/EN перечислены, touch/performance названы, откат описан, открытых - продуктовых вопросов нет. -- Соответствие `docs/SCOPE.md` (J4/J6) и обоим комментариям владельца — из r1, - делта его не меняет. +- Оба продуктовых раздела §7.1 (сценарий, что человек увидит) присутствуют + и не описывают реализацию; +- открытых продуктовых вопросов к владельцу нет, оба его решения (комментарии + 2026-08-25T15:10:53Z о световом режиме пространства и 2026-08-26T07:15:44Z + о запрете `zero_kind`) полностью отражены в §4 и §5.2; +- модель v8/v9 описана не как догадка, а с явной опорой на уже слитый #282, + и эта опора проверена по факту (не по заявлению автора) в разделе «Как + проверялось»; +- AC1-AC18 пронумерованы, у каждого указан способ доказательства + (unit/backend/smoke/golden/perf), формулировки однозначны; +- release-артефакты (§19) включают оба changelog, оба user-guide, канонические + документы подсистем (WALL-THICKNESS, LIGHT, CONFIG-COMPATIBILITY, + ARCHITECTURE, STATUS) и явно требуют bundle sync — соответствует PROCESS.md + §8 и §11.2 таблице класса D; + i18n-таблица симметрична RU/EN, включает пояснение под селектором отдельным + ключом (не только tooltip), что было прямым требованием владельца; +- откат (§12) отдельно разбирает forward compatibility и invalid-downgrade, + без Labs-флага — обоснование («две одновременно пишущие модели — больший + риск, чем флаг снимает») продуктово осмысленно и не противоречит + `docs/CONFIG-COMPATIBILITY.md`; +- зависимости (§21) корректно называют #282 как реализованную основу и не + претендуют на дублирование её identity-writer; #148/#173 помечены как + требующие superseded-note, а не тихо игнорируются. ## Чего не проверял -- Полный повторный разбор AC1–AC18 по существу (не требуется по §2.10: их - текст дельта не касается, только номера ссылок на другие разделы). -- Код — этап spec-review, кода к задаче ещё нет. -- Тяжёлые гейты (smoke/golden/backend/performance) — неприменимо к этапу ТЗ и - к classу C diff (только документация); прогнаны только дешёвые - документационные тесты (`docs-accept`, `process-gate`), как и в r1. -- `docs/specs/README.md` — колонка ссылки на `306-zero-thickness-walls.md` на - месте, но известная проблема с дублирующей колонкой «Статус ТЗ» (PROCESS.md - §7.3 п.1) не в скоупе этой задачи и не проверялась повторно. +- Не прогонялись `npm run typecheck`/`npm test`/`npm run build` — на этапе + ревью ТЗ src не менялся, эти гейты относятся к код-ревью (PROCESS.md §2.7, + §8) и здесь неприменимы; +- не прогонялись browser-смоки, golden, `python -m pytest tests_backend` — + код отсутствует, нечего исполнять; упомянутые в ТЗ файлы тестов + (`test/zero-wall-migration.test.mjs`, `demo/smoke_zero_walls.mjs` и др.) + ещё не существуют, это ожидаемо для стадии спеки; +- не проверялась математика perf-бюджетов §13 (p95 +10%/+5%) эмпирически — + оценена только как формулируемая и измеримая величина, без числового + прецедента на реальном large-house fixture; +- не проверялись все 21 раздел построчно на перенумерацию (в отличие от r2, + где это было предметом дельты) — в этом раунде перенумерации не было, + структура документа (1…21) стабильна между `2c801bf5` и `abbd4904`, что + подтверждено `grep -n '^## '` без более глубокой сверки каждой + внутренней `§N`-ссылки за пределами тех, что упомянуты выше. ## Вердикт -Зелёный. Три Medium-находки r1 закрыты по существу, ни одна не оставлена как -TODO. Новых High/Medium делта не создала. ТЗ готово к разработке. +Одна находка Medium (M1, в скоупе, устаревший лимит `wall_segments[]`), +High — нет. По PROCESS.md §2.4/§4 это жёлтый вердикт: автор правит текст в +трёх/четырёх местах (§10 п.10, §13, §17 AC13, §20), фикс проходит повторный +раунд ревью по дельте (§2.10, дельта в этом случае локальна — правка одной +цифры и её контекста, не новая подсистема). + +**Вердикт: жёлтый · заход r3 · блокирующих циклов 2/4 · High: 0 · Medium: 1 → в задаче**