From df8482c70260e5762ea4aa60eab900d54f1dccea Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 05:52:12 +0000 Subject: [PATCH] docs: review document for #738 Issue: #738 User-Visible: no --- docs/reviews/CODE-REVIEW-738-r1.md | 148 +++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 docs/reviews/CODE-REVIEW-738-r1.md diff --git a/docs/reviews/CODE-REVIEW-738-r1.md b/docs/reviews/CODE-REVIEW-738-r1.md new file mode 100644 index 00000000..3504d1ff --- /dev/null +++ b/docs/reviews/CODE-REVIEW-738-r1.md @@ -0,0 +1,148 @@ +# CODE-REVIEW-738-r1 + +**Issue:** #738 — «process-gate, правило 10: код из S3 после reclassify не судится» +**Трек:** show · заход r1 · блокирующих циклов использовано 0 из 2 +**Материал раунда:** ветка `issue/738-rule10-epochs`, один коммит +`021a94959856c81c7fafac90f8f84fb87cc2a1c2` поверх `origin/dev` +`bc59917ea473635fe3a2f22893afd28513d37131` (merge-base +`76558bf2a0bf72dcfed369743639c989b4099450`). Диапазон ревью — +`git diff origin/dev...HEAD`. + +## Скоуп + +Чистая правка процессного гейта: `scripts/process-gate.mjs` (правило 10, +`checkCommitEraStatuses`), `test/process-gate.test.mjs`, PROCESS.md §10.2. +Файлов класса A нет, продуктовый код (`src/**`, `custom_components/**`) не +тронут. `User-Visible: no` — верно: правка видна только конвейеру. + +Критерии маршрута §5 (route): `complexity` — одна чистая функция, низкий риск; +`surfaces` — одна поверхность (правило 10 гейта); `migration` — нет; +`ux-contract` — нет; `perf-touch` — нет; `undocumented` — ожидаемое поведение +зафиксировано правилом №1, §2.5 и #726, подтверждено владельцем в комментарии +трека. Все критерии пройдены → **route: fix**, `reclassify` не требуется. + +## Что сделано (по диффу) + +`checkCommitEraStatuses` раньше сравнивал `authorDate` коммита только с +**первым** событием `labeled` из `allowed` (`readyAt`). Теперь строится шкала +статусных событий (`statusEvents`): метки `allowed` открывают эпоху «можно +писать код», `PRE_READY_STATUS` (`S1-new`…`S4-spec-review`) её закрывают, +остальные метки (`blocked`, `track:*`, `review-4`, `S8-merged` при +`--no-merged`) в шкалу не попадают вовсе. Статус на момент `w` — +`statusIndexAt`: последнее событие с `at ≤ w`. Для коммита: если на его +`authorDate` эпоха открыта — чисто; если нет и готовности вообще не было — +старый текст «до первого достижения…»; если готовность была, но закрылась — +новый текст называет статус на `authorDate`, время возврата (первое закрывающее +событие после последней готовности) и следующую готовность или «ещё не +достигнут». + +PROCESS.md §10.2 получил пункт 10, точно описывающий эту модель (эпохи, +закрывающие метки, `warn` без таймлайна). + +## Как проверялось + +| Гейт | Статус | Как | +|---|---|---| +| `npx tsc --noEmit`, полный `npm test`, `npm run build` + сверка бандла | не перегонялся | Validate на `021a9495` зелёный (run 36821163281) — §8 позволяет не дублировать на этом SHA | +| `test/process-gate.test.mjs` (точечно) | прогнан лично | `node --test test/process-gate.test.mjs` → 38/38 `ok`, включая старый тест rule 10 (#311) и три новых (#738) | +| Тест умеет падать (AC1, AC2) | проверено лично | Временно подменил `scripts/process-gate.mjs` на версию `origin/dev`, прогнал тот же тестовый файл: старый тест (#311) остаётся зелёным, три новых теста (#738) красные (`not ok 36/37/38`). Рабочую копию восстановил из git сразу после, `git status` — чисто | +| `node scripts/mutation-gate.mjs --check` | прогнан лично | `предупреждений mutation registry: 3`, browser guards 200/200 — совпадает с заявленным «как на dev» | +| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | прогнан лично | «Исполняемого frontend-диффа нет (src/**/*.ts не тронут)» — смоки не выбираются, выбирать нечего (`src/**` не менялся) | +| `python -m pytest tests_backend` | не требуется | `custom_components/**/*.py` не тронут | +| `npm run invariants` | не требуется | геометрия и ссылки на неё не тронуты | +| `npm run golden:verify` | не требуется | метки `ci:golden` на issue нет, рендер не тронут | +| performance-профили | не требуется | не названы в AC | +| Побочное наблюдение из ТЗ (не AC): риск для открытых веток S5…S7 | частично | `gh issue list` по меткам `S5-ready/S6-in-progress/S7-code-review` — живые кандидаты: #729, #731, #735, #736, #737, #739, #740, #741, #742 (и сам #738). По их **текущим** меткам ни один не стоит в `S3-spec`/`S4-spec-review`, то есть тривиального кейса «сейчас в пред-готовом статусе» нет. Полную проверку (`process-gate --range origin/dev..<ветка> --issues --report` по каждой из этих веток, с разбором таймлайна на предмет скрытого возврата `S5+→S3/S4` в прошлом) не гонял — это явно не-AC наблюдение из самого ТЗ, и объём трека show его не требует | + +## Проверка AC по тексту ТЗ + +- **AC1** (эпоха после возврата) — доказан `test/process-gate.test.mjs:905-988`. + Лично проверил сценарий таблицы ТЗ (S5 t1→S6 t2→S7 t3→S3 t4→S4 t5→S5 t6): + коммит `t2+1ч` чист, `t4+1ч` красит с текстом про `S3-spec`/`t4`/`t6`, + `t5+1ч` — про `S4-spec-review`/`t4`/`t6`, `t6+1ч` чист, `t1-1ч` — старый + текст без «после возврата». Два возврата подряд и «возврат без новой + готовности → ещё не достигнут» — второй тест файла, тоже зелёный на HEAD и + красный на dev. **Доказан автотестом, тест умеет падать — проверено лично.** +- **AC2** (совместимость и границы) — третий новый тест: старый тест #311 не + тронут и зелёный; таймлайн только из `allowed` даёт прежние вердикты; класс + B/C не красит; `blocked`/`track:ask` не меняют статус; `S8-merged` со + `STRICT_STATUS` не открывает и не закрывает эпоху; неотсортированные события + дают тот же результат; `authorDate == S3-spec` уже в `S3`. **Доказан + автотестом, тест умеет падать — проверено лично** (тот же red/green прогон). +- **AC3** (канон и гейт) — PROCESS.md §10.2 действительно называет эпохи, + `S1`…`S4` как закрывающие и `warn` без таймлайна — прочитано лично + (`PROCESS.md:1186-1202`). `gate:small` и `mutation-gate --check`: второе + прогнано лично (см. таблицу), `gate:small` не перегонялся отдельно — его + состав (typecheck/test/lint) покрыт зелёным Validate на этом SHA. + **Проверено чтением канона + частичным исполнением.** + +Защитный AC (AC1/AC2 — гард против невидимого нарушения DoR): таблица «AC · +чем доказан · чем краснеет» в теле issue не пустая и подтверждена мной лично +(red-run на `origin/dev`-версии функции), а не только заявлением автора. + +## Находки + +Нет High. Нет Medium. + +- **Low (не блокирует, снято)**: автор сознательно не завёл мутанта в реестр + (`demo/guard`) для новой ветки `checkCommitEraStatuses`, аргументируя тем, + что функция чистая и тест уже содержит богатый набор отрицательных случаев. + Для трека show это ровно «бухгалтерия» — отсутствие записи в реестре, а не + неподтверждённая защита (защита подтверждена исполнением red/green выше). + Снимаю без действия. + +## Что проверено и корректно + +- Логика эпох (`statusEvents`/`statusIndexAt`/`checkCommitEraStatuses`) + разобрана построчно и прогнана на сценарии из ТЗ лично — поведение совпадает + с описанием «Что меняется» и с обоими текстами находок. +- Обратная совместимость с правилом 10 до #738 (#311) подтверждена + неизменным зелёным тестом и логически: при таймлайне без возвратов + `lastReady` всегда `-1`, так что ветка кода схлопывается к прежнему + поведению (`readyAt` = `firstReady.at`). +- Трейлеры коммита: `Issue: #738`, `User-Visible: no` — верно, changelog не + требуется. Один коммит, ветка `issue/738-rule10-epochs` соответствует + номеру issue. Класса A файлов нет — отдельного ТЗ-AC на трейлер не теряет + силу. +- Одно число — один источник (§8): список `PRE_READY_STATUS` объявлен один + раз как константа и используется и в коде, и неявно описывается в + PROCESS.md (текстом, не импортом) — это документация поведения, а не + второй независимый источник истины; расхождения нет, проверено построчной + сверкой текста канона с кодом. +- `PRE_READY_STATUS` экспортирован, но нигде не импортируется (ни тестом, ни + другим скриптом) — стилистически не отличается от уже существующих + `ALLOWED_STATUS`/`STRICT_STATUS`, не находка. + +## Чего не проверял + +- Полный `npm test`, `npx tsc --noEmit`, `npm run build` целиком — не + перегонял, положился на зелёный Validate этого SHA (run 36821163281); + точечно сам прогнал только изменённый тестовый файл. +- Browser-смоки — не прогонял: `smoke-select.mjs` не выбрал ни одного (нет + фронтенд-диффа). +- Исчерпывающий обход таймлайнов всех открытых веток `S5…S7` на предмет + скрытого прошлого возврата `S5+→S3/S4` — не AC, трек show не требует этого + объёма; сделана только лёгкая проверка по текущим меткам (см. таблицу + гейтов). +- Свежесть скриншотов документации — не гейт задачи, не проверялась. + +## Вердикт + +Зелёный. Код делает ровно то, что заявлено в ТЗ, оба новых и прежний тест +проверены лично на предмет «умеет падать», граница трека show (route: fix) +соблюдена, трейлеры в порядке, гейты по диффу и AC либо прогнаны лично, либо +законно не требуются. + +--- + + + +## Материал раунда + +- Ветка: `issue/738-rule10-epochs`, коммит `021a94959856` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `22e667a9118166033cd5f1a1fd2f2a2287c7b924` + ``` + git log --all --format='%H %T' | grep 22e667a91181 + ``` +- Тело issue: `cd8ce90eb1d3e249c9aca6c38257d69e533d0e4b030cd6f4681f385c407ab264` +- Вердикт конвейера: `green` · High 0 · маршрут `fix`