diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index 49742430..df5c1c9c 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,12 +1,13 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 271, issue: 138. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 272, issue: 139. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| | бета v1.79.0-beta.1 | [SHIP-REVIEW-v1.79.0-beta.1.md](SHIP-REVIEW-v1.79.0-beta.1.md) | пакетное ревью ship · — | ⚪ — | 0 | 0 | — | — | | #775 | [CODE-REVIEW-775-r1.md](CODE-REVIEW-775-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #772 | [CODE-REVIEW-772-r1.md](CODE-REVIEW-772-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | +| #762 | [SPEC-REVIEW-762-r1.md](SPEC-REVIEW-762-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | | #761 | [CODE-REVIEW-761-r1.md](CODE-REVIEW-761-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | заявленная «красная» мутация не воспроизводится в этой среде | `scripts/process-metrics.mjs` | | #757 | [CODE-REVIEW-757-r1.md](CODE-REVIEW-757-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #756 | [CODE-REVIEW-756-r1.md](CODE-REVIEW-756-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/docs/reviews/SPEC-REVIEW-762-r1.md b/docs/reviews/SPEC-REVIEW-762-r1.md new file mode 100644 index 00000000..09f3b4c9 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-762-r1.md @@ -0,0 +1,173 @@ +# SPEC-REVIEW-762-r1 + +Issue: #762 — «Warm remount и отложенный режим: хвосты после #756» +Этап: spec (PROCESS.md §2.4) · Трек: ask (§5) · Заход: r1 · блокирующих циклов 0/4 +Материал: тело issue #762, раздел `## ТЗ`, сверено с рабочей копией на +`0606a3664a6c819a501316f478840d6c3a5b456c` (HEAD; совпадает с актуализацией, +заявленной в самом ТЗ — «Актуализация по `dev` `0606a366...`»; Validate на +этом SHA зелёный). Код продукта в задаче ещё не писался — ревью судит только +текст ТЗ и его соответствие дереву, на которое он ссылается. +Route: fix. + +## Скоуп + +Пять связанных регрессий «тёплого» пересоздания карточки с отложенным правом +записи (хвосты после #756/#95): (1) выход из отложенного редактора теряет +исходный zoom/центр Просмотра; (2) камера дёргается на промежуточных кадрах +отложенного восстановления без открытого диалога; (3) в warm-памятку +попадает смешанная пара `hdrH`/`stageH` от разных layout; (4) позднее +`_resumePendingNavMode` перебивает уже отданную пользователем новую команду +режима; (5) смена пространства не отменяет ожидающее восстановление +редактора старого пространства. Служит J1/J6 `docs/SCOPE.md` — «план остаётся +верным» и «продолжить ту же работу после технического пересоздания»; новых +UI-элементов, настроек и touch-жестов редакторов нет, View/выбор пространства +на touch — обязательная поверхность и явно покрыты AC5. + +## Как проверялось + +Ревью ТЗ не включает выполнение гейтов — кода нет, этап его не требует. +Проверялись: наличие обязательных разделов §7.1; однозначность и способ +доказательства каждого AC; соответствие канону (`docs/WARM-REMOUNT.md`, +`docs/CANVAS.md`, `docs/SCOPE.md`, `docs/USER-GUIDE.ru.md`); и, так как и +ТЗ, и аналитический комментарий автора опираются на построчные ссылки на +код, — сверка каждой процитированной причины с реальным деревом на +материальном SHA, а не с заявлением автора. + +Построчно сверено чтением (не исполнением) с текущим деревом: + +| Утверждение ТЗ/комментария | Файл:строка | Проверено | +|---|---|---| +| `resumeWarmMode` удерживает камеру только при `_warmRevivePending`, случай без черновика выходит раньше защиты | `src/warm-mode-adoption.ts:55` (фактически строка `if (!host._warmRevivePending) return;`, код в файле сейчас на строке 58) | совпадает: ранний `return` действительно пропускает весь блок удержания `_view`/refit (строки 59–63), когда диалога нет | +| `_setMode` при входе из Просмотра в редактор перезаписывает `_viewModeSnap` текущей камерой, а не сохранённым warm-снимком | `src/houseplan-editor-runtime.ts:986` (блок `this.host._viewModeSnap = { ... zoom: this.host._zoom ... }`) | совпадает: присваивание читает `this.host._zoom`/`this.host._view` на момент вызова `_setMode`, т.е. временную камеру отложенного Просмотра, если вход идёт через `resumeWarmMode → commit()` | +| Обработчик шапки пишет новую `hdrH` вместе с `stage.clientHeight`, снятым до следующего рендера | `src/houseplan-card.ts:4068` (сейчас строка 4080: `this._warmPatch({ hdrH: t, stageH: stage.clientHeight })`) | совпадает: `stage.clientHeight` читается синхронно в том же колбэке, что и новое `t`, до того как layout успевает осесть под новой высотой шапки | +| Новая команда редактора не отменяет `_pendingNavMode` синхронно | `src/houseplan-card.ts:737` (`_requestMode`) | совпадает: по всему файлу `_pendingNavMode` читается/пишется только в четырёх местах (:3311 установка, :4164–4166 потребление в `_resumePendingNavMode`, :7368/:7439 disconnect-путь) — `_requestMode` его не трогает вовсе | +| Смена пространства не очищает pending | `src/houseplan-card.ts:1414` (`_commitSpace`) | совпадает: `_commitSpace` не ссылается на `_pendingNavMode` | +| `docs/NAV-PERSIST*` на dev отсутствует | — | совпадает: файла нет, упомянутое в исходном (внешнем) репорте название действительно устарело | +| `demo/smoke_nav_persist.mjs` существует и упомянут как часть материала | `demo/smoke_nav_persist.mjs`, `docs/WARM-REMOUNT.md:6` | совпадает | +| «View restores the saved same-space centre and zoom on exit» — контракт п. 2 ТЗ не противоречит канону | `docs/CANVAS.md:104–113` | совпадает дословно по смыслу | +| «Явная команда пользователя всегда сильнее ещё не применённой памятки» — контракт п. 5 — уже задокументированный принцип, ТЗ лишь уточняет его для окна загрузки модуля | `docs/WARM-REMOUNT.md:148–166` | совпадает | + +Ни одно утверждение о текущем поведении кода не разошлось с деревом; все +пять причинно-следственных связей, на которых строится ТЗ, подтверждены +чтением, а не только ссылкой автора. + +Дополнительно проверено: `_canManageConfiguration` (houseplan-card.ts:983) +фолбэчится на `hass.user.is_admin` до ответа сервера — значит окно AC4 +«задержанный модуль» действительно достижимо пользователем (вкладки +редактора рендерятся раньше, чем приходит авторитетный `can_write`), а не +теоретическая гонка, которую невозможно воспроизвести через UI. + +## Находки + +High и Medium нет. + +## Что проверено и корректно + +- Обязательные разделы §7.1 присутствуют все: сценарий (персона «владелец + умного дома», десктоп/touch), что человек увидит до/после (одной фразой, + без терминов реализации — «план может дёрнуться... после исправления + сохраняет прежний вид»), проблема с построчными ссылками, скоуп и + не-скоуп (явно перечислено, что НЕ переписывается: lifecycle целиком, + загрузчик редакторов, TTL, owner-слоты, геометрия), контракт поведения + и UX (пп. 1–8), модель данных/миграция/i18n («нет» явным текстом, + обоснованно), критерии приёмки AC1–AC6 с доказательством, план + автотестов, риски, откат, release-артефакты. +- Каждый AC однозначен и снабжён конкретным, фальсифицируемым механизмом + проверки: AC1 — числовые значения (1.6→3.4) и точка наблюдения (возврат + после закрытия редактора); AC2 — rAF-запись каждого кадра перехода, а не + только финала, явно запрещены «обязательные три кадра» как false floor; + AC3 — наблюдение самой записи в памятку, а не только итоговых размеров; + AC4/AC5 — конкурирующие исходы в обоих порядках (сервер раньше/позже + модуля); AC6 — именованные существующие смоки, которые обязаны остаться + зелёными, плюс проверка конечного состояния вместо поиска строк в + исходнике. +- Защитные AC (камера не дёргается, memo не смешивает пару, устаревший + resume не побеждает) доказываются по правилам §2.7 уже на стадии ТЗ: для + каждого из пяти симптомов назван отдельный красный свидетель на исходном + коде, а не общий «потом разберёмся». План автотестов прямо требует писать + их независимо друг от друга, чтобы один провал не прятал остальные — это + снижает риск, что пройдёт зелёным ТЗ, которое на самом деле чинит только + часть симптомов. +- Термины согласованы с каноном: `_view`/`viewBox`/«Просмотр»/«пространство» + использованы в точности как в `docs/CANVAS.md` и `docs/USER-GUIDE.ru.md`; + описание warm-памятки, TTL, одноразового воскрешения диалога и приоритета + явной команды не противоречит `docs/WARM-REMOUNT.md`, а п. 3 контракта + («наличие черновика не влияет на защиту камеры») точно закрывает + несостыковку, которую сам канон констатирует словом «камера... возвращается + бит-в-бит», а код — нет (см. таблицу сверки выше). +- Технических утверждений, не подкреплённых ни кодом, ни каноном и не + помеченных как предположение, не найдено — все пять причин проверены + чтением и совпали; раздел «принято предположительно» (4 пункта) содержит + только действительно нейтральные для пользователя технические решения + (структура идентичности pending-запроса, разбиение тестов, отложенное + измерение геометрии, тестовые значения zoom) и ни один не маскирует + продуктовый вопрос. +- Продуктовых вопросов владельцу в тексте нет, и это обоснованно: все восемь + пунктов контракта либо повторяют уже принятое канон-решение (приоритет + явной команды, «воскрешаем черновик, не воскрешаем решение», one-shot + revive), либо являются прямым следствием того, что пользователь уже увидел + как баг (откат к старой камере, потеря выбора). Отдельно проверена + потенциально спорная граница — что происходит, если пользователь успевает + запросить другой редактор, пока ещё не разрешился `_editorRuntime` внутри + уже идущего resume (а не общий `can_write`): это реальное, достижимое через + UI окно (см. «Как проверялось», фолбэк `_canManageConfiguration` на + `is_admin`), и AC4 его покрывает явно, с обоими порядками разрешения гонки. +- Touch покрыт в объёме, обязательном по `docs/TOUCH-SUPPORT.md`: View и + выбор пространства полностью поддержаны, AC5 отдельно требует проверки tap + в touch-viewport; новые touch-жесты редакторов осознанно не добавляются и + не требуются (редакторы — desktop-first). +- Release-артефакты: issue/ветка названы, `User-Visible: yes` обоснован + (пользователь видел баг — пропадающий зум/самовольное переключение режима, + значит и исправление видимо), оба changelog явно требуются в том же + коммите, bundle/VERSION/теги не трогаются, перед S7 требуются ссылки на + исходные красные и итоговые зелёные прогоны по каждому AC. +- Трек `ask` обоснован критерием §5: несколько связанных async-путей, + контракт камеры и риск 7/10, что выше рамок `show`; соответствует уже + установленной метке `track:ask` и `ci:golden` (камера — визуальный риск + даже без изменения статичного вида, значит `ci:golden` уместен). + +## Чего не проверял + +- Исполнение гейтов (`tsc`, `npm test`, `npm run build`, golden, браузерные + smoke) — кода ещё нет, этап spec их не требует; «дешёвый» зелёный Validate + на материальном SHA относится к существующему `dev`, а не к ещё не + написанной реализации этой задачи. +- Фактическое поведение браузера на заявленных численных порогах (1.6→3.4, + «не более 1 CSS px», «минимум 5 кадров») — это спецификация будущего + теста, а не код, который можно прочитать и исполнить сегодня; проверено + только, что похожий порог (1 CSS px, 48 CSS px и т. п.) — устоявшийся в + проекте паттерн измерения (docs/CANVAS.md, docs/WALL-THICKNESS.md, + docs/TOUCH-SUPPORT.md), а не произвольное число без основания. +- Состояние соседних задач #756 и #95 как таковых — они не являются + материалом этого ревью; ТЗ ссылается на их контракты корректно (черновик + едет по цепочке, приоритет явной команды), и это подтверждено чтением + `docs/WARM-REMOUNT.md`, а не повторным ревью тех issue. +- Реализуемость предложенных точек изменения (`src/warm-mode-adoption.ts`, + `src/houseplan-card.ts`, при необходимости `src/houseplan-editor-runtime.ts`) + — список файлов правдоподобен (именно там найдены все пять причин), но + фактический диф появится только на код-ревью. + +## Вердикт + +Зелёный. Документ ТЗ полон по §7.1, все пять причинно-следственных связей +проверены чтением и совпадают с деревом на материальном SHA, каждый AC +однозначен и снабжён названным способом доказательства и отдельным красным +свидетелем, открытых продуктовых вопросов нет, технических утверждений без +основания не найдено. High: 0, Medium: 0. + +--- + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `0606a3664a6c` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `2b4c828038177a9231a8b041da0dad7c60c54f9f` + ``` + git log --all --format='%H %T' | grep 2b4c82803817 + ``` +- Тело issue: `43855b946e06e4cbd56d6890ba92b55ab76f4f3334fd8c10ac7b271d90344cee` +- Вердикт конвейера: `green` · High 0 · маршрут `fix` +