18 KiB
CODE-REVIEW-736-r1
Issue: #736 · Этап: code · Трек: show · Заход: r1 · блокирующих циклов использовано 0/2
Материал раунда: git log --oneline origin/dev..HEAD и git diff origin/dev...HEAD на
2ed56bbabd6554afa9380128d688b57004dd47ab (рабочая копия на нём, HEAD подтверждён git rev-parse HEAD).
Диапазон — один коммит 2ed56bba. Diffstat:
.github/workflows/_nightly.yml | 51 ++++-
PROCESS.md | 22 ++
scripts/night-red.mjs | 300 ++++++++++++++++++++++++++
test/night-red.test.mjs | 462 +++++++++++++++++++++++++++++++++++++++++
test/nightly-workflow.test.mjs | 38 ++++
Скоуп
Инфраструктурная задача (класс B + документация §10.4), выделена из #727.
После красного полного ночного Validate на dev новая job night_red
(_nightly.yml) запускает scripts/night-red.mjs, который находит последнюю
зелёную ночь, вычисляет подозреваемые задачи (по Issue: #NN коммитов
классов A/B без Release: между зелёной и красной ночью) и пишет каждой один
комментарий, не повторяясь в рамках одной серии красных ночей. SCOPE.md не
применим напрямую — это процесс/CI-инструмент, не продуктовая фича; трек
show подтверждён владельцем в комментарии к issue («трек: show… Следующий
статус: S5-ready»).
Маршрут критериев §5 (трек show):
complexity— владелец оценил сложность 3/10; код компактный, без скрытых развилок — проходит.surfaces— одна поверхность:_nightly.yml+scripts/night-red.mjs+ абзац PROCESS.md §10.4 — проходит.migration— нет изменения конфига и compatibility-полей продукта — проходит.ux-contract— нет UX, задача не трогает карточку/интеграцию — проходит.perf-touch— не касается производительности карточки или touch — проходит.undocumented— поведение полностью зафиксировано в теле issue (раздел «Что меняется», К1–К7) и теперь задокументировано в PROCESS.md §10.4 тем же коммитом — проходит.
Все критерии §5 пройдены → route: fix (не reclassify).
Как проверялось
- Прочитан диапазон коммитов и полный дифф (
git log,git diff origin/dev...HEAD). - Прочитано тело issue #736 (раздел
## ТЗ, К1–К7, таблица AC) и комментарии (оценка владельца, handoff автора). - Построчно прочитан
scripts/night-red.mjs— сопоставлен с К1–К6 ТЗ. - Построчно прочитан дифф
.github/workflows/_nightly.yml— сопоставлен с К1, К7, правами и условиемif. - Прочитаны тесты
test/night-red.test.mjs(7 тестов) и добавленный тест вtest/nightly-workflow.test.mjs(1 тест) — сверены утверждения с кодом. - Проверены вызываемые внешние примитивы на предмет корректного переиспользования (не доказательство новым кодом, а проверка, что контракт соблюдён):
classify(scripts/change-classes.mjs),issueTrailers/hasReleaseTrailer(scripts/release-membership.mjs,scripts/ship-review.mjs),evaluateCiProof/loadGithubProofContext/CI_PROOF_POLICIES(scripts/ci-proof.mjs),isMainModule(scripts/spawn-portable.mjs),validateJobs/resolveJobRules(scripts/workflow-jobs.mjs,scripts/ci-proof.mjs) — все существуют и сигнатуры совпадают с использованием. - Прогнаны тесты задачи напрямую:
node --test test/night-red.test.mjs test/nightly-workflow.test.mjs— 13/13 зелёных (bash-тесты не пропущены,hasBash()истинен в этой среде). - Доказательство «тест умеет падать» для двух защитных AC — ручная мутация и прогон (после — восстановление файла,
git statusподтвердил чистую копию):- убрана проверка
hasReleaseTrailerвcountsForNightRed→ упало 3 из 7 тестов (AC1 К3, AC2 К4–К5, AC2/AC3 bash); commentVerdictупрощён до «всегда comment» (убрано правило «не повторяться в серии») → упало 3 из 7 тестов (AC2 К4–К5, AC2 К5, AC2/AC3 bash). Оба защитных правила ловятся без мутационного прогона реестра — по trackshowэто допустимо (мутанты в разработке не гоняются ни на одном треке, §5).
- убрана проверка
- Проверены трейлеры коммита:
Issue: #736,User-Visible: no— корректно, changelog не трогается, видимого пользователю поведения нет. - Сверено размещение абзаца PROCESS.md: внутри §10.4, рядом с абзацем о ночном ship-ревью (#727), как и заявлено в ТЗ (К7).
- Сверена логика потолка прав тонкого файла (
test/default-branch-workflows.test.mjs:195-215):night_redпроситactions: read, contents: read— подмножество уже имеющегосяactions: write, contents: readу других job тела; объединение прав не меняется, тонкийnightly.ymlвmainне трогается — подтверждено чтением теста и логикиunionPermissions, не исполнением (gate:small не перегонялся — обоснование ниже).
Таблица AC · чем доказан · чем краснеет
| AC | Что | Доказано | Чем краснеет (проверено) |
|---|---|---|---|
| AC1 (К2–К3) | последняя зелёная ночь и подозреваемые | test/night-red.test.mjs, 3 теста (findLastGreen, rangeSuspects, countsForNightRed) на настоящем git во временном репозитории с реальным ci-proof |
Проверено мутацией: убрана фильтрация Release: → тест AC1 К3 падает. Остальные случаи (лёгкий zелёный, поздний, чужая ветка, окно 50, G==R) разобраны чтением — тест явно утверждает каждый из них отдельным assert |
| AC2 (К1, К4, К5) | когда и сколько комментариев | test/night-red.test.mjs, 3 теста + bash-тест на реальном HTTP-сервере и подменённом gh |
Проверено мутацией: упрощение commentVerdict (без проверки «та же серия») → тест AC2 К4–К5 и AC2 К5 падают. conclusion фильтр (cancelled/success/timed_out) разобран отдельным тестом с тремя исходами |
| AC3 | проводка, права, канон | test/nightly-workflow.test.mjs (контракт YAML + содержимого PROCESS.md), ревью кода |
Проверено чтением, не исполнением: if-условие, права job, токены, checkout-параметры, отсутствие npm ci, наличие абзаца К7 в шапке _nightly.yml и в PROCESS.md §10.4 — всё сверено построчным assert.match против реального YAML/MD. Актуальность bash -n на теле шага подтверждена (прогнано как часть теста) |
Пустых третьих столбцов нет.
Находки
Находок нет. High: 0, Medium: 0, Low: 0.
Разобраны и признаны корректными потенциально спорные места:
- Порядок коммитов в
rangeSuspects/commentBody(oldest→newest внутриbyIssue,LIST_LIMITберёт первые N = самые старые, явно подтверждено тестомAC1 К3иAC2 К4–К5) — не дефект, просто явный выбор, не влияющий на AC. - Слияние (
--no-merges) исключает коммит-слияние из диапазона даже если у него собственныйIssue:трейлер (тестsidebranch, #6) — соответствует тексту ТЗ К3 дословно («сами слияния не считаются»). evaluateCiProofвызывается без явногоcandidate.sha(default{}) — безопасно, так как функция сама подставляетrunShaOf(run); тот же паттерн уже используется вship-review.mjs, это не новый риск.- Гонка «issue закрылась между
viewиcomment» — не покрыта тестом, но не AC и не риск, явно описанный в ТЗ; cost/benefit на trackshowне оправдывает находку.
Что проверено и корректно
- Скрипт работает только при
conclusion: failureкрасного прогона (К1) — веткиcancelled/success/timed_outдают только строку сводки, проверено тестом с тремя исходами. - Поиск
G(К2): 50 последних dispatch-прогонов, фильтр поcompleted+success, raньше красного по времени, предок поgit merge-base --is-ancestor, зелёныйci-proofпо политикеrelease(лёгкий прогон —stale). Порядок проверок (сначала дешёвые, потом загрузкаci-proof) подтверждён тестомloaded— доказательство грузится только у прошедших дешёвые фильтры. - Подозреваемые (К3):
git rev-list --no-merges G..R, фильтр класса A/B безRelease:, коммиты без трейлера — в «без задачи», коммиты изdocs/**— не считаются, ветка, влитая вторым родителем, входит, само слияние — нет. - Шаблон комментария (К4): оба прогона, до 10 коммитов («и ещё N»), упавшие job, фраза «подозреваемая, а не виновная», маркер
hp:night-red green=… red=… commits=…, несущий все (не только показанные) коммиты задачи. - Подавление шума (К5): закрытая задача — не комментируется, строка в сводке; одна и та же пара — не повторяется; новый коммит задачи в той же серии — комментарий снова; новая зелёная ночь начинает новую серию.
- Цвет ночи (К6): сбой скрипта/API —
::warning::и строка сводки, код возврата 0,continue-on-error: trueна уровне job — проверено на реальном bash с имитацией сбоя Actions API (500) и отсутствующего скрипта. - Права и токены (К7, AC3):
night_redпросит толькоactions: read, contents: read;ACTIONS_TOKEN=github.token,GH_TOKEN(дляgh) =secrets.HP_PROCESS_TOKEN— подтверждено и YAML-тестом, и bash-тестом (реальные HTTP-запросы несутBearer actions-token,gh-лог несётtoken=process-token). dispatchотдаёtrun_idтем же шагом, что иhead_sha, до шага ожидания — красныйwatchне теряет выход.- Канон: абзац «Красная ночь (#736)» в PROCESS.md §10.4 рядом с абзацем о ночном ship-ревью; шапка
_nightly.ymlназывает адресата сигнала. Оба проверены построчным сопоставлением с текстом ТЗ. - Трейлеры коммита корректны (
Issue: #736,User-Visible: no), changelog не нужен и не тронут — задача не меняет видимое пользователю число или поведение (§8неприменим: ничего не дублируется для пользователя). test/default-branch-workflows.test.mjsлогически не ломается: добавленная job снижает, а не расширяет права относительно существующего потолка тонкого файла.
Чего не проверял
npx tsc --noEmit,npm test(полный),npm run build+ сверка бандла — не перегонял: Validate на этом же SHA2ed56bbaзелёный (ссылка на прогон дана в постановке), дешёвые гейты этим подтверждены. Дополнительно прогнал целевые тестовые файлы задачи напрямую (п. 7 выше) — зелёные.- Смоки в браузере — не прогонял:
node scripts/smoke-select.mjs --base <base> --head <head>не запускался отдельно; диапазон не трогаетsrc/**или что-либо, влияющее на визуальный рендер карточки (только.github/workflows/**,scripts/**,test/**,PROCESS.md) — браузерных поверхностей в диффе нет, это чисто серверный/CI-скрипт. Решение: не прогонять, так как изменённые пути не пересекаются ни с одним смоук-сценарием. npm run golden:verify— не прогонял: меткиci:goldenна задаче нет, диапазон не трогает путь отрисовки плана.python -m pytest tests_backend— не прогонял: диапазон не содержит правокcustom_components/**/*.py.npm run invariants— не прогонял: диапазон не трогает геометрию модели.- Performance-профили — не названы в AC, не прогонял.
- Реальный прогон против живого GitHub API (загрузка
ci-proofчерезactions: read,gh issue view/commentсHP_PROCESS_TOKEN) — не воспроизводился: это заявленный автором риск («Против настоящего GitHub не проверены…»), out of scope для ревью кода на материале — первая живая красная ночь покажет это на практике; механизм отказоустойчив (continue-on-error,::warning::), поэтому сбой первого реального прогона не красит ночь и не блокирует бету. - Мутационный прогон реестра — не запускался: на треке
showмутанты в разработке не гоняются ни одним агентом (#709), отсутствие прогона — не находка. Вместо этого вручную проверено (см. «Как проверялось», п. 8), что тесты ловят минимум по одной осмысленной порче на каждый защитный AC.
Вывод
AC1–AC3 выполнены и доказаны чтением + исполнением тестов задачи; оба защитных правила (исключение Release:-коммитов, подавление повторного комментария в серии) проверены на умение падать вручную. Находок нет.
Вердикт: зелёный.
Материал раунда
- Ветка:
issue/736-night-red-comment, коммит2ed56bbabd65— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
8186f6ff39cd6868725a79f4a7feeb444c6c6d88git log --all --format='%H %T' | grep 8186f6ff39cd - Тело issue:
6cd408eba981cb82629e225f025e183f70de0ac956d12cc26cf1d6d07c983ec2 - Вердикт конвейера:
green· High 0 · маршрутfix