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

70 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/516-patch-id-without-review-docs`, коммит `8c13b5d16de4` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `26ba415b57cc52fb8c084ed654452b2fce3f0099`
```
git log --all --format='%H %T' | grep 26ba415b57cc
```
- Вердикт конвейера: `green` · High 0