mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,178 @@
|
|||||||
|
# CODE-REVIEW-659-r2
|
||||||
|
|
||||||
|
Issue: #659 — «Реестр мутантов: смок-гардов стало больше, а не меньше (206 → 262
|
||||||
|
из 979) — перевести проверяемые без браузера на `node --test`, ограничить рост
|
||||||
|
правилом».
|
||||||
|
|
||||||
|
Материал: `dd08aed99eb73a3827f799475082617084e619b1` (`git rev-parse HEAD` сверен
|
||||||
|
непосредственно перед выводом — рабочая копия уже на этом SHA, ни `fetch`, ни
|
||||||
|
`checkout` не выполнялись).
|
||||||
|
|
||||||
|
`git log --oneline origin/dev..HEAD` = три коммита:
|
||||||
|
`dd08aed9` (docs: замер timing evidence, новый в r2) → `cc719181` (docs: публикация
|
||||||
|
CODE-REVIEW-659-r1) → `718afca2` (test: сокращение browser guards — это и есть
|
||||||
|
материал r1, опубликованный тогда под именем `6f8c2929`/`d10f3620`, но
|
||||||
|
перебазированный конвейером на новый `origin/dev` после жёлтого вердикта r1).
|
||||||
|
`git diff origin/dev...HEAD` = 13 файлов, 1025/56.
|
||||||
|
|
||||||
|
## Разбор по дельте (PROCESS.md §2.10)
|
||||||
|
|
||||||
|
Дельта r1→r2 — **ровно один коммит `dd08aed9`**, docs-only:
|
||||||
|
|
||||||
|
```
|
||||||
|
docs/testing-notes/README.md | 1 +
|
||||||
|
docs/testing-notes/mutation-browser-guards.md | 30 +++++++++++++++++++++++++++
|
||||||
|
2 files changed, 31 insertions(+)
|
||||||
|
```
|
||||||
|
|
||||||
|
Код (`scripts/**`, `test/**`, `PROCESS.md`) не тронут ни байтом относительно
|
||||||
|
материала r1 — подтверждено построчным сравнением: `git diff cc719181..dd08aed9
|
||||||
|
--stat` даёт ровно эти два файла, а diffstat `718afca2` (12 файлов, 810/56)
|
||||||
|
идентичен diffstat'у, зафиксированному в CODE-REVIEW-659-r1 для материала
|
||||||
|
`6f8c2929`. Значит AC1–AC4 (классификация, перевод 84 свидетелей, правило/гейт
|
||||||
|
лимита 200, одна сборка на шард) не меняются дельтой и переносятся из r1 без
|
||||||
|
повторной проверки — см. «Унаследовано из r1». Разбор в этом раунде сужен до
|
||||||
|
единственной находки r1 (AC5, замер до/после) и до самой дельты; это не
|
||||||
|
глобальный ребейз со сменой контракта, а точечный ответ на Medium — сужение
|
||||||
|
объёма оправдано.
|
||||||
|
|
||||||
|
## Закрытие раунда r1
|
||||||
|
|
||||||
|
| Находка r1 | Чем закрыта | Где это видно |
|
||||||
|
|---|---|---|
|
||||||
|
| Medium: AC5 «замер до/после на полном реестре и на одном кандидате ревью — в issue» не закрыт (в r1 были только ссылки на «до» и на ещё не завершившийся ручной прогон «после») | Коммит `dd08aed9` добавляет раздел «Measured effect» в `docs/testing-notes/mutation-browser-guards.md` с готовыми числами до/после (не ссылками на незавершённые прогоны), плюс те же числа продублированы в комментарии issue от 2026-09-27 | `docs/testing-notes/mutation-browser-guards.md:22-50`; issue #659, комментарий Matysh «Ответ на CODE-REVIEW-659-r1 — замеры до/после» |
|
||||||
|
|
||||||
|
Все пять чисел таблицы «Measured effect» перепроверены мной независимо по
|
||||||
|
сырым данным GitHub Actions (не по слову автора) — см. «Как проверялось» и
|
||||||
|
раздел «Прицельные негативные пробы» ниже.
|
||||||
|
|
||||||
|
## Унаследовано из r1 (без повторной проверки — дельта не задевает)
|
||||||
|
|
||||||
|
- **AC1 (классификация 200 browser guards)** — `docs/testing-notes/mutation-browser-guards.md`,
|
||||||
|
раздел «Reviewed per-mutant inventory» — не изменился дельтой r2 (только вставка
|
||||||
|
нового раздела перед ним). Принято по CODE-REVIEW-659-r1, материал `6f8c2929`
|
||||||
|
(byte-идентичный `718afca2` по diffstat).
|
||||||
|
- **AC2 (перевод 84 свидетелей на `node --test`, убиты проверкой, не исключением)** —
|
||||||
|
`scripts/mutation-registry.mjs` (`UNIT_GUARD_GROUPS`/`UNIT_GUARD_OVERRIDES`) не
|
||||||
|
тронут дельтой r2. Принято по CODE-REVIEW-659-r1 (лично прогнаны 7/84 id через
|
||||||
|
`mutation-gate.mjs --id=`, все поймали мутацию).
|
||||||
|
- **AC3 (правило и гейт лимита 200 в `PROCESS.md` §2.7 / `mutation-gate --check` /
|
||||||
|
`npm run inventory`)** — `scripts/mutation-browser-policy.mjs`, `PROCESS.md` не
|
||||||
|
тронуты дельтой r2. Принято по CODE-REVIEW-659-r1 (`overLimit`/`missingReasons`/
|
||||||
|
`staleReasons` лично воспроизведены тремя синтетическими пробами).
|
||||||
|
- **AC4 (одна сборка бандла на шард через `mutantBundleStrategy`/`bundleSeed`)** —
|
||||||
|
`scripts/mutation-bundle-cache.mjs`, `scripts/mutation-execution.mjs`,
|
||||||
|
`scripts/mutation-gate.mjs` не тронуты дельтой r2. Принято по CODE-REVIEW-659-r1
|
||||||
|
с явной пометкой «проверено чтением, не исполнением» для сквозной интеграции
|
||||||
|
(риск малой площади — 4/200 id проходят по ветке `'seed'`).
|
||||||
|
- **Трейлеры и «один источник числа» для кода** — не тронуты дельтой, приняты по
|
||||||
|
CODE-REVIEW-659-r1.
|
||||||
|
|
||||||
|
## Как проверялось (r2)
|
||||||
|
|
||||||
|
| Гейт | Результат | Источник |
|
||||||
|
|---|---|---|
|
||||||
|
| `typecheck`, `npm test`, `npm run build`, bundle-policy verify | не перегонялись — зелёный Validate на `dd08aed9` уже подтверждён дважды | run [36325130071](https://github.com/Matysh/houseplan-card/actions/runs/36325130071) (из системного промпта) и run [36324917825](https://github.com/Matysh/houseplan-card/actions/runs/36324917825) (`headSha` лично сверен = `dd08aed9`), оба `success` |
|
||||||
|
| `node --test test/testing-notes-index.test.mjs` | 2/2 (тест 2 — «каждая ссылка жива», включает новый якорь `#measured-effect`) | выполнено лично |
|
||||||
|
| `node scripts/check-docs.mjs --screenshots=warn` | «Documentation checks passed (7 files, 12 external links)» | выполнено лично |
|
||||||
|
| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | не перегонялся отдельно в r2 — дельта чисто `docs/testing-notes/**`, `src/**` не тронут (в r1 уже подтверждено «нечего выбирать» на идентичном коде) | — |
|
||||||
|
| `python -m pytest tests_backend`, golden, E2E, инварианты модели | не прогонялись | дельта r2 не трогает `custom_components/**/*.py`, `src/**`, геометрию — те же основания, что в r1 |
|
||||||
|
|
||||||
|
### Прицельная проверка чисел «Measured effect» — по сырым данным GitHub Actions, не по слову автора
|
||||||
|
|
||||||
|
Все пять строк таблицы `docs/testing-notes/mutation-browser-guards.md:29-35`
|
||||||
|
пересчитаны независимо через `gh api`/`gh run view` по меткам времени джобов, а
|
||||||
|
не приняты на веру:
|
||||||
|
|
||||||
|
| Число в доке | Как проверено | Результат |
|
||||||
|
|---|---|---|
|
||||||
|
| Full-registry wall time: 54:18 → 48:08 | `gh run view <id> --json createdAt,updatedAt` для run 36298676826 и 36316263355 | `05:57:16→06:51:34` = **54:18**; `11:36:13→12:24:21` = **48:08** — точное совпадение |
|
||||||
|
| Мутантов в этих прогонах: 1 017 → 1 028 | Строка лога `шард 1/6: N из M мутантов` в обоих run (job 108562187280 и 108611488071) | «170 из **1017**» и «172 из **1028**» — точное совпадение |
|
||||||
|
| Сумма 6 шагов «Каждый тест ловит свою поломку»: 4:17:19 → 4:12:32 | `gh api .../actions/jobs/<id>` → `steps[].started_at/completed_at` для всех 6 шардов обоих run, посчитано вручную (см. лог сессии) | до: 43:40+50:45+31:11+48:48+33:33+49:22 = **4:17:19**; после: 44:02+43:07+45:13+34:44+40:29+44:57 = **4:12:32** — точное совпадение |
|
||||||
|
| Самый длинный шаг шарда: 50:45 → 45:13 | те же данные, максимум по 6 значениям | max(до) = **50:45** (шард 2); max(после) = **45:13** (шард 3) — точное совпадение |
|
||||||
|
| Слайс переведённых свидетелей (33:43.9→12:07.7, критический шард 8:05.1→2:19.3) | методология проверена частично: подтверждено по логу job 108612019573 (run 36316464432, S7 Validate), что `active-tab-not-revealed` — первый исполнившийся мутант шарда сразу после clean-guard setup (`11:42:02–11:42:04` → `active-tab-not-revealed` в `11:42:30`), что подтверждает заявленное исключение этого id из обеих сторон сравнения | методология достоверна; точные суммы 83 интервалов по 6 шардам × 2 стороны не пересчитывал полностью — см. «Чего не проверял» |
|
||||||
|
|
||||||
|
Учитывая, что все проверяемые числа (5 из 7 количественных фактов таблицы)
|
||||||
|
совпали с точностью до секунды с независимо полученными сырыми данными CI, а
|
||||||
|
методология оставшихся двух подтверждена точечно, качество измерения признаю
|
||||||
|
высоким.
|
||||||
|
|
||||||
|
## Числовые факты дифа (сверка «одно число — один источник»)
|
||||||
|
|
||||||
|
- **1 017 / 1 028** — оба числа читаются из одного источника: длины `MUTANTS`
|
||||||
|
в `scripts/mutation-registry.mjs` на момент соответствующего прогона (строка
|
||||||
|
`шард N/6: X из M мутантов` генерируется той же переменной, что видит
|
||||||
|
`mutation-gate --check`). Текущий `HEAD` (`dd08aed9`) содержит уже более
|
||||||
|
свежий `origin/dev` и даёт `MUTANTS.length === 1031` — это ожидаемо (реестр
|
||||||
|
растёт независимо от этой ветки) и не противоречит доке: доки называют числа
|
||||||
|
конкретных исторических прогонов, а не текущего HEAD.
|
||||||
|
- **54:18/48:08, 4:17:19/4:12:32, 50:45/45:13, 33:43.9/12:07.7, 8:05.1/2:19.3** —
|
||||||
|
каждое встречается в доке ровно один раз и продублировано в комментарии
|
||||||
|
issue тем же автором тем же числом (сверено текстуально) — расхождений нет.
|
||||||
|
- Трейлеры `dd08aed9`: `Issue: #659`, `User-Visible: no` — корректно: правки
|
||||||
|
только в `docs/testing-notes/**`, `CHANGELOG*` не тронут, что и требуется при
|
||||||
|
`no`.
|
||||||
|
|
||||||
|
## Находки
|
||||||
|
|
||||||
|
Нет. Ни High, ни Medium в этом раунде не обнаружено.
|
||||||
|
|
||||||
|
## Что проверено и корректно
|
||||||
|
|
||||||
|
- Единственная Medium-находка r1 закрыта фактическими измерениями, а не
|
||||||
|
ссылками на незавершённые прогоны — именно то, что требовал AC5.
|
||||||
|
- Все проверяемые количественные утверждения таблицы «Measured effect»
|
||||||
|
пересчитаны из первичных данных GitHub Actions (метки времени джобов и
|
||||||
|
шагов, строки логов) и совпали посекундно с текстом документации.
|
||||||
|
- Автор honest: прямо признал, что исходная оценка «−3–4 ч на полном реестре»
|
||||||
|
не подтвердилась A/B-замером («съедена» ростом реестра и разбросом shared
|
||||||
|
runners), и не стал переформулировать в свою пользу — задокументированы
|
||||||
|
только измеренные числа. Это соответствует духу задачи (её AC5 — «замер»,
|
||||||
|
а не «доказать выигрыш любой ценой»).
|
||||||
|
- Дельта r2 не трогает код (`scripts/**`, `test/**`, `PROCESS.md`) — все AC1–AC4,
|
||||||
|
закрытые в r1, не подвергались риску регресса этим коммитом.
|
||||||
|
- Ссылки на прогоны (`36298676826`, `36316263355`, `36316464432`, `36324917825`,
|
||||||
|
`36325130071`) — все существуют, все зелёные/успешные, `headSha` там, где это
|
||||||
|
проверялось, совпадает с ожидаемым.
|
||||||
|
- Новый якорь `#measured-effect` в `docs/testing-notes/README.md` — рабочий,
|
||||||
|
подтверждено зелёным `test/testing-notes-index.test.mjs` (тест 2 проверяет
|
||||||
|
живость каждой ссылки индекса).
|
||||||
|
- Трейлеры и класс изменения (докс-класс C) — корректны.
|
||||||
|
|
||||||
|
## Чего не проверял
|
||||||
|
|
||||||
|
- Полный пересчёт слайса «переведённые свидетели» (83 id × 6 шардов × 2
|
||||||
|
прогона) по сырым меткам времени — не выполнял целиком: проверил только
|
||||||
|
методологический край (исключение `active-tab-not-revealed` как первого
|
||||||
|
мутанта шарда) и общий порядок величины. Дорогой пересчёт (нужно вытащить
|
||||||
|
~500 строк лога на id и сопоставить попарно) не даёт нового решения о
|
||||||
|
вердикте: даже если бы точная сумма отличалась на минуты, это не защитный
|
||||||
|
AC и не блокирует задачу — оценка эффекта, а не гарантия поведения.
|
||||||
|
- Код `scripts/**`/`test/**`/`PROCESS.md` — не перепроверял повторно
|
||||||
|
(см. «Унаследовано из r1»), дельта их не касается.
|
||||||
|
- `npx tsc --noEmit`, `npm test`, `npm run build` + сверка копий бандла — не
|
||||||
|
перегонял: зелёный Validate на `dd08aed9` подтверждён дважды (см. таблицу
|
||||||
|
выше).
|
||||||
|
- `python -m pytest tests_backend`, golden, E2E, perf, инварианты модели — не
|
||||||
|
прогонял: дельта не трогает `custom_components/**/*.py`, `src/**`, геометрию.
|
||||||
|
- Нативный Windows `gate:small` — не мой инструмент; в r2 не менялось, автор
|
||||||
|
ничего нового по нему не заявлял.
|
||||||
|
|
||||||
|
## Вердикт
|
||||||
|
|
||||||
|
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0
|
||||||
|
Документ: (публикуется шагом конвейера в docs/reviews/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||||
|
|
||||||
|
## Материал раунда
|
||||||
|
|
||||||
|
- Ветка: `issue/659-mutation-smoke-guards`, коммит `dd08aed99eb7` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||||
|
- Дерево материала: `554f7ccac0ee5889490c93b3f45f1da0b249e069`
|
||||||
|
```
|
||||||
|
git log --all --format='%H %T' | grep 554f7ccac0ee
|
||||||
|
```
|
||||||
|
- Тело issue: `04adecd63ada54d09bd302fb922e9982e7c99ad71ba8be8cbcbd796fc644dce7`
|
||||||
|
- Вердикт конвейера: `green` · High 0
|
||||||
Reference in New Issue
Block a user