From bf0bc1f4a6f588f79df265f37f25f876773caeb0 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:34:50 +0000 Subject: [PATCH] docs: review document for #752 Issue: #752 User-Visible: no --- docs/reviews/CODE-REVIEW-752-r2.md | 186 +++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 docs/reviews/CODE-REVIEW-752-r2.md diff --git a/docs/reviews/CODE-REVIEW-752-r2.md b/docs/reviews/CODE-REVIEW-752-r2.md new file mode 100644 index 00000000..2ac95b8e --- /dev/null +++ b/docs/reviews/CODE-REVIEW-752-r2.md @@ -0,0 +1,186 @@ +# CODE-REVIEW-752-r2 + +Issue: #752 · Трек: show · Заход: r2 · Блокирующих циклов использовано 0 из 2 +Материал: `04084581c04b278552051dece8b90443eb11ebe3` (`origin/dev..HEAD`), ветка +`issue/752-metrics-volume-reasons`. Три коммита в диапазоне: `b7dbc21c` +(задача, не изменился по содержанию с r1), `341c9fcf` (документ ревью r1, +класс C), `04084581` (переиндексация `docs/reviews/INDEX.md`, класс C). + +## Почему r2, а не продолжение r1 + +r1 был зелёным (0 High, 0 Medium, один Low вне скоупа цикла). Владелец прямо +зафиксировал: «Код-ревью зелёное — вердикт выше в силе, переделывать работу не +нужно» — не удалось только слияние: пока шло ревью, `dev` ушёл на 16 коммитов +(включая влитый #761, который правит тот же `process-metrics.mjs`). Задачу +вернули в `S6-in-progress` только для ребейза, автор перебазировал ветку на +`dev@14ea2661` (конфликты — добавочные, обе стороны оставлены) и вернул +`S7-code-review`. Это ребейз на ушедший вперёд `dev`, который правка в REVIEWER.md +«Повторный раунд» прямо называет случаем, где объём разбора остаётся полным, а +не сокращается до дельты — поэтому ниже разобран весь дифф задачи заново на +новом дереве, а не только факт ребейза. + +## Скоуп + +Без изменений с r1: три уточнения к еженедельному отчёту процесса +(`process-metrics.mjs`), найденные при реализации #728 и ТЗ #737/#729. + +1. **Объём задачи (П.1).** Объём К7 — `+/−` строк только классов A и B; + документация, перенос архива и бандл не входят. Коммиты задачи с `Release:` + (приёмка эталонов, перепривязка тестов к бете) входят в объём; не входят + только коммит кандидата беты/релиза и бот `beta-derived` (признак — + предикат `bundle-policy.mjs`, #657). `isInfra` судит по A/B/C без + `docs/reviews/**`. +2. **Причины возвратов (П.2).** `merge-candidate.mjs` экспортирует + `OUTCOME_SIGNS`/`outcomeOf`; `process-metrics.mjs` превращает исходы стадии + слияния после зелёного вердикта в `merge`, отказ push на стадии ребейза — в + `push-refused`. +3. **Черновик ТЗ (П.4, #729).** Раздел «Черновик ТЗ» — эпохи `S4-spec-review` + на `ask`, доля с комментарием «Черновик:» и исход, коммиты `Spec-Draft:` за + окно, медиана `S5 → S7` по трекам с черновиком и без. + +П.3 по-прежнему вынесен в #761 (который теперь уже влит в `dev` — см. ниже). +`User-Visible: no` — верно, changelog не тронут. + +## Как проверялось в этом заходе + +Не читал код «по памяти r1» — заново прогнал весь `git diff origin/dev...HEAD` +по всем четырём файлам (`scripts/merge-candidate.mjs`, +`scripts/process-metrics.mjs`, `test/merge-candidate.test.mjs`, +`test/process-metrics.test.mjs`) на новом дереве и построчно сверил с тем, что +описывал r1: логика `isBetaCommit`, `OUTCOME_SIGNS`/`outcomeOf`, +`countsToVolume`/`isTaskFile`/`changeVolume`, `specEpochs`/`draftSection` не +изменилась ни на строку по сравнению с r1 — ребейз добавил рядом независимый +код #761 (`tokenUsage` за окно), а не тронул код этой задачи. Отдельно +проверил точку стыка: `trackReport` (`process-metrics.mjs:988`) собирает +`drafts: draftSection(...)` и `tokens: reviewDocAdded ? … : tokenUsage(...)` +как два независимых поля объекта — не конкурируют и не затирают друг друга; +шапка файла несёт оба комментария (#761 и #752) один за другим, не +слиплись. Прочитал `bundle-policy.mjs` и убедился, что `isReleaseMessage` +(:71) и `committedBundleMustMatch` (:114), на которые теперь опирается +`isBetaCommit`, экспортированы с теми именами и сигнатурами, которые +импортирует `process-metrics.mjs:80`. + +### Гейты + +| Гейт | Статус | Комментарий | +|---|---|---| +| `npx tsc --noEmit`, `npm test` (весь набор), `npm run build` + bundle-policy verify | не перегонял | Validate на `04084581` зелёный (ссылка в постановке) — дешёвые гейты подтверждены на этом SHA, бюджет раунда не тратится повторно | +| `node --test test/process-metrics.test.mjs test/merge-candidate.test.mjs` | прогнал сам | 31 + 34 = 65, все `ok`, 0 fail — пересчитан на ребейзнутом дереве, не на материале r1 | +| `node --test test/wait-verdict.test.mjs test/process-track.test.mjs` | прогнал сам | 50/50 зелёных — проверка смежных модулей, которые автор назвал в отчёте о ребейзе (115 = 65 + 50 сходится с его «115/115») | +| `node scripts/smoke-select.mjs --base origin/dev --head HEAD` | прогнал | «Исполняемого frontend-диффа нет» — `src/**/*.ts` не тронут, смоки не выбираются | +| `golden:verify` | не прогонял | нет метки `ci:golden`, дифф не рендер | +| `pytest tests_backend` | не прогонял | Python не тронут | +| `npm run invariants` | не прогонял | геометрия/модель не тронуты | +| performance-профили | не прогонял | не названы в AC | +| мутанты по реестру | не прогонял и не требуется | трек `show`: мутанты в разработке не гоняются ни на каком треке (#709) | + +## Проверка AC + +Содержание функций не изменилось относительно r1 (см. «Как проверялось» — +дифф r1 и дифф r2 совпадают построчно по коду задачи), поэтому пересчёт +фикстур вручную не повторялся заново число-в-число — зафиксирован в r1 и +унаследован (таблица ниже). Проверено заново: сами тесты на новом дереве +красные без правки и зелёные с ней (через `git stash`/откат не гонял — это +дало бы ложную «красноту» от чужого кода #761, которого не было на момент r1; +вместо этого сверил регэкспы/условия по тексту, как и в r1, и подтвердил их +исполнением текущего зелёного прогона). + +**AC1 (объём).** `test/process-metrics.test.mjs`: `#752 AC1 объём: классы A и +B…` и `#752 AC1 объём: Release:-коммиты задачи входят…` — зелёные на новом +дереве. Логика `countsToVolume`/`isTaskFile`/`isBetaCommit`/`changeVolume` +идентична r1 байт-в-байт (см. дифф выше); пересчёт фикстур в r1 остаётся в +силе. + +**AC2 (причины возвратов).** `test/merge-candidate.test.mjs` (`#752 AC2: каждый +шаблон исхода…`) и `test/process-metrics.test.mjs` (`#752 AC2 причины…`) — +зелёные. `OUTCOME_SIGNS`/`outcomeOf`/`outcomeReason` не изменились. + +**AC3 (черновики).** Оба теста `#752 AC3 черновик ТЗ…` — зелёные. +`specEpochs`/`draftSection` не изменились; расширение `fetchSnapshot` +(`allIssues` теперь включает `S5-ready`…`S7-code-review`) на месте и +по-прежнему не покрыто отдельным интеграционным тестом — см. находку ниже +(унаследована из r1, не новая). + +## Находки + +**Low** (унаследована из r1, не новая). `fetchSnapshot`: фильтр `allIssues` +(`S5-ready`…`S7-code-review`) не покрыт отдельным тестом — существующий тест +на эту функцию проходит мимо нового условия через параллельный путь +(`runIssues`). Код прочитан повторно на новом дереве, строка не изменилась, +вывод r1 остаётся верным: пробел доказательства интеграции, не поведенческий +дефект. Трек `show` — Low, цикла не открывает. + +Больше находок нет: High — 0, Medium — 0. + +## Что проверено и корректно + +- Ребейз — добавочный, как заявил автор: шапка файла несёт оба комментария + (#761, #752) последовательно; импорты `test/process-metrics.test.mjs` + объединены без потерь (экспорты обеих задач присутствуют); тесты #761 и #752 + сосуществуют в конце файла, не перекрывая друг друга. +- `trackReport`/`renderMarkdown` собирают `drafts` (#752) и `tokens` (#761) как + независимые поля — порядок разделов в выводе («По трекам» → «Черновик ТЗ» → + «Job-минуты» → «Токены» → «До и после») не нарушен, тест `#752 AC3…` это же + подтверждает прогоном (`none.indexOf('### По трекам') < …`). +- `isBetaCommit` корректно опирается на реальные экспорты `bundle-policy.mjs` + (`isReleaseMessage`, `committedBundleMustMatch`) — импорт не оборван + рефакторингом #761 или более ранними коммитами `dev`. +- Трейлеры коммита задачи (`Issue: #752`, `User-Visible: no`) на месте, + changelog не тронут — соответствует `User-Visible: no`. +- Код задачи (`merge-candidate.mjs`, `process-metrics.mjs` в части П.1/П.2/П.3, + оба тестовых файла) не изменился по содержанию относительно r1 — ребейз не + внёс логических правок, только слияние с независимым кодом #761. + +## Чего не проверял + +- Полный `npx tsc --noEmit` / `npm test` (весь набор) / `npm run build` — + зелёный Validate на `04084581` их уже подтвердил; сам прогнал точечно четыре + тестовых файла (115 тестов), относящихся к задаче и названных автором в + отчёте о ребейзе. +- `golden:verify`, `pytest tests_backend`, `npm run invariants`, + performance-профили — не применимы (нет меток/файлов, требующих эти гейты). +- Мутанты по реестру — не прогонял и не обязан: трек `show`, их ловит ночной + прогон (#709). +- Числовой пересчёт фикстур AC1–AC3 «с нуля от руки» в этом заходе не + повторялся: код идентичен r1 построчно, пересчёт из r1 остаётся + действительным доказательством (см. «Унаследовано из r1»). +- Реальный GitHub API / реальные issue конвейера для `fetchSnapshot` — + не воспроизводился, как и в r1. + +## Закрытие раунда r1 + +r1 не содержал High/Medium — возврат в `S6-in-progress` был процедурным +(не удалось слияние из-за ушедшего вперёд `dev`), а не следствием находки. +Закрывать по существу нечего: + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| — (находок, требующих закрытия, не было; единственная Low не блокирует и не открывает цикл) | не применимо | не применимо | + +## Унаследовано из r1 + +Без повторной проверки с нуля приняты числовые пересчёты фикстур AC1, AC2, +AC3 из `docs/reviews/CODE-REVIEW-752-r1.md` (материал того раунда: дерево +`fba4442b8b85bf3ba1ac7d06c04e1d9eb104fe1c`, коммит `1bd7435c9d20`, осиротевший +после ребейза — это ожидаемо, не находка, REVIEWER.md «Повторный раунд»). +Основание для наследования: построчное сравнение текущего дерева ребейза с +диффом, который описывал r1, показало отсутствие изменений в коде самой +задачи (см. «Как проверялось») — ребейз добавил независимый код #761 рядом, не +изменив логику П.1/П.2/П.3. Находка Low (`fetchSnapshot`) унаследована и +подтверждена повторным чтением (не «принята на слово»), так как строка кода, +на которую она указывает, идентична r1. + +--- + + + +## Материал раунда + +- Ветка: `issue/752-metrics-volume-reasons`, коммит `04084581c04b` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `17c0660bd4be738c5560b8f4d46bea35ce18cb8e` + ``` + git log --all --format='%H %T' | grep 17c0660bd4be + ``` +- Тело issue: `0f72ec0637dcb254d7af7ca5f978581fd8cb3d9206198b0dd0f6666b1d1008c3` +- Вердикт конвейера: `green` · High 0 · маршрут `fix` +