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

13 KiB
Raw Blame History

SPEC-REVIEW-252-r2

  • Issue: #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 (закоммичен в 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 (документ закоммичен в 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