Files
houseplan-card/docs/reviews/SPEC-REVIEW-252-r2.md
T
2026-08-23 08:06:22 +00:00

165 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW-252-r2
- Issue: [#252](https://github.com/Matysh/houseplan-card/issues/252) — «Отчёт
"Оптимизировать" перечисляет внутренние id вместо того, чтобы починить или
сказать, что делать»
- Этап: spec (PROCESS.md §2.4)
- Заход: r2 · блокирующих циклов израсходовано 1 из 4 (зелёный вердикт r2
бюджет не тратит, #227)
- ТЗ: `docs/specs/252-optimize-orphan-layout-report.md`, коммит `0e4a562`
(HEAD), ветка `issue/252-optimize-orphan-layout-report`
- Трек: обычный (не `small`/`trivial`)
- Предыдущий раунд: [SPEC-REVIEW-252-r1](https://github.com/Matysh/houseplan-card/blob/issue/252-optimize-orphan-layout-report/docs/reviews/SPEC-REVIEW-252-r1.md)
(закоммичен в `2fbab95`), вердикт **жёлтый**, ТЗ на момент этого вердикта —
коммит `883a95a`
## SHA этого раунда (§2.10 п.1)
r1 не назвал SHA в тексте вердикта (issue-комментарий), но назвал его в самом
документе ревью: «ТЗ: …, коммит `883a95a`». Это не пропуск — шаблон вердикта
из PROCESS.md §7.2 не требует SHA в комментарии, а документ его содержит.
Восстановленная цепочка коммитов веток `issue/252-optimize-orphan-layout-report`:
```
883a95a docs: specify orphan layout cleanup — ТЗ на момент r1
2fbab95 docs: review document for #252 — вердикт r1 (жёлтый, M1)
0e4a562 docs: clarify orphan cleanup invariant — фикс M1 (HEAD, этот раунд)
```
`git diff 883a95a..2fbab95` меняет только `docs/reviews/SPEC-REVIEW-252-r1.md`
(добавление документа ревью, ТЗ не тронуто). `git diff 2fbab95..0e4a562` —
единственный файл спецификации, +17/-2 строки. Дельта этого раунда — ровно
этот второй диапазон.
## Дельта раунда (§2.10 п.2)
```
diff --git a/docs/specs/252-optimize-orphan-layout-report.md
--- (883a95a) +++ (0e4a562)
@@ §3, после абзаца про недостаточность "id отсутствует в config.markers" @@
+ Это осознанно **заменяет**, а не дополняет, прежний абсолютный инвариант из
+ `docs/CANVAS.md:494-497` ... То же консервативное обещание было опубликовано
+ в английском changelog для v1.59.0-rc.1. ... При реализации старое
+ предложение в `CANVAS.md` должно быть переписано новым доказательным
+ контрактом, а не оставлено рядом с ним.
@@ §13, список release-артефактов @@
- `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md` со ссылкой на #252;
+ `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md` со ссылкой на #252 и явным
+ пояснением, что прежнее полное сохранение unattached layout entries из
+ v1.59.0-rc.1 сужено: ...
- `docs/CANVAS.md` — owner classification и идемпотентность cleanup;
+ `docs/CANVAS.md` — **заменить**, не дополнить, старое предложение строк
+ 494–497 «does not ... delete unattached layout entries» новым owner
+ classification/fail-closed контрактом и идемпотентностью cleanup;
```
Дельта строго локальна: два вставленных абзаца внутри §3 (диагноз) и §13
(release-артефакты). Она не трогает §4 (цели), §5 (scope/не-scope), §6-7
(контракт классификации и поведения), §8-12 (данные, UX, AC1-AC8, план
тестов, риски) и §14 (принятые предположения). Это не ребейз на ушедший
вперёд `dev`, не смена контракта поведения (контракт удаления уже был описан
в §4/§6.2/§7.1 исходной редакции и не менялся — меняется только то, как ТЗ
называет отношение к старому инварианту CANVAS.md) и не новая подсистема.
Условия «разбирать полностью» (§2.10) не выполнены — разбор по дельте.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** (Medium, в скоупе): ТЗ вводит поведение, обратное задокументированному в `docs/CANVAS.md:494-497` инварианту («deliberately does not ... delete unattached layout entries») и опубликованному в `docs/CHANGELOG.md` (v1.59.0-rc.1, «unattached layout entries ... are left alone»), не называя явно, что это замена, а не дополнение | Автор добавил в §3 абзац с прямой ссылкой на `docs/CANVAS.md:494-497` и на changelog-запись v1.59.0-rc.1, словом «заменяет» (не «дополняет»); в §13 бюллет `docs/CANVAS.md` явно требует «заменить, не дополнить» старое предложение строк 494–497, а бюллет CHANGELOG требует явно описать сужение старого обещания | `docs/specs/252-optimize-orphan-layout-report.md:61-69` (§3) и `:342-350` (§13), коммит `0e4a562` |
Проверка не ограничена заявлением автора: сверил оба цитируемых источника
построчно.
- `docs/CANVAS.md:493-497` (текущее состояние репозитория) содержит именно ту
формулировку, которую ТЗ цитирует: «The optimizer deliberately does **not**
alter … delete unattached layout entries (a device may only be temporarily
unavailable) …» — совпадает буквально.
- `docs/CHANGELOG.md:1373-1385` (`## v1.59.0-rc.1 — 2026-08-06`) содержит
«Backdrop calibration, saved views, unattached layout entries and user
files are left alone.» — совпадает буквально, включая номер релиза.
Обе цитаты в ТЗ точны, ссылки на строки/релиз верны, требование «заменить, не
дополнить» сформулировано без места для двойного толкования при реализации.
M1 закрыт полностью, находка не переоткрывается.
## Унаследовано из r1
Принято без повторной проверки в этом раунде, на основании
[SPEC-REVIEW-252-r1](https://github.com/Matysh/houseplan-card/blob/issue/252-optimize-orphan-layout-report/docs/reviews/SPEC-REVIEW-252-r1.md)
(документ закоммичен в `2fbab95`, ТЗ на момент вывода — `883a95a`), поскольку
дельта этого раунда не касается ни одного из этих участков:
- полнота обязательных разделов ТЗ по PROCESS.md §7.1 (все присутствуют,
включая блок принятых предположений §14);
- построчное соответствие диагноза (§3, часть до вставленного абзаца) коду
(`space-reference-repair.ts`, `_renderAlignDialog`, `ha-binding-status.ts`,
i18n) — диагноз не является догадкой, выданной за факт;
- исчерпывающая классификация владельцев (§6): `rl_`, marker-id/`lg_`,
unknown — других префиксов layout-ключей в коде нет;
- техническая база fail-closed authority (`HaRegistrySnapshot.authoritative`)
уже существует и используется в проде;
- однозначность и способ доказательства AC1–AC8;
- соответствие не-скоупа (§5) реальному объёму issue;
- полнота списка release-артефактов §13 (кроме изменённых двух бюллетов —
они проверены заново выше);
- согласованность safety-контракта с правилом SCOPE.md «never delete a
user's file on an inference»;
- отсутствие технических вопросов, поданных владельцу как продуктовые;
- корректность решения не применять `small`/`trivial`.
## Проверка дельты — новые находки
Дельта не вводит новых противоречий и не расширяет скоуп:
- новый текст §3 и §13 ссылается только на уже существующие в репозитории
документы (`docs/CANVAS.md`, `docs/CHANGELOG.md`) точными номерами строк и
релиза — проверено выше, не догадка;
- формулировка «заменить, не дополнить» однозначна для будущей реализации —
не оставляет решение на усмотрение имплементора и не создаёт риска
дублирующего абзаца в каноническом документе, на который указывал M1;
- изменение не открывает нового продуктового вопроса: замена инварианта
CANVAS.md — прямое следствие уже принятого в §4/§6.2 контракта удаления
доказанно отсутствующих владельцев (сам контракт не менялся этим раундом,
и его принятие исходно инициировано владельцем в теле issue #252);
- AC1–AC8, scope, UX и risk-раздел не затронуты дельтой и не требуют
повторной проверки по правилу «только те AC, чьё доказательство дельта
задевает» (§2.10 п.4) — дельта не касается доказательства ни одного AC.
Находок в этом раунде нет: ни High, ни Medium, ни Low.
## Что проверено и корректно
- Дельта раунда полностью соответствует объёму, который M1 требовал закрыть:
явная ссылка на источник + слово «заменяет» + требование к release-артефакту.
- Обе цитаты (CANVAS.md, CHANGELOG.md) сверены с текущим состоянием
репозитория и совпадают буквально.
- SHA обеих сторон дельты восстановлены из истории ветки и подтверждают
заявление автора комментарием («M1 закрыт в `0e4a562`»).
- Раздел «Унаследовано из r1» покрывает всё, что не перепроверялось в этом
раунде, со ссылкой на документ и SHA r1.
## Чего не проверял
- Не проверял production-код реализации — задача остаётся на этапе
`S4-spec-review`, кода ещё нет.
- Не запускал `typecheck`/`test`/`build`/`check-docs` — раунд правит только
документацию ТЗ (`docs/specs/**`), класс C по AGENTS.md, код не менялся;
дешёвые гейты релевантны код-ревью, а не ревью ТЗ без единой строки в `src/**`.
- Не перечитывал заново разделы §4-§12, не тронутые дельтой — см. раздел
«Унаследовано из r1» с указанием документа и SHA, на которых вывод получен.
- Не проверял `docs/ARCHITECTURE.md`, `docs/UX-MODES.md`, `docs/TOUCH-SUPPORT.md`
построчно — то же основание, что в r1: эти документы дельтой не затронуты и
не переопределяются.
## Вердикт
Единственная находка предыдущего раунда (M1, Medium, в скоупе) закрыта точной,
проверяемой правкой текста ТЗ, без изменения технического контракта. Новых
находок дельта не вносит.
**Зелёный.** ТЗ переходит в «Готово к разработке».
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0