docs: review document for #744

Issue: #744
User-Visible: no
This commit is contained in:
claude[bot]
2026-10-01 10:04:12 +00:00
parent 5a49c8c32d
commit 37238f3990
2 changed files with 144 additions and 1 deletions
+2 -1
View File
@@ -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` |
+142
View File
@@ -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.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `5a49c8c32df9` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `436061a24c6d0fb33f9cc036606d03922b5476a9`
```
git log --all --format='%H %T' | grep 436061a24c6d
```
- Тело issue: `9dec80eead95ea0cbc014364d7ed09eaef1f7f45b7e2c70f97f1a95c586ac465`
- Вердикт конвейера: `green` · High 0 · маршрут `fix`