docs: review document for #516

Issue: #516
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-09 21:39:17 +00:00
parent 3ad5d0baea
commit 96bfd94313
+69
View File
@@ -0,0 +1,69 @@
# 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