Files
houseplan-card/docs/reviews/CODE-REVIEW-516-r1.md
T
2026-09-09 21:39:17 +00:00

10 KiB
Raw Blame History

CODE-REVIEW-516-r1

Issue: #516 — merge-candidate: patch-id кандидата включает собственный документ ревью Материал: 8c13b5d16de41db7adfc3ecd00710fb9837ed432 (origin/dev..HEAD — один коммит: ci: merge-candidate compares patch-ids without the review documents) Этап: code · заход r1 · блокирующих циклов израсходовано 0 из 2 Класс изменения: B (гейты/инструменты) — scripts/merge-candidate.mjs, scripts/mutation-gate.mjs, test/merge-candidate.test.mjs. Ни одного файла класса A — задача не трогает продукт.

Скоуп

Симптом (описан в issue #514/#508): merge-candidate.mjs считал patchId(materialBase, material) и patchId(devNow, candidate) по полному диффу, включая docs/reviews/**. Кандидат (вершина ветки) уже несёт собственный CODE-REVIEW-N-rKmd, материал (SHA, прочитанный ревьюером) — нет. Поэтому patch-id расходились всегда, когда dev двигался хотя бы одним паблиш-коммитом документа другой задачи, и зелёный кандидат уходил на повторное ревью без единой содержательной причины.

Правка: realOps.patchId считает git diff --full-index from to -- . ':!docs/reviews' — то же исключение, которое reviewedFresh рядом уже применяет через diffNames. Добавлен мутант merge-rereviews-own-review-doc (снимает pathspec) и тест на настоящем git, воспроизводящий ровно сценарий #514/#508.

Это ТЗ лёгкого трека, живёт в теле issue; отдельного файла в docs/specs/ нет и не должно быть — соответствует.

Как проверялось

Дешёвые гейты на этом SHA уже зелёные (Validate 8c13b5d1, https://github.com/Matysh/houseplan-card/actions/runs/34405162422) — npx tsc --noEmit, npm test, npm run build со сверкой бандла и check-docs не перегонял: diff не трогает src/**, класс A отсутствует, геометрия/layout/толщина стен не затронуты — инварианты модели, golden, смоки и backend-тесты к этой задаче не относятся.

Прогнал точечно, поскольку diff их непосредственно меняет:

  1. node --test test/merge-candidate.test.mjs — 13/13 зелёных, включая новый #516 AC1.
  2. Дисциплина «тест умеет падать» — вручную откатил pathspec в patchId (убрал '.', ':!docs/reviews'), прогнал тот же файл: тест #516 AC1 красный ('rereview' !== 'push'), остальные 12 держатся. Откатил правку файла обратно, git status/git diff чистые.
  3. node scripts/mutation-gate.mjs --check — весь реестр валиден, патчи применяются к текущему коду.
  4. node scripts/mutation-gate.mjs --id=merge-rereviews-own-review-doc — «поймано 1 из 1», совпадает с заявленным в handoff.
  5. node --test test/mutation-gate.test.mjs — 42/42, реестр (guard-файлы, применимость патчей) не сломан добавлением записи.
  6. Прочитал decideMerge/mergeCandidate целиком, сверил, что patchId — единственное затронутое место, а reviewedFresh (уже использующий то же исключение) не тронут и логически согласован с новым patchId — проверено чтением, не исполнением отдельно от юнит-тестов.

Проверка AC

  • AC1 («сдвиг dev только документами ревью не возвращает зелёный кандидат на повторное ревью») — доказан автотестом #516 AC1 на настоящем git (materialBase без документа, кандидат с публикацией CODE-REVIEW-9-r1.md, dev двинут чужим CODE-REVIEW-8-r2.md): action === 'push', комментария с «patch-id» нет, оба документа и код доехали до origin/dev. Тест умеет падать (см. п.2 выше). Выполнен.
  • AC2 («реальное изменение содержимого патча при ребейзе по-прежнему возвращает в S7») — покрыт существующим unit-тестом patch-id изменился при ребейзе — S7-code-review... (test/merge-candidate.test.mjs:130, мокнутые patchId). Этот тест не тронут правкой и остаётся зелёным (входит в 13/13). Логика неравенства patch-id в mergeCandidate не менялась — менялась только сама функция patchId, а не место её использования, поэтому мок на уровне decideMerge/mergeCandidate достаточен: содержательное изменение патча (не в docs/reviews) по-прежнему учитывается pathspec . наравне с остальным деревом. Выполнен.
  • AC3 («мутант пойман штатным раннером», User-Visible: no) — merge-rereviews-own-review-doc зарегистрирован с guard node --test test/merge-candidate.test.mjs (согласовано со стилем соседних мутантов этого файла — той же группы, не требующей пересборки бандла), --id= прогон даёт «поймано 1 из 1». Трейлеры коммита: Issue: #516, User-Visible: no — присутствуют; changelog (docs/CHANGELOG.md, docs/CHANGELOG.ru.md) не тронут, что корректно при User-Visible: no. Выполнен.

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

  • Диапазон правки минимален и точно соответствует пункту ТЗ 1–3, скоуп не расширен (только заявленные 3 файла).
  • patchId(materialBase, material) и patchId(devNow, candidate) теперь считаются симметрично одному и тому же правилу исключения, что и reviewedFresh — нет риска, что одна проверка учитывает docs/reviews, а другая нет.
  • Мутант зарегистрирован в том же стиле (because, guard, patches.find/replace на точную строку кода) — реестр не разъезжается со стилем соседних записей.
  • Пуш кандидата в ветку и последующий Validate по-прежнему выполняются на кандидате, несущем документ ревью — исключение из patch-id не означает исключение файла из самого коммита/пуша, документ едет в dev вместе с кодом (проверено тестом AC1).
  • Единственное число, видимое пользователю, здесь не применимо — задача не выводит величин пользователю (User-Visible: no), правило «одно число — один источник» не задействовано.

Чего не проверял и почему

  • Полный npm test / npx tsc --noEmit / npm run build со сверкой бандла — не перегонял, засчитан зелёный Validate на этом же SHA (8c13b5d1, ссылка выше); прогнал только файлы, которые эта задача непосредственно меняет или из которых прямо следует поведение (merge-candidate.test.mjs, mutation-gate.test.mjs, mutation-gate.mjs --check/--id).
  • node scripts/check-docs.mjs — не запускал: diff не трогает src/**, отпечаток документации не мог устареть от этой правки.
  • npm run invariants, golden, backend pytest, performance-профили, demo/smoke_*.mjs — не относятся: diff не трогает геометрию, рендер, custom_components/**/*.py или чувствительные к перфу пути; в AC ни один смок не назван.
  • Реальное поведение GitHub Actions (gh workflow run, gh run list, --force-with-lease против настоящего GitHub API) — не воспроизводилось, только через realOps на локальном bare-репозитории в тесте (сеть/API не поднимались); это тот же уровень доказательства, что и у остальных тестов файла, включая уже принятые ранее раунды.

Находки

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

Вердикт

Зелёный. AC1–AC3 выполнены и доказаны (автотест + доказанная «умение падать» + прогон мутанта), скоуп не расширен, трейлеры корректны, изменение точечное и симметрично уже принятому решению по reviewedFresh.


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

  • Ветка: issue/516-patch-id-without-review-docs, коммит 8c13b5d16de4 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 26ba415b57cc52fb8c084ed654452b2fce3f0099
    git log --all --format='%H %T' | grep 26ba415b57cc
    
  • Вердикт конвейера: green · High 0