mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 13:18:58 +00:00
163 lines
14 KiB
Markdown
163 lines
14 KiB
Markdown
# 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 → в задаче**
|