diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index ae4835cc..92266b19 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,10 +1,11 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 242, issue: 120. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 243, issue: 121. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). 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 | — | — | +| #744 | [SPEC-REVIEW-744-r1.md](SPEC-REVIEW-744-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — | | #742 | [SPEC-REVIEW-742-r1.md](SPEC-REVIEW-742-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | устаревшее число в AC6 (не блокирует) | `src/houseplan-card.ts` `test/core-file-budget.test.mjs` | | #741 | [CODE-REVIEW-741-r1.md](CODE-REVIEW-741-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #740 | [SPEC-REVIEW-740-r1.md](SPEC-REVIEW-740-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | устаревший номер строки в «Проблема», п.2 | `src/stairs-view.ts` `src/stairs-editor.ts` `stairs-view.ts` `stairs-editor.ts` `stairs.ts` `large-house.mjs` `matrix.mjs` | diff --git a/docs/reviews/SPEC-REVIEW-744-r1.md b/docs/reviews/SPEC-REVIEW-744-r1.md new file mode 100644 index 00000000..a30eeb09 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-744-r1.md @@ -0,0 +1,142 @@ +# SPEC-REVIEW-744-r1 + +Issue: #744 — «Производительность: кэш чистого пола сбрасывается любой правкой конфига» +Этап: spec (PROCESS.md §2.4) · Трек: ask (§5, критерий «перф») · Заход: r1 · блокирующих циклов 0/4 +Материал: тело issue #744 (раздел `## ТЗ`), сверено с кодом на `origin/dev` `8b7725ac` (SHA, на который ссылается сам автор) и с рабочей копией `5a49c8c3` — расхождений в затронутых файлах между этими SHA нет (единственный коммит между ними — несвязанный тест луны). +Route: fix (трек уже `ask`, переквалификация не применяется). + +## Скоуп + +Задача меняет ключи и инвалидацию четырёх структурных геометрических кэшей +этажа (`_physicalBodiesCache`, `_wallUnionGeometry`/`_wallUnionPool`, +`_innerRoomContour`/`_innerContourCache`, `cleanFloorForRoom`/`_cleanFloorCache`): +сегодня ключ несёт глобальный `_cfgEpoch`, из-за чего правка одного этажа +«остужает» кэши всех остальных. Цель — ключ на отпечаток содержимого записи +конкретного этажа, без потери инвалидации при правках, которые законно трогают +несколько этажей (лестницы, общие стены). Служит J1/J6 docs/SCOPE.md — отзывчивость +переключения этажей и честность редакторского цикла; видимых новых функций нет. + +## Как проверялось + +Ревью ТЗ на этом этапе не включает выполнение гейтов (код не писался) — проверялась +только состоятельность документа: обязательные разделы §7.1, однозначность и +доказуемость каждого AC, и — так как расследование опирается на построчные +ссылки на код — сверка каждой процитированной строки с реальным деревом, +а не с заявлением автора. + +Построчно сверено чтением (не исполнением) с текущим деревом: + +| Утверждение ТЗ | Файл:строка в ТЗ | Проверено | +|---|---|---| +| `roomKey`/ключ чистого пола, LRU 600 | `src/clean-floor.ts:32–33,64` | совпадает дословно | +| Ключ оболочки стен, пул LRU 8 | `src/houseplan-card.ts:8755,8777` | совпадает (`:8755`, `lruWrite(... 8)` на той же строке диапазона) | +| Ключ внутренних контуров, LRU 600 | `:8806` | совпадает | +| Ключ физических тел, «одна запись» | `:9462–9463` | совпадает — это действительно единственный слот, не `Map`; автор сам это отмечает («одна запись») | +| `_saveConfig` поднимает эпоху, комментарий «every mutation path ends here» | `:7634–7637` | совпадает (функция с 7634, `_cfgEpoch++` на 7635) | +| Замена `_serverCfg` поднимает эпоху кроме geometry-preserving исключения | `:4019–4025` | совпадает | +| `StairsEditor.write` поднимает эпоху и чистит `_cleanFloorCache` целиком | `src/stairs-editor.ts:149–156` | совпадает (`clear()` действительно без учёта этажа — текущий баг подтверждён) | +| `contentFingerprint` существует, уже используется для `_model` | `src/visual-continuity.ts:439`, `houseplan-card.ts:3817` | совпадает | +| `cacheSnapshot` считает `wallUnion` как 0/1, не считает `innerContour` вовсе | `demo/benchmark_large_house.mjs:163–172` | совпадает — подтверждает «слепоту» свидетеля #735, на которую опирается AC3 | +| Потолок `src/houseplan-card.ts` — 12896 строк, запас к моменту ТЗ — 4 | `test/core-file-budget.test.mjs:52` | совпадает: файл сейчас 12892 строки | +| Явные полные сбросы при откате и восстановлении геометрии остаются | `src/houseplan-editor-runtime.ts:1474–1477, 1688–1691` | совпадает | +| Фикстуры-прецеденты для нового смока (`physicalize`, партиции/колонна) | `demo/smoke_space_switch_transitions.mjs:55–66`, `demo/smoke_space_card.mjs:18–34` | совпадает по смыслу и содержимому | +| `performance.yml` можно запустить вручную (`workflow_dispatch`) для AC4 | `.github/workflows/performance.yml:15` | совпадает | + +Ни одно утверждение о текущем поведении кода не разошлось с деревом. Это +резко снижает риск «ТЗ описывает код, которого нет». + +## Находки + +Находок High и Medium нет. + +Low (снято с записью, не требует правки): раздел «План автотестов» даёт явную +красную причину для AC1, AC2а, AC2б, но не называет отдельный красный случай +для AC2в (поведение во время resize-превью). Это не защитный AC в смысле §2.7 +(не валидация/гард, а утверждение о неизменности поведения, которое уже +корректно на dev), и на стадии ТЗ отдельная строка «чем краснеет» для него не +обязательна — но на код-ревью пустое место здесь не должно остаться пустым по +умолчанию, если тест действительно нечувствителен к ошибке в превью-ветке. + +## Что проверено и корректно + +- Обязательные разделы §7.1 присутствуют все: сценарий (две персоны из + `docs/SCOPE.md` — админ-десктоп, домочадцы-киоск), что человек увидит + до/после (одной фразой, без терминов реализации), проблема (5 нумерованных + пунктов с кодовыми ссылками), скоуп и не-скоуп (с явной мотивировкой каждого + исключения), контракт поведения К1–К5, UX/данные/i18n/touch (сжато, + обоснованно — новых элементов нет), критерии приёмки AC1–AC5 с колонками + «Доказательство» и «Oracle», план автотестов, риски, откат, + release-артефакты (текст changelog RU+EN уже написан). +- Каждый AC однозначен и проверяем конкретным механизмом: AC1/AC2 — новый + смок с названным сценарием воздействия и named oracle (независимая карточка, + построенная с нуля на том же конфиге — классический oracle против «кэш + соврал»); AC3 — правка полей бенчмарка плюс существующий сторож диапазона; + AC4 — реальный perf-workflow плюс локальный зонд тем же методом, что в «Итоге + исследования»; AC5 — перечисленные гейты и два конкретных мутанта с + названными guard AC. +- Защитный AC (К1 «правка другого этажа не остужает этот», К2 «устаревший + кадр не отдаётся») доказывается по правилам §2.7 уже на стадии ТЗ: для + AC1 назван красный случай на текущем коде (эпоха в ключе), для AC2а — + названный мутант без отпечатка содержимого, для AC2б — красный случай на + текущем коде (`StairsEditor.write` чистит чужой кэш). Пустых строк в этой + части нет. +- Главный риск задачи («устаревший кадр» — неполный ключ отдаст старую + геометрию) назван автором явно и закрыт мерой (ключ — отпечаток всей записи + этажа «по построению», плюс независимый oracle AC2а) — это ровно то дерево + рассуждений, которого требует правка кэша на горячем пути. +- «Принято предположительно» — пять технических решений, явно помеченных как + не-продуктовые и подлежащие пересмотру ревьюером без эскалации владельцу; + каждое обосновано (трейд-офф полнота/скорость ключа, выбор четырёх кэшей на + основе замера, отказ от `StairsEditor.write` чистки по данным замера, смок + вместо новой метрики бенчмарка — экономия на правке `budgets-*.json`, + отдельный модуль ключа — из-за строкового бюджета). Технических споров, + которые требовали бы вердикта вместо решения автора, не нашлось. +- Раздел «Вопросы владельцу» — пусто, с явным обоснованием («видимое изменение + одно, расширение на четыре кэша — техническое средство без отдельного + видимого эффекта»); никакого технического вопроса, спрятанного под видом + вопроса владельцу, в тексте нет — весь список открытых решений находится в + «Принято предположительно», а не вынесен наружу. +- Трейлер `User-Visible: yes` обоснован (один наблюдаемый эффект — + отзывчивость переключения этажей после правки) и текст changelog уже + подготовлен на русском и английском в самой ТЗ — на коммите кода потребуется + перенести его в оба `docs/CHANGELOG*.md`, это уже учтено в «Затронутые файлы». +- Трек `ask` обоснован по критерию §5 «перф»: горячий путь переключения этажа, + задействованный предыдущими перф-правками (#694/#725/#740), риск неверного + кадра, а не просто медленного — ТЗ сама называет этот критерий, совпадает с + меткой `track:ask` на issue. + +## Чего не проверял + +- Исполнение гейтов (`tsc`, `npm test`, `npm run build`, golden, perf) — кода + ещё нет, этап spec их не требует. +- Прогон `smoke-select`, мутационных якорей или perf-workflow — неприменимо до + реализации. +- Фактическую корректность числовых замеров из «Итога исследования» (607 мс, + 3 % вклад чистого пола и т. п.) — они явно помечены автором как локальная + диагностика, а не доказательство (это доказывает только будущий AC4), и + ревью ТЗ не требует их перепроверки. +- Состояние соседней задачи #742 (на неё ссылается пункт 5 «Принято + предположительно» про запас строк) — не часть материала этого ревью; если к + моменту кода запас бюджета будет другим, это всплывёт на гейте + `core-file-budget`, а не здесь. + +## Вердикт + +Зелёный. Документ ТЗ полон, построчные ссылки на код проверены и совпадают, +AC однозначны и снабжены доказательством и oracle, защитные AC доказаны по +правилам §2.7 уже на этой стадии, открытых продуктовых вопросов нет. High: 0, +Medium: 0. + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `5a49c8c32df9` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `436061a24c6d0fb33f9cc036606d03922b5476a9` + ``` + git log --all --format='%H %T' | grep 436061a24c6d + ``` +- Тело issue: `9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465` +- Вердикт конвейера: `green` · High 0 · маршрут `fix`