Files
2026-10-01 10:04:12 +00:00

14 KiB
Raw Permalink Blame History

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