Files
2026-09-28 20:07:11 +00:00

19 KiB
Raw Permalink Blame History

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 / legacy trivial/small / без меток → ask), приоритет меток, лимит циклов для явно помеченных track:show/track:ship/ track:ask в _process.yml:87-99 — там же, дерево 2faf4770f1ba6a3.... Дельта r2 добавляет только новую ветку ПОСЛЕ этой логики (строки 224-242) и не меняет ни один из проверенных r1 путей; сама функция trackFromLabels в дельте не тронута (diff scripts/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.yml guard 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 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 2645a194ffcd661ca9d05eb38db68d9e378faae9
    git log --all --format='%H %T' | grep 2645a194ffcd
    
  • Тело issue: c74209278f8dd164514eda40d8841d6eefdeffd3b490a90f47b20e3ff2b667e7
  • Вердикт конвейера: green · High 0