docs: spec #473 — сценарий, риски, доказательство AC7, флаги бенчмарка

User-Visible: no
Issue: #473
This commit is contained in:
Codex
2026-09-06 15:00:29 +03:00
parent 7a662d93ed
commit 5fbb9339c6
+41 -5
View File
@@ -26,6 +26,23 @@ LRU-кэш размещений с подписью, кэш по идентич
Два дефекта одного класса: горячий код без свидетелей и гейт, который есть, но
не там, где нужен.
## 1.1. Сценарий
Персона — автор задачи, трогающей путь отрисовки (`src/iso-*`, `src/live-*`,
`houseplan-card.ts`), и ревьюер этой задачи. Автор пушит ветку; Validate
запускается сам. Ревьюер читает вердикт Validate на SHA как подтверждение
дешёвых гейтов и тратит бюджет раунда на чтение кода.
## 1.2. Что человек увидит до и после
До: регрессия первого кадра в 6,5 раза невидима до предрелизного полного
бенчмарка; ревью проходит зелёным; исправление идёт под тегом по §11.4.
После: на первом же пуше ветки, задевшей `src/iso-*`, job `performance_smoke`
краснеет с абсолютным потолком профиля — «первый кадр 9 870 мс при потолке
3 500» — и автор видит это до того, как ревью началось. Для веток, не
трогающих отрисовку, ничего не меняется: те же два glow-профиля, то же время.
## 2. Скоуп
1. Свидетели на четыре механизма перф-дельты (§4) — через них проходит и
@@ -71,9 +88,12 @@ LRU-кэш размещений с подписью, кэш по идентич
`src/houseplan-card.ts` — добавляется `large-house-interaction-v1`.
Классификацию делает `changes` (существующий job) двумя новыми выходами
`perf_iso` и `perf_interaction` по тем же `has(...)`-шаблонам. Профили идут с
`--variants=60 --samples=3 --warmups=1 --absolute-only` и **своими
smoke-бюджетами** `budgets-isometric-smoke.json`, `budgets-interaction-smoke.json`
`perf_iso` и `perf_interaction` по тем же `has(...)`-шаблонам. Профили идут
через `demo/benchmark_large_house.mjs` с `--samples=3 --warmups=1`
(`--variants` — флаг только `benchmark_glow.mjs`, у `benchmark_large_house`
его нет: `demo/benchmark_large_house.mjs:17-18` принимает `samples`,
`warmups`, `target-root`, `profile`, `output`), сравнение —
`benchmark:compare --absolute-only` и **свои smoke-бюджеты** `budgets-isometric-smoke.json`, `budgets-interaction-smoke.json`
(`minimumSamples: 3`, потолки — `hardMaxMs` из полных профилей). Регрессионные
коэффициенты в смоке не участвуют: сравнивать не с чем, абсолютный потолок
достаточен — 9 870 мс против 3 500 он ловит с одного образца.
@@ -100,7 +120,22 @@ smoke-бюджетами** `budgets-isometric-smoke.json`, `budgets-interaction-
| AC4 | Smoke-бюджеты новых профилей валидны для `benchmark:compare --absolute-only` и повторяют `hardMaxMs` полных | unit: чтение обоих файлов, сравнение потолков |
| AC5 | Ключ `reuse` для `performance_smoke` различает наборы профилей | контрактный тест на YAML |
| AC6 | Воспроизведение: на дереве `de215578` изометрический smoke-бюджет краснеет по первому кадру | замер один раз при реализации, результат в issue с командой |
| AC7 | На текущем `dev` оба новых профиля укладываются в потолки за 3 образца | прогон в CI этой ветки |
| AC7 | На текущем `dev` оба новых профиля укладываются в smoke-потолки за 3 образца | вручную при реализации, как AC6: команды и числа в issue. Дифф этой задачи не задевает продуктовых путей, поэтому её собственный Validate новые профили не запустит, а `workflow_dispatch` у `validate.yml` нет |
| AC8 | Диффозависимость доказана на самом workflow: контрактный тест подставляет в `changes` дифф из `src/iso-x.ts` и ожидает `perf_iso=true`, из `src/live-x.ts` — `perf_interaction=true`, из `docs/x.md` — оба `false` | unit на функцию классификации, вынесенную из inline-shell в `scripts/classify-changes.mjs` (или на извлечённые `has(...)`-шаблоны) |
## 7.1. UX, модель данных, i18n
Не применимо: продуктовый код, конфиг, хранилище и словари не меняются;
пользователь ничего не увидит. Единственная поверхность — CI.
## 7.2. Риски и меры
| Риск | Мера |
|---|---|
| Изометрический профиль на 3 образцах удлиняет `performance_smoke` за 20-минутный лимит job | замер при реализации (AC7); при превышении лимит поднимается в этой же задаче с числом |
| Абсолютный smoke-потолок на 3 образцах шумит на общем раннере и красит честные ветки | потолки берутся из `hardMaxMs` полных профилей — это «в разы», а не «на проценты»; регрессионные коэффициенты в смок сознательно не входят |
| Свидетель AABB недостижим существующей фикстурой (перекрытие вместо касания) | фикстура касания добавляется, отрицательный прогон обязателен до заявления мутанта (правило после #426) |
| Ключ `reuse` без набора профилей засчитает glow-only результат прогону с изометрией | AC5, контрактный тест |
## 8. Release-артефакты
@@ -113,7 +148,8 @@ smoke-бюджетами** `budgets-isometric-smoke.json`, `budgets-interaction-
- `test/iso-scene-render.test.mjs`, `test/iso-overlays.test.mjs` — гарды и AC2;
- `.github/workflows/validate.yml` — выходы `changes`, условные шаги смока, ключ `reuse`;
- `demo/performance/budgets-isometric-smoke.json`, `budgets-interaction-smoke.json` — новые;
- `test/validate-workflow.test.mjs` — AC3, AC5; `test/performance-budget.test.mjs` — AC4;
- `test/validate-workflow.test.mjs` — AC3, AC5, AC8; `test/performance-budget.test.mjs` — AC4;
- `scripts/classify-changes.mjs` — если `has(...)`-шаблоны `changes` выносятся из inline-shell ради AC8;
- `PROCESS.md` §8.
## 10. Принятые предположения