diff --git a/docs/reviews/CODE-REVIEW-753-r2.md b/docs/reviews/CODE-REVIEW-753-r2.md new file mode 100644 index 00000000..33568e50 --- /dev/null +++ b/docs/reviews/CODE-REVIEW-753-r2.md @@ -0,0 +1,215 @@ +# CODE-REVIEW #753 · r2 + +Материал раунда: `1a086aa611b667c72885a952b4240d331c3b932c` (ровно он, рабочая +копия на нём). Диапазон `origin/dev..HEAD` — три коммита: +`94192889` (код), `cafc57fe` (документ ревью r1, публикация прошлого раунда), +`1a086aa6` (индекс ревью, публикация прошлого раунда). + +## Скоуп + +Issue #753 не меняется с r1: исключение #562 («инфраструктурный диапазон +статуса не требует, если в диффе нет файлов класса A») не знало, где +находится задача, и позволяло issue в `S3-spec`/`S4-spec-review` (маршрут +`track:ask`) пушить ветку из одних тестов без статусной метки — вопреки §11.8 +(«до `S5` не пушится ни код, ни сама ветка») и с риском того, что эта ветка +станет материалом ревью ТЗ. Задача сужает исключение: решение по каждому +issue в `checkIssueStatuses`, а не по диапазону. + +Трек show (#696), критерий §5 маршрута вердикта пройден так же, как в r1: +`complexity` (чистая правка одной функции), `surfaces` (один модуль +`scripts/process-gate.mjs`), `migration` (нет), `ux-contract` (нет — CI-гейт), +`perf-touch` (нет), `undocumented` (поведение уже в каноне §11.8/§2.5, задача +устраняет расхождение гейта с каноном). → `route: fix`. + +### Почему r2, а не слияние после зелёного r1 + +r1 (материал `23447c36`) получил зелёный вердикт без находок, документ и +индекс были опубликованы в ветку (`cafc57fe`, `1a086aa6`) — штатный шаг +конвейера после зелёного вердикта. Дальше `dev` ушёл вперёд несколько раз во +время слияния (гонка #492), ветку трижды ребейзили, автосверка процесса +зафиксировала «Validate on the material is completed but the round was not +resumed» и разбудила `S7-code-review` заново на новом материале. Это ребейз на +ушедший вперёд `dev` — один из случаев, когда разбор остаётся полным, а не +сокращается до дельты (§2.10, конспект «Повторный раунд»), поэтому ниже — +полный разбор, а не только показ закрытия находок r1 (их и не было). + +## Как проверялось + +1. Сверено, что дерево материала r2 после ребейза не разошлось по содержанию + с тем, что проверял r1: `git diff 94192889~1 94192889 --stat` даёт ровно + те же 4 файла / 141 вставку / 3 удаления, что и r1 на `23447c36`; хеш + текста диффа (`scripts/process-gate.mjs`, `scripts/mutation-registry.mjs`, + `test/process-gate.test.mjs`, `PROCESS.md`) посчитан и сверен — **содержимое + патча бит-в-бит то же**, что проверял r1. Старое дерево материала r1 + (`e94227ed9fa2…`) само по себе уже не резолвится — объект собран как + мусор после ребейза; это не находка (конспект «Повторный раунд»: мёртвый + SHA — обычное дело, если дерево при публикации существовало, а находка — + только мёртвый SHA уже в момент публикации отчёта; свежий тег подтверждён + числом изменённых строк и текстом). +2. Проверено, не задевает ли содержательно новые коммиты `dev` между + материалом r1 и r2 ту же область кода: `git log 88985d2e..origin/dev -- + scripts/process-gate.mjs test/process-gate.test.mjs + scripts/mutation-registry.mjs PROCESS.md` нашёл один коммит + (`a7b02db6`, #755), трогающий `process-gate.mjs` — но правит + `classifyRisk` (риск по изменённым участкам), не пересекается с + `checkIssueStatuses`/`isInfrastructureRange`/`SPEC_ROUTE_STATUS`. + Остальные найденные коммиты (#745, #757, #742, #739, #729, #736, #738, + #718, #730, #727, #725, #728, #694, #707, #724, #723, #716) либо не + трогают эти файлы, либо (как #738, #729, #736) правят другие функции того + же файла. Семантического конфликта нет — ребейз был чист и для git + (отсутствие маркеров конфликта), и по смыслу. +3. Код прочитан заново в контексте текущего файла (не по диффу, а по месту): + `isInfrastructureRange` (`scripts/process-gate.mjs:404-423`), + `SPEC_ROUTE_STATUS` (`:459-463`), `checkIssueStatuses` (`:467-518`). +4. Тесты AC1/AC2 прочитаны целиком в текущем файле: + `test/process-gate.test.mjs:775-823` (юнит `checkIssueStatuses`, + `statusOptional does not cover an issue in the spec route S3/S4 (#753)`), + `:905-947` (сквозной CLI, `the CLI refuses a class-B-only range of an issue + in S3/S4 but not in S1 (#753)`). +5. Мутант `process-gate-infra-entry-covers-spec-route` + (`scripts/mutation-registry.mjs:3602-3612`) прочитан: патч убирает условие + `specRoute.length === 0`, возвращая `optional = statusOptional` — именно + регресс, который AC1 должен ловить. +6. Прогнаны гейты (ниже — свои, в дополнение к ссылке на Validate). +7. Текст PROCESS.md §10.2 (`:1169-1174`) сверен дословно с формулировкой ТЗ — + совпадает, то же предложение, что проверял r1. +8. Трейлеры всех трёх коммитов диапазона проверены (ниже). +9. Прочитано тело issue #753 и полная лента комментариев, включая гонку + ребейза и сообщение автосверки — расхождений с тем, что знал r1, нет. + +## Что проверено и корректно + +- **AC1** (исключение не для маршрута ТЗ) — без изменений от r1, содержимое + патча идентично. `specRoute = names ∩ SPEC_ROUTE_STATUS`, + `optional = statusOptional && specRoute.length === 0`; при непустом + `specRoute` — отказ с текстом, называющим статус, §11.8 и #562 (`:505-508` + в текущей нумерации, что совпадает по смыслу с `:496-514` из r1 — смещение + строк из-за восстановленных комментариев выше по файлу, не из-за правки + логики). `S1-new`/`S2-analysis` вне `SPEC_ROUTE_STATUS` — соответствует + ТЗ. Юнит покрывает все случаи таблицы АС, включая два issue в одном + диапазоне и `blocked` поверх специального статуса. Прогнан заново — зелёный. +- **AC2** (сквозной CLI) — без изменений от r1. `S4-spec-review`/`S3-spec` → + выход 1, `FAIL п.8`, текст с `#753 в <статус>`; `S1-new` → выход 0 и + предупреждение #562 без `FAIL`. Прогнан заново — зелёный. +- **AC3** (канон + мутант) — без изменений от r1. PROCESS.md §10.2 содержит + предложение дословно. Мутант `process-gate-infra-entry-covers-spec-route` + назначен guard'ом `node --test test/process-gate.test.mjs`; целевой прогон + мутационного гейта на этом SHA подтверждает `ok` (мутант убит новым тестом). +- **Доказательство «тест умеет падать»**: перепрогнано самостоятельно на + текущем материале, не принято на слово ни от автора, ни от документа r1: + `node scripts/mutation-gate.mjs --id=process-gate-infra-entry-covers-spec-route --check` + → `ok`. +- Сообщение `main()` про предупреждение #562 по-прежнему печатается для + всего диапазона независимо от отказа по конкретному issue — подтверждено + тестом AC2 (оба сообщения одновременно). +- Трейлеры: `94192889` несёт `Issue: #753`, `User-Visible: no` — корректно + (CI-гейт, пользовательского поведения нет, CHANGELOG не тронут и не + должен быть). `cafc57fe` и `1a086aa6` — документация публикации + (документ ревью и индекс), тоже с `Issue: #753`, `User-Visible: no`; по + правилу (PROCESS.md §3 п.10) докс-коммит класса C может не нести трейлеры + вовсе — здесь они проставлены сверх минимума, это не находка. +- Числовых величин, видимых пользователю дважды, диапазон не вводит — + не применимо, задача не трогает UI. +- Ребейз не оставил конфликтных маркеров, `.orig`-файлов или следов + неполного мержа ни в одном из четырёх правленных файлов. + +### Прогон гейтов (сам, в дополнение к Validate на этом SHA) + +- Validate на `1a086aa6` зелёный (ссылка в задаче ревью) — закрывает + `tsc --noEmit`, `npm test`, `npm run build` + сверку бандла. +- `node --test test/process-gate.test.mjs` — 48/48 зелёные, включая оба + теста AC1 и AC2 (перепрогнано на материале r2, не принято из документа r1). +- `node scripts/mutation-gate.mjs --id=process-gate-infra-entry-covers-spec-route --check` + — `ok` (мутант убит); попутно вывод отметил + `WARN browser guards: 205 при ориентире 200` — это накопленное + превышение мягкого ориентира реестра мутантов в целом, не связанное с + диффом #753 (диапазон не добавляет и не трогает ни один `browser`-мутант; + добавленный мутант — не браузерный), отдельной находкой не считаю. + +## Чего не проверял и почему + +- Полный `mutation-gate --check` по всему реестру — дорого и не нужно для + track show на диапазоне, трогающем один мутант; целевой `--id=` на нём + достаточен для AC3. +- Браузерные смоки / `smoke-select.mjs` — diff не трогает `src/**`/`www/**`, + frontend-диффа нет; r1 это уже подтвердил внутри `gate:small`, повторный + запуск не даёт новой информации на идентичном патче. +- `npm run golden:verify`, `python -m pytest tests_backend`, + `npm run invariants`, performance-профили — не применимо: диффа в golden, + `custom_components/**`, геометрии или производительности нет, в АС не + названы. +- Ручное тестирование UI — не применимо: задача меняет CI-скрипт + (`process-gate.mjs`) и канон-документ, пользовательского поведения нет. +- Зависимость #748 п.1 (подсказка `S3` со стороны `task-packet.mjs`) — + вне скоупа этой задачи по самому ТЗ («Порядок любой»), не проверял. +- Содержательно не перепроверял историческую часть ТЗ (происхождение + исключения #562 из #207/#118, хронология `ad8e7a50`/`3934f8d8`) — она не + менялась между r1 и r2 и не относится к коду; принимаю её из r1 (раздел + ниже). + +## Находки + +Нет. High: 0, Medium: 0 (в скоупе и вне скоупа). + +## Вердикт + +Зелёный. Содержимое патча идентично тому, что уже получило зелёный вердикт в +r1 (сверено бит-в-бит, не только по статистике диффа); причина r2 — +исключительно гонка ребейза с продвигающимся `dev` (#492), а не правка кода. +Ребейз чист и для git, и по смыслу: единственный коммит `dev`, тронувший тот +же файл (#755), правит не пересекающуюся функцию. Оба AC1/AC2 перепрогнаны +самостоятельно на материале r2 и зелёные, мутант AC3 убит целевым прогоном на +этом SHA, PROCESS.md §10.2 дословно совпадает с ТЗ. Трейлеры корректны на всех +трёх коммитах диапазона. + +## Закрытие раунда r1 + +r1 находок не содержал (High 0, Medium 0) — закрывать нечего. Таблица ниже +фиксирует это явно, как того требует формат раздела: + +| Находка r1 | Чем закрыта | Где видно | +|---|---|---| +| — (находок не было) | не применимо | `docs/reviews/CODE-REVIEW-753-r1.md`, раздел «Находки»: «Нет. High: 0, Medium: 0» | + +## Унаследовано из r1 + +Принято без повторной проверки — материал не менялся по содержанию между +раундами: + +- Историческая реконструкция происхождения исключения #562 (`ad8e7a50`/#118, + `3934f8d8`/#562) и её связь с ТЗ — документ `CODE-REVIEW-753-r1.md`, + материал `23447c36` (дерево `e94227ed9fa2…`, не резолвится после ребейза — + ожидаемо, см. «Как проверялось» п.1). +- Разбор того, что `ALLOWED_STATUS` не содержит `S3-spec`/`S4-spec-review` и + обычный (не `statusOptional`) путь не меняется — `CODE-REVIEW-753-r1.md`, + п.6 раздела «Как проверялось»; перепроверено по месту в текущем файле + (см. п.3 выше) и подтверждено прежним. +- Разбор того, что задача не вводит видимых пользователю величин — + `CODE-REVIEW-753-r1.md`, раздел «Что проверено и корректно»; задача не + затрагивает UI ни в r1, ни в r2. + +--- + + + +## Материал раунда + +- Ветка: `issue/753-rule8-spec-statuses`, коммит `1a086aa611b6` (ровно он, + рабочая копия на нём). +- Диапазон: `origin/dev..HEAD` = `94192889`, `cafc57fe`, `1a086aa6`. +- Вердикт этого раунда: `green` · High 0 · Medium 0 · маршрут `fix`. + +--- + + + +## Материал раунда + +- Ветка: `issue/753-rule8-spec-statuses`, коммит `1a086aa611b6` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `7a562b237ac83512a473e752e05098bba55cde46` + ``` + git log --all --format='%H %T' | grep 7a562b237ac8 + ``` +- Тело issue: `6ed6d6796ac50ee54325c0f740dc43953899f6c0b846c8bdc7ea2d41767a498f` +- Вердикт конвейера: `green` · High 0 · маршрут `fix` +