docs: review document for #306

Issue: #306
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-26 12:55:27 +03:00
committed by Matysh
parent fa9d9b05e9
commit 5e35612bdd
+162
View File
@@ -0,0 +1,162 @@
# SPEC-REVIEW-306-r4
- **Issue:** [#306](https://github.com/Matysh/houseplan-card/issues/306) — Редактор плана: заменить виртуальные стены обычными стенами толщиной 0
- **Этап:** ревью ТЗ (PROCESS.md §2.4, повторный раунд — §2.10)
- **Заход:** r4 · блокирующих циклов израсходовано (до этого вердикта) 2 из 4
- **ТЗ:** `docs/specs/306-zero-thickness-walls.md`, HEAD ветки `issue/306-zero-thickness-walls` = `3d7395abc354b072d4ed8ae48809972509dde41` («docs: align zero-wall spec limits»)
- **Метка issue:** `S4-spec-review` (полный трек, не `small`/`trivial`)
## Расхождение метаданных запуска с фактическим состоянием issue (процессная находка, не по ТЗ)
Входные метаданные этого запуска указывали «Заход: r2 · блокирующих циклов
израсходовано 1 из 4». Это не совпадает с состоянием GitHub — тот же класс
расхождения, который уже фиксировали `SPEC-REVIEW-306-r2.md` и
`SPEC-REVIEW-306-r3.md` для своих запусков:
- r1 (`904c47e4`) — жёлтый, High 0, Medium 3 (2026-08-25T16:49:42Z) — 1 цикл;
- r2 (`2c801bf5`) — зелёный, High 0, Medium 0 (2026-08-25T16:57:24Z) — цикл не тратит;
- r3 (SHA на момент ревью не разрешается локально: документ r3 называет
`abbd4904`, этот коммит недостижим в текущей истории — по датам и
содержимому (то же сообщение «docs: adapt zero-wall spec to model v8»,
2026-08-26T07:21:56+03:00) это переписанный при rebase-на-`dev` эквивалент
коммита `9283d2ee`; между r2 и r3 в лог влиты посторонние коммиты `dev`,
например `93054823`, что и есть след rebase) — жёлтый, High 0, Medium 1
(M1: устаревший лимит `500` вместо `MAX_WALL_SEGMENTS=200000`),
2026-08-26T07:31:54Z — 2-й цикл;
- автор исправил M1 в `3d7395ab` («docs: align zero-wall spec limits»,
2026-08-26T07:33:20+03:00) и передал «на финальный spec-review r4/4»
(2026-08-26T07:33:36Z).
Провожу разбор как **r4** по фактическому состоянию GitHub, а не как r2.
Это находка процесса запуска ревью, а не находка по содержанию ТЗ #306 —
отдельный issue не заводится (параметр одного прогона, не продуктовый
дефект, прецедент — сам этот issue в r2/r3).
## Скоуп этого раунда
Дельта между содержимым, разобранным в r3 (эквивалент `9283d2ee`), и текущим
HEAD (`3d7395ab`):
```
git diff 9283d2ee..3d7395ab -- docs/specs/306-zero-thickness-walls.md
```
даёт 11 изменённых строк в трёх местах документа (§10 шаг 10, §13, §17 AC13) —
ровно та правка, которую предписал вердикт r3 для закрытия M1. Правка не
меняет ни одного контракта поведения, не задевает новую подсистему и не
сопоставима по объёму с исходной задачей — это учебный пример локальной
дельты по критерию §2.10. Разбор по дельте: заново проверено только M1 и
AC13/§10/§13, чьё доказательство эта правка задевает; остальное — раздел
«Унаследовано».
## Как проверялось
- `git diff 9283d2ee..3d7395ab -- docs/specs/306-zero-thickness-walls.md` —
единственный источник дельты, прочитан целиком построчно;
- `grep -n '\b500\b' docs/specs/306-zero-thickness-walls.md` — пусто:
устаревшая цифра из трёх мест M1 (§10 п.10, §13, §17 AC13) удалена
полностью, замена на `` `MAX_WALL_SEGMENTS` (сейчас 200 000) `` /
«любого другого актуального backend-лимита»;
- `custom_components/houseplan/validation.py:1047-1048` —
`MAX_WALLS = MAX_WALL_SEGMENTS = 200_000` подтверждено текущим кодом
(та же строка, что и в r3, повторно проверена — правка ссылается на
реальную константу, не на новую догадку); `:1056` `MAX_OPEN_SPANS = 500` —
как и в r3, это предел удаляемого поля, не итогового каталога, ТЗ его не
использует;
- §20 «Риски и защита» (строка «Atomization превысит лимит» → «atomic
failure, no truncation») уже была сформулирована без конкретной цифры —
делта её не касалась, четвёртое место M1 не требовало правки;
- `node --test test/docs-accept.test.mjs test/process-gate.test.mjs` —
41 passed, 0 failed, 0 skipped (Linux; автор указывал 40 passed + 1
ожидаемый Windows-skip — расхождение по площадке, не по существу);
- секции 1 «Сценарий» и 2 «Что человек увидит до и после» (закрытие M1 r1)
и ссылка на `docs/SCOPE.md` J4/J6 перечитаны на текущем HEAD (строки 9-26) —
дельта их не касалась, текст не откатился;
- `docs/SCOPE.md` — `J4`/`J6` существуют в документе (`grep -n "J4\|J6"`),
утверждение §1 не голословно.
## Закрытие раунда r3
| Находка r3 | Чем закрыта | Где видно |
|---|---|---|
| **M1** (Medium, в скоупе) — лимит `wall_segments[]` в ТЗ назван устаревшим числом `500` в трёх местах (§10 п.10, §13, §17 AC13), противоречит уже слитому #282 (`MAX_WALL_SEGMENTS=200_000`) | Все три места переписаны на именованную константу/обобщённую формулировку без хардкода цифры | `docs/specs/306-zero-thickness-walls.md:351-353` («При превышении `MAX_WALL_SEGMENTS` (сейчас 200 000) или любого другого актуального backend-лимита отказать целиком»), `:423-424` («Лимит authoritative-каталога остаётся равен backend-константе `MAX_WALL_SEGMENTS` (сейчас 200 000)»), `:605-606` AC13 («Превышение любого актуального backend-лимита… отклоняет весь candidate без truncation/partial apply») — коммит `3d7395ab` |
| Low, снято с записью r1/r3 (нет единого консолидированного блока предположений) | Не переоткрывается — r1 и r3 уже признали формат достаточным при отсутствии открытых продуктовых вопросов | без изменений в этом раунде |
Других находок r3 не было (High 0, Medium 1 — только M1).
## Унаследовано из r1/r2/r3
Без повторной проверки по существу в этом раунде — дельта `9283d2ee..3d7395ab`
их не касается ни текстуально, ни по содержанию:
- продуктовые решения владельца по световому режиму (таблица dashed/solid,
запрет фиктивной толщины, единый resolver для Glow и солнца, инвалидация
кэшей при переключении, RU/EN copy под селектором) — проверены в
`SPEC-REVIEW-306-r1.md`/`r2.md`/`r3.md` на SHA `904c47e4`/`2c801bf5`/
эквиваленте `9283d2ee`; §4 п.4-7, §9.1, §15 текущего файла не менялись;
- соответствие `docs/SCOPE.md` (J4/J6) и отсутствие конфликта с out-of-scope —
§1, §21 не в дельте;
- присутствие `docs/USER-GUIDE.ru.md` в §16/§19 (закрытие M2 r1) — строки
484, 683 текущей ревизии, не в дельте;
- статусы compatibility-реестра `deprecated-read`/`migrate-on-write`
(закрытие M3 r1) — §6.2, строки ~172-175, проверены в r3 прямым
обращением к `scripts/config-field-registry.mjs`/`docs/CONFIG-COMPATIBILITY.md`,
не в дельте r3→r4;
- целевая модель v8→v9 на authoritative `wall_segments[]`, stable ID/lineage
#282, backend-диапазоны `cm` для `wall_segments`/`room_drafts`/`partitions`/
`wall_columns` — проверены в r3 по коду (`validation.py`), эта дельта их не
меняет;
- AC1, AC2, AC3, AC4, AC5, AC6, AC7, AC8, AC9, AC10, AC11, AC12, AC14, AC15,
AC16, AC18 — не в дельте, наследуются из r3 без повторного разбора;
- i18n-таблица §15, touch/accessibility §14 — не в дельте;
- release-артефакты §19 (оба changelog, оба user-guide, канонические
документы подсистем) — не в дельте.
**AC13** и связанный текст §10 п.10, §13 — единственные места, разобранные
заново в этом раунде (см. «Как проверялось» и таблицу закрытия выше); AC17
(перф-бюджеты) перечитан целиком заново, так как его формулировка находится
в §13, но сам перф-контракт (fingerprint, отсутствие rebuild на HA tick,
benchmark-пороги) не изменился словом — дельта тронула только соседнюю
строку про лимит записей.
## Находки
Нет. High: 0, Medium: 0.
## Что проверено и корректно
- M1 закрыт по существу, не декларативно: три из трёх мест исправлены
идентичной по смыслу формулировкой, привязанной к реальной именованной
константе, а не к новому хардкоду; четвёртое упомянутое в r3 место (§20)
не требовало правки, так как не содержало числа;
- исправление не создало нового технического долга: вместо конкретной
цифры документ теперь ссылается на «текущий backend-лимит» — формулировка
переживёт будущее изменение константы без повторного устаревания;
- docs/process gate зелёный (`node --test test/docs-accept.test.mjs
test/process-gate.test.mjs` — 41/41);
- секции 1-2 (§7.1), ссылка на `docs/SCOPE.md`, i18n, touch, release-артефакты
не откатились и не пострадали от точечной правки — дельта минимальна и не
затронула соседний текст.
## Чего не проверял
- Не перепроверял AC1-AC12, AC14-AC18 по существу заново — они не в дельте
r3→r4 и не зависят от лимита `wall_segments[]`; их закрытие наследуется из
r3 (см. раздел «Унаследовано»);
- не прогонялись `npm run typecheck`/`npm test`/`npm run build`, browser-смоки,
golden, `python -m pytest tests_backend` — на этапе ревью ТЗ src не менялся
ни в этой дельте, ни в дельте r3→r4; это гейты код-ревью (PROCESS.md §2.7,
§8), здесь неприменимы;
- не проверял заново реестр `docs/CONFIG-COMPATIBILITY.md`/
`scripts/config-field-registry.mjs` — сделано в r3, дельта их не касается;
- не восстанавливал точную историю rebase (`abbd4904` → `9283d2ee`)
коммит-за-коммитом — установил только, что это тот же контент по времени,
сообщению коммита и последующему diff; для целей этого ревью достаточно,
что дельта М1 считается от контента, который r3 реально видел.
## Вердикт
M1 закрыт по существу на всех трёх упомянутых местах, новых находок дельта
не создала. High: 0, Medium: 0 — **зелёный**.
**Вердикт: зелёный · заход r4 · блокирующих циклов 2/4 · High: 0 · Medium: 0 → в задаче**