docs: review document for #752

Issue: #752
User-Visible: no
This commit is contained in:
claude[bot]
2026-10-01 15:34:50 +00:00
parent 04084581c0
commit bf0bc1f4a6
+186
View File
@@ -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.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/752-metrics-volume-reasons`, коммит `04084581c04b` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `17c0660bd4be738c5560b8f4d46bea35ce18cb8e`
```
git log --all --format='%H %T' | grep 17c0660bd4be
```
- Тело issue: `0f72ec0637dcb254d7af7ca5f978581fd8cb3d9206198b0dd0f6666b1d1008c3`
- Вердикт конвейера: `green` · High 0 · маршрут `fix`
<!-- hp:usage input_tokens=4354 output_tokens=16824 cache_creation_input_tokens=104371 cache_read_input_tokens=1767411 num_turns=32 -->