Files
houseplan-card/docs/reviews/CODE-REVIEW-632-r3.md
T
2026-09-24 05:07:19 +00:00

18 KiB
Raw Blame History

CODE-REVIEW-632-r3

Issue: #632 · этап: код-ревью · заход r3 · блокирующих циклов израсходовано 1 из 4 Трек: инфраструктурный (ускоренный вход, AGENTS.md §1 / PROCESS.md §1) — весь дифф класса B, ни одного файла класса A (подтверждено ниже).

Материал: HEAD = 14396ed0b186dc9b883f0b26e460458828dcb58c («docs(reviews): индекс после сдвига каталога (#632)»), рабочая копия уже на нём. git log --oneline origin/dev..HEAD: 5 коммитов; git diff origin/dev...HEAD --stat:

docs/reviews/CODE-REVIEW-632-r1.md | 231 ++++++++++++++
docs/reviews/CODE-REVIEW-632-r2.md | 202 ++++++++++++++
docs/reviews/INDEX.md              |   4 +-
scripts/mutation-registry.mjs      |  44 +++++++
scripts/task-packet.mjs            |  51 ++++++-
test/task-packet.test.mjs          |  69 ++++++-

Почему это r3, а не продолжение зелёного r2 — реконструкция по issue и логам

r2 (docs/reviews/CODE-REVIEW-632-r2.md, материал b64bc932) уже вынес зелёный вердикт: High 0, Medium 0. Зелёный цикла не образует и должен двигать задачу вперёд (§4). То, что ревью назначено снова, — не сигнал о находке, а следствие события после вердикта; разобрал по комментариям issue и логам CI, а не со слов автора:

  1. Пока шло ревью r2, dev продвинулся на 2 коммита; автор перебазировал ветку на dev@c8f9b5d3 → кандидат 1e866291.
  2. Validate на 1e866291 красный (run 35949058000, conclusion: failure, проверено gh run view). Разобрал сам, какой именно job/шаг упал:
    $ gh run view 35949058000 --json headSha,conclusion,status,jobs
    headSha 1e86629189ddf61eacae82fac281b7a13915611a conclusion failure
    Предполёт: документация, провенанс, процесс   failure
    Фронтенд: типы, юниты, мутанты, синхрон бандла   success
    Мутанты по диффу (1..6/6)                         success (все шесть шардов)
    
    Упал только предполётный job; все мутантные шарды и фронтенд-гейт — зелёные на этом кандидате. Внутри упавшего job — конкретно шаг workflow_sync:
    $ gh run view 35949058000 --log-failed | grep -i "process.yml\|различаются"
    РАСХОЖДЕНИЕ: process.yml в main и dev различаются.
    mutation-gate.yml: main и dev идентичны
    process-resume.yml: main и dev идентичны
    FAIL process.yml и mutation-gate.yml в main и dev (failure)
    
    Это проверка «.github/workflows/process.yml в main совпадает с dev» — репозиторного уровня инвариант, никак не зависящий от дерева ветки #632 (её диф вообще не трогает .github/workflows/**, см. список файлов выше). Причина расхождения — независимая правка #634 в main, не отражённая в зеркале; сам автор её так и определил в issue.
  3. Автор зеркалировал main (main = 7752329d) и переподписал вершину без изменения дерева: 14396ed0 имеет то же дерево, что и кандидат до переподписания (дерево 0d959028, по словам автора) — я это не принимаю на слово, а проверяю ниже блобами по каждому файлу.

Итог: r3 — не ревью новой правки, а подтверждение, что дерево, получившее зелёный вердикт в r2, не изменилось, и что сорвавшийся кандидат упал по причине, не относящейся к #632. Разбираю дельту, а не задачу целиком (PROCESS.md §2.10) — она пуста по коду.

Тождество дерева r2 → r3 (проверено блобами, не заявлением)

docs/reviews/CODE-REVIEW-632-r2.md называет SHA материала b64bc932, который в этом дереве не резолвится (ожидаемо — ребейз, тот же паттерн, что уже был у r1→r2). Материал восстановлен не по SHA, а по содержимому:

$ git ls-tree HEAD -- scripts/task-packet.mjs test/task-packet.test.mjs scripts/mutation-registry.mjs
100644 blob f07f56b64e7b92b67b32654481b28e718788de6e  scripts/mutation-registry.mjs
100644 blob c7bfebd2904fca3360b11eacedf9343d768e7915  scripts/task-packet.mjs
100644 blob 15b9c04786b6733c8564c3173f700f374cc5b22d  test/task-packet.test.mjs

scripts/task-packet.mjs (c7bfebd2…) и test/task-packet.test.mjs (15b9c047…) — точное совпадение блобов, названных в r2-документе как материал ревью. Это не эквивалент по содержимому, это тот же самый файл байт в байт: решающая логика и тесты, за которые r2 выдал зелёный вердикт, не изменились ни на символ.

scripts/mutation-registry.mjs в r2-документе назван другим блобом (e48ddb98…, тоже мёртвый), текущий — f07f56b6…. Как и в r1→r2 (там же объяснялось: между ребейзами dev получает чужие правки того же файла от других issue), проверил, что содержимое трёх/четырёх мутантов #632 внутри не пострадало — не по аналогии с прошлым разом, а прогоном на этом SHA:

$ node --test test/task-packet.test.mjs
# tests 14, pass 14, fail 0

$ node scripts/mutation-gate.mjs --check | grep task-packet
ok   task-packet-product-flow-overrides-diff
ok   task-packet-review-docs-not-material
ok   task-packet-s6-s7-alone-not-product-flow
ok   task-packet-trivial-is-product-flow

$ node scripts/mutation-gate.mjs --id=task-packet-trivial-is-product-flow
ok   чистый прогон: node --test test/task-packet.test.mjs
ok   task-packet-trivial-is-product-flow: заявленный тест покраснел на мутанте
поймано 1 из 1

$ git status --porcelain   # после гейтов — пусто

Все четыре мутанта задачи (включая trivial-is-product-flow, закрывший Medium из r1) на месте и красят ровно то, что заявлено — защитное свойство доказано исполнением на текущем SHA, не унаследовано голословно.

Закрытие раунда r2

r2 не оставил находок (High 0, Medium 0) — таблицы «находка → чем закрыта» формально нет. Единственное, что произошло между вердиктом r2 и этим раундом, — событие вне дерева задачи (провал предполётного workflow_sync на промежуточном кандидате 1e866291 из-за расхождения process.yml между main/dev, вызванного другой задачей #634). Проверил, что расхождение устранено и не является скрытой находкой против #632:

$ git fetch origin main dev --quiet   # только чтение ссылок, HEAD/рабочая копия не менялись
$ git diff origin/main origin/dev -- .github/workflows/process.yml
(пусто)

process.yml в main и dev теперь идентичны — зеркало восстановлено, причина красного дispatch снята. git rev-parse HEAD после fetch — та же 14396ed0…, рабочая копия не трогалась (см. правило §2.7/#312 — не уходить с материала ревью; fetch не меняет ни HEAD, ни индекс, только обновляет удалённые ссылки для чтения).

Унаследовано из r2 (и транзитивно из r1)

Дельта по коду между r2 и r3 пуста (см. блобы выше), поэтому решающая логика повторно вручную не переразбиралась — но защитные тесты и мутанты перепрогнаны на этом SHA заново (не просто приняты на слово):

  • AC1 (продуктовая S6-задача с ТЗ/ревью ТЗ сохраняет право класса A) — документ docs/reviews/CODE-REVIEW-632-r1.md, мутант task-packet-product-flow-overrides-diff — ok на этом SHA (выше).
  • AC2 (docs/reviews/** не влияет на классификацию ветки) — тот же документ, мутант task-packet-review-docs-not-material — ok на этом SHA.
  • AC3 (настоящая инфраструктурная задача без ТЗ сохраняет запрет) — тот же документ, мутант task-packet-s6-s7-alone-not-product-flow — ok на этом SHA.
  • AC4 (каждый признак самодостаточен; ## ТЗшка не считается разделом ТЗ) — регэксп (?![\p{L}\p{N}_]) не менялся (блоб task-packet.mjs идентичен r2); тест на эту границу входит в те же 14 зелёных.
  • Medium r1 (trivial-трек не входил в признаки продуктового потока) — закрыт в r1-фиксе, документ docs/reviews/CODE-REVIEW-632-r2.md, мутант task-packet-trivial-is-product-flow — ok на этом SHA (перепрогнан выше, «поймано 1 из 1», не только унаследован).
  • Трейлеры и класс файлов — сверены заново на этом SHA (раздел ниже), не унаследованы.

Находки

Нет. High: 0. Medium: 0.

Дерево, за которое r2 выдал зелёный вердикт, не изменилось (байт в байт по двум решающим файлам); дельта — это только публикация документов ревью и восстановление зеркала process.yml, вызвавшего посторонний красный dispatch. Красный кандидат 1e866291 не является находкой против #632: его причина полностью внешняя (расхождение main/dev от другой задачи), подтверждена логами CI, а не заявлением автора, и уже устранена.

Что проверено и корректно

  • Трейлеры коммитов: 1fbf7704 и 10d32312 несут Issue: #632, User-Visible: no — корректно, продуктового поведения нет (diff не трогает src/**), changelog не требуется.
    $ git log --format='%H %s%n%b' origin/dev..HEAD -- scripts/task-packet.mjs test/task-packet.test.mjs scripts/mutation-registry.mjs
    
    оба коммита несут оба трейлера.
  • Класс файлов: git diff origin/dev...HEAD --name-only — шесть файлов, все docs/**, scripts/**, test/**; ни одного файла класса A. Инфраструктурный трек (ускоренный вход) применён корректно.
  • docs/reviews/INDEX.md свеж: node scripts/reviews-index.mjs --check → «свеж», rc 0; счётчики «Документов: 1021, issue: 361» и строка #632 r2 · 🟢 · 0 · 0 сгенерированы машиной, не вписаны руками — одно число, один источник (генератор), сверено прогоном, а не чтением.
  • Публикация docs/reviews/CODE-REVIEW-632-r2.md дословно соответствует вердикту, вынесенному в комментарии issue 2026-09-24T02:51:34Z (Вердикт: зелёный · заход r2 · … High: 0 · Medium: 0) — сверено gh issue view.
  • Validate зелёный на точном материале ревью:
    $ gh run view 35957716904 --json headSha,conclusion
    headSha 14396ed0b186dc9b883f0b26e460458828dcb58c conclusion success
    
    SHA совпадает с git rev-parse HEAD — дешёвые гейты (tsc, npm test, npm run build+сверка бандла) подтверждены этим прогоном, повторно не гонял.
  • Промежуточный красный 1e866291 разобран логами CI (раздел выше) — его единственная причина, workflow_sync/process.yml, не пересекается с диффом #632 и уже устранена.

Чего не проверял

  • npx tsc --noEmit / npm test (полный) / npm run build со сверкой бандла — не перегонял отдельно: зелёный Validate есть на точном SHA 14396ed0 (ссылка выше), дифф не касается src/**. Точечно код и тесты задачи (node --test test/task-packet.test.mjs, мутанты) перепрогнал сам — см. выше.
  • node scripts/check-docs.mjs — не применим, диф не трогает src/**.
  • npm run golden:verify, браузерные смоки, python -m pytest tests_backend, npm run invariants — не применимы: диф не меняет рендер, геометрию, custom_components/**/*.py не тронут; node scripts/smoke-select.mjs для этого диффа не запускал повторно — вывод «исполняемого frontend-диффа нет» дан в r2 на дельте, которая с тех пор не менялась (блобы идентичны), новых причин для другого ответа нет.
  • Живой node scripts/task-packet.mjs --issue 612 с реальным gh — не запускал (gh в CI-раннере ревьюера доступен только для чтения issue и run-логов через уже настроенный токен, но полный сценарий с реальным API GitHub для входных данных скрипта не воспроизводил); эквивалентно проверено на уровне buildPacket()/тестов в r1/r2, логика сборки входов в этом раунде не менялась вовсе (блобы идентичны).
  • Полный лог упавшего 1e866291 целиком (все job) не читал — только сводку jobs[].conclusion и grep по причине упавшего шага; этого достаточно, чтобы отделить «эта причина не в скоупе #632» от «эта причина маскирует находку», поскольку сам факт и текст ошибки (process.yml в main и dev различаются) не пересекается с файлами #632.

Материал раунда

tree (14396ed0) — рабочая копия
blob c7bfebd2904fca3360b11eacedf9343d768e7915 scripts/task-packet.mjs
blob 15b9c04786b6733c8564c3173f700f374cc5b22d test/task-packet.test.mjs
blob f07f56b64e7b92b67b32654481b28e718788de6e scripts/mutation-registry.mjs
SHA материала ревью: 14396ed0b186dc9b883f0b26e460458828dcb58c
Предыдущий материал (r2, дельта от): b64bc932 (мёртв после ребейза; task-packet.mjs/test — те же блобы, см. выше; мутация-реестр перепроверен исполнением, не по блобу)

Вердикт

Зелёный. Дерево, за которое r2 уже выдал зелёный вердикт (High 0, Medium 0), не изменилось: scripts/task-packet.mjs и test/task-packet.test.mjs байт в байт совпадают с материалом r2; все четыре мутанта задачи и весь тестовый файл перепрогнаны на текущем SHA и зелёные. Красный промежуточный кандидат 1e866291 разобран по логам CI — причина полностью внешняя к #632 (расхождение process.yml между main и dev, вызванное другой задачей #634), устранена, дерево при переподписании не менялось. Трейлеры, класс файлов, свежесть индекса — в порядке. Новых находок нет. High: 0. Medium: 0. Задача готова к пред-релизной очереди.


Материал раунда

  • Ветка: issue/632-task-packet-track, коммит 14396ed0b186 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 0d959028d35b205d556d2bf81ab5e2571128963e
    git log --all --format='%H %T' | grep 0d959028d35b
    
  • Тело issue: 85577dba6802882fd2cb7cc293044cd8318bc67981c0f743e27b5e77294bdece
  • Вердикт конвейера: green · High 0