19 KiB
CODE-REVIEW #695 r2
Материал: origin/dev..HEAD, ровно f6c76b7351b1d0b9a61954b0153a44bb098bc7f3
(рабочая копия уже на нём). Диапазон трёх коммитов: 57ce1072 (реализация r1,
уже разобрана в CODE-REVIEW-695-r1), 51854aea (публикация документа r1,
служебный коммит конвейера), f6c76b73 (правка Medium из r1 — материал этого
раунда). Дельта этого раунда — ровно 57ce1072..f6c76b73:
.github/workflows/_process.yml, scripts/mutation-registry.mjs,
scripts/task-packet.mjs, test/review-doc-guard.test.mjs,
test/task-packet.test.mjs.
Скоуп
Единственная блокирующая находка r1 (Medium, в скоупе) — канон §5.1
(«инфраструктурная задача (§1) без трековой метки — как track:show») не
был реализован ни в _process.yml (лимит циклов), ни в task-packet.mjs
(отображаемый трек). Автор заявляет это закрытым коммитом f6c76b73
(комментарий «Сделано (r1)»). Разбор по PROCESS.md §2.10 — по дельте: полный
пересчёт находки r1, остальное (таблица треков §5, trackFromLabels() для
явно помеченных задач, якоря конспектов, трейлеры) унаследовано без повтора —
дельта их не задевает (ни один из пяти изменённых файлов не входит в
доказательную базу этих пунктов r1, кроме task-packet.mjs, где тронута
только инфраструктурная ветвь track, разобранная ниже).
Как проверялось
| Гейт | Команда | Результат |
|---|---|---|
| Validate на материале | CI run на f6c76b73 (ссылка в задаче ревью) |
зелёный; дешёвые гейты (tsc, npm test, build+bundle-policy) не перегонял — приняты по этой ссылке (#343) |
| Целевой юнит-набор | node --test test/task-packet.test.mjs test/review-doc-guard.test.mjs |
80/80 и 64/64 pass, 0 fail |
process-gate.mjs (офлайн) |
node scripts/process-gate.mjs --range origin/dev..HEAD |
«гейт пройден, предупреждений 0» |
mutation-gate --check |
node scripts/mutation-gate.mjs --check |
guard-infra-keeps-ask-limit — ok; packet-infra-track-ignores-show-default — ok; browser guards: 200/200; 3 предупреждения — все про #650 (baseline, не связаны с диффом — совпадают с r1) |
Мутант guard-infra-keeps-ask-limit |
вручную заменил limit=2 на limit=4 # mutant в _process.yml, прогнал --test-name-pattern="r1 #695" test/review-doc-guard.test.mjs, вернул файл (git diff --stat после — пусто) |
краснеет: AssertionError, тест ловит мутацию |
Мутант packet-infra-track-ignores-show-default |
вручную заменил тернарник hasTrackLabel(labels) ? trackFromLabels(labels) : 'show' на trackFromLabels(labels) в task-packet.mjs, прогнал --test-name-pattern="r1 #695" test/task-packet.test.mjs, вернул файл |
краснеет: AssertionError: expected 'инфраструктурный · show', actual 'инфраструктурный · ask' |
| Исполнение bash-ветки guard (не только чтение) | Извлёк новый блок .github/workflows/_process.yml:224-242 в отдельный скрипт с mock gh/has, прогнал 6 сценариев (нет меток+только инфра-файлы; нет меток+файл класса A; явный track:ask; явный track:show; отказ gh api; legacy small) |
все 6 дали ожидаемый limit — см. таблицу «Что проверено» |
| Синтаксис bash-шага | python3 -c "yaml.safe_load(...)" извлёк run: строку guard, bash -n на неё |
синтаксис корректен |
| Node-однострочник guard | Прогнал ровно ту же node --input-type=module -e '...' строку на трёх наборах путей (только scripts/+test/; с src/houseplan-card.ts; пустой список) |
exit 0 / 1 / 1 — соответствует логике «инфраструктура доказана только непустым списком путей без класса A» |
smoke-select.mjs |
node scripts/smoke-select.mjs --base 57ce1072 --head f6c76b73 |
«Исполняемого frontend-диффа нет (src/**/*.ts не тронут)» — смоки не выбираются, выбирать нечего |
| Трейлеры и провенанс коммита | git show -s --format=full f6c76b73 |
Issue: #695, User-Visible: no, корректно: изменение автоматизации/скриптов, ни одного пользовательского поведения продукта не задето |
| Сверка со сформированным пакетом | node scripts/task-packet.mjs --issue 695 |
трек issue #695 (само помечено track:show владельцем) печатается как инфраструктурный · show — согласуется с явной меткой |
Не прогонял (и почему): golden/скриншоты, браузерные смоки (подтверждено
smoke-select.mjs — нечего выбирать), pytest tests_backend, инварианты
модели, check-docs.mjs (диапазон не касается src/**), performance-профили —
диапазон не затрагивает ни одного файла класса A и не меняет геометрию/рендер.
Полный npm test (3223 теста) не перегонял целиком — принят по зелёному
Validate на этом SHA (#343); перегонял точечно только изменённые тестовые
файлы и мутации по ним, плюс собственноручный харнесс исполнения bash-ветки
(таблица выше) — этого требует #454 (inline-shell без исполнения не
доказывает поведение), выполнено сверх минимума, а не вместо него.
Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
Medium: §5.1 («инфраструктура без трековой метки — track:show») не реализован ни в _process.yml (лимит циклов), ни в task-packet.mjs (отображаемый трек); зелёный тест task-packet.test.mjs:171 прямо утверждал старое поведение |
_process.yml: новая ветка guard (строки 224-242) — при отсутствии track:*/small/trivial берёт диффа ветки против dev через compare API, классифицирует пути classify() из process-gate.mjs; при непустом списке (< 300, потолок ответа) без единого файла класса A ставит limit=2. task-packet.mjs: infraTrack = hasTrackLabel(labels) ? trackFromLabels(labels) : 'show' (строка 189), трек инфраструктурной задачи теперь печатается как инфраструктурный · ${infraTrack} вместо голого 'инфраструктурный'. Тест task-packet.test.mjs:171 (#632), на который указывала находка, переписан: assert.equal(packet.track, 'инфраструктурный · show', ...) — прежнее ожидание 'инфраструктурный' больше не в коде. |
.github/workflows/_process.yml:224-242; scripts/task-packet.mjs:143-144,189-191; test/task-packet.test.mjs:110,180,231-241; test/review-doc-guard.test.mjs:971-982; оба новых мутанта (scripts/mutation-registry.mjs) реально ловят регресс — проверено воспроизведением (таблица «Как проверялось»), не по названию. Исполнение bash-ветки (6 сценариев харнессом) подтверждает: без метки трека и без класса A → limit=2; с любой явной меткой трека → блок не трогает limit; при отказе gh api или файле класса A → limit остаётся консервативным (не понижается ошибочно). |
Находка полностью закрыта: и механизм (§1: «ни одного файла класса A» —
ровно та же формула, что в PROCESS.md §1), и обе точки, которые r1 назвал
нереализованными, и тест, который r1 предъявил как доказательство обратного
поведения, — всё сходится с текстом §5.1 дословно («инфраструктурная задача
(§1) без трековой метки — как track:show»).
Унаследовано из r1 (без повторной проверки — дельта не задевает)
- Таблица треков §5 и её колонки, согласованность PROCESS.md / AGENTS.md /
docs/process/AUTHOR.md/docs/process/REVIEWER.md— документCODE-REVIEW-695-r1.md, дерево2faf4770f1ba6a32a599552db9c611bfb5cc5a18. Ни один из этих четырёх файлов не входит в дельту57ce1072..f6c76b73. trackFromLabels()для явно помеченных задач (track:ship/track:show/track:ask/ legacytrivial/small/ без меток →ask), приоритет меток, лимит циклов для явно помеченныхtrack:show/track:ship/track:askв_process.yml:87-99— там же, дерево2faf4770f1ba6a3.... Дельта r2 добавляет только новую ветку ПОСЛЕ этой логики (строки 224-242) и не меняет ни один из проверенных r1 путей; сама функцияtrackFromLabelsв дельте не тронута (diffscripts/task-packet.mjsдобавляет толькоhasTrackLabelи меняет строку сборкиtrack, не трогая телоtrackFromLabels).- Якоря конспектов (AC2 #634), ключевые формулировки, обратная
совместимость легаси-меток
small/trivial, трейлеры провенанса, отсутствие продуктового кода в диффе — там же, дерево2faf4770f1ba6a3...; ни один из файлов этой доказательной базы (PROCESS.md,AUTHOR.md,REVIEWER.md,test/process-digests.test.mjs) не входит в дельту r2.
Что проверено и корректно
- Механический признак §1 применён идентично канону: и в
_process.yml(список файлов диффаdev...branch, ни одногоclassify() === 'A'), и вPROCESS.md§1 («ни одного файла класса A») — то же условие, что уже реализовано вbranchIsInfrastructure()(task-packet.mjs, не тронут этим диффом) и в самомprocess-gate.mjs. Никакого нового, отличного от канона определения «инфраструктуры» дифф не вводит. - Приоритет явной метки владельца сохранён: guard пропускает новую ветку
целиком (
&& ! has track:ship && ! has track:show && ! has track:ask && ! has small && ! has trivial), если стоит любая из пяти меток — идентичный набор в JS (hasTrackLabel). Подтверждено исполнением (харнесс, сценарии 3, 4, 6) и юнит-тестом'метка владельца главнее'. - Fail-safe при неполном доказательстве: пустой список файлов, отказ
gh api, наличие файла класса A или обрезанный (≥300) ответ compare — во всех случаяхlimitостаётся 4 (не понижается ошибочно), задача не наказывается лимитом 2 без доказанной инфраструктуры. Подтверждено исполнением (харнесс, сценарии 2, 5) и отдельным прогоном node-однострочника на пустом списке. - Мутанты
guard-infra-keeps-ask-limitиpacket-infra-track-ignores-show-defaultреально ловят регресс — проверено ручным воспроизведением обеих мутаций (не по названиюokвmutation-gate --check, а прогоном упавшего теста). - Синтаксис нового bash-блока и YAML-документа —
bash -nиyaml.safe_loadне нашли ошибок; блок стоит внутри уже существующегоif [ -n "$stage" ], использует уже установленноеlimitдо последующих проверокEXHAUSTED/spent -ge limit(строки 270-299) — порядок вычисления корректен, «состояния гонки» с более поздним использованиемlimitнет. - Трейлеры коммита —
Issue: #695,User-Visible: no(корректно: не задето ни одно пользовательское поведение продукта), веткаissue/695-track-labels. - Согласованность с самим issue #695: у issue стоит метка
track:show— собранный пакет (task-packet.mjs --issue 695) печатаетинфраструктурный · show, то есть явная метка отражена корректно и задокументированный пример (issue #695 сам себе) воспроизводится.
Чего не проверял
- Живой прогон
_process.ymlguard job на реальном GitHub Actions раннере с настоящимgh api compare— не воспроизводил; логика проверена чтением синтаксиса, ручным bash-харнессом с мок-gh/has(6 сценариев, см. таблицу) и юнит-тестом на текст блока. Записываю явно: для самого факта исполнения на реальном GitHub API — проверено чтением и контролируемым харнессом, не живым запуском workflow. Это не новый пробел этой задачи — тот же пробел зафиксирован в r1 для всей ветки guard job (тестов, исполняющих_process.ymlнапрямую, в репозитории нет ни для старой, ни для новой логики). - Поведение конвейера по треку (мутанты на диффе кандидата
ship, слияние без ревью модели, ребейз-семантика) — вне скоупа #695, это #696, не проверял. process-labels/labels.tsv(папка владельца, вне git-дерева) — файл недоступен ревью, как и в r1.- golden/скриншоты, браузерные смоки (кроме факта, что
smoke-select.mjsничего не выбрал),pytest tests_backend, инварианты модели, performance-профили — диапазон не касается визуала, геометрии или Python. - Ребейз-устойчивость якорей мутантов
guard-infra-keeps-ask-limit/packet-infra-track-ignores-show-defaultна дальнейших ребейзах — не тестировал долгосрочную устойчивость find/replace патчей, только их текущую верность материалу.
Вердикт
Единственная находка r1 (Medium, в скоупе) закрыта построчно: оба места,
которые она называла нереализованными, реализованы правилом, дословно
совпадающим с §5.1; тест, который r1 предъявил как живое доказательство
старого поведения, переписан и подтверждает новое; оба новых мутанта реально
ловят регресс — проверено воспроизведением, а не по имени ok; сама bash-
ветка проверена не только чтением, но и контролируемым исполнением на шести
сценариях. Новых находок дельта 57ce1072..f6c76b73 не даёт: правка узкая,
ограничена ровно заявленным скоупом, не трогает ни один файл класса A, не
меняет ни одну ранее проверенную ветвь trackFromLabels/таблицы §5.
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0
Материал раунда
- Ветка:
issue/695-track-labels, коммитf6c76b7351b1— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
2645a194ffcd661ca9d05eb38db68d9e378faae9git log --all --format='%H %T' | grep 2645a194ffcd - Тело issue:
c74209278f8dd164514eda40d8841d6eefdeffd3b490a90f47b20e3ff2b667e7 - Вердикт конвейера:
green· High 0