Files
houseplan-card/docs/reviews/CODE-REVIEW-454-r4.md
T
claude[bot] 5784a0e271
Проверка (CI) / Классификация изменённых файлов (push) Successful in 25s
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Failing after 51s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 53s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 19s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 18s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 7m16s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 9m37s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
docs: review document for #454
Issue: #454
User-Visible: no
2026-09-04 17:45:17 +00:00

112 lines
16 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 — issue #454 · заход r4
- Issue: https://github.com/Matysh/houseplan-card/issues/454
- Материал: `git rev-parse HEAD` = `2a883217c156c349e4cca9bc3bd5a75d85b7b928`
(ветка `issue/454-review-round-counter`).
- Предыдущий раунд: r3, жёлтый, документ `docs/reviews/CODE-REVIEW-454-r3.md`,
материал `4b443d8c` (там же был rev-parse HEAD того раунда).
- Дельта r3→r4: `git diff 4b443d8c..HEAD` — три коммита:
- `9e7ae520` docs: публикация документа r3 (сам ревью-файл, не код);
- `d5e11452` fix: закрытие M1 (комментарий засчитывается вердиктом только по
документу своей задачи), 5 файлов, +174/−27;
- `2a883217` chore: пересборка бандла под новый отпечаток исходников —
несвязанная поддержка (см. «Вне дельты» ниже), уже с `Baseline-Reviewed`.
Ребейза не было, дельта локальна (диапазон `origin/dev...HEAD` не изменился
по существу с r3, кроме этих трёх коммитов) → разбор по дельте (PROCESS.md
§2.9/§2.10), а не заново.
## Закрытие раунда r3
| Находка | Чем закрыта | Где видно |
|---|---|---|
| **M1** (Medium, в скоупе) — резервный счёт по комментариям матчил голую подстроку маркера (`CODE-REVIEW`/`SPEC-REVIEW`) в любой прозе, включая цитаты чужих задач и чужого этапа; на самих данных #454 это дало код-ревью-раунду имя `r3` вместо `r1`, а заявление ТЗ §3 «перерасчёт невозможен по построению» не выполнялось для `attemptComments`/`spentComments` | Правило заменено на два условия: комментарий обязан (а) объявлять вердикт строгой строкой `verdictDeclaration`, (б) называть документ **этой** задачи и **этого** этапа — `<MARKER>-<NUM>` вместо голого `<MARKER>`. Формулировка §3 ТЗ смягчена до факта («удвоение невозможно, завышение одной из компонент — возможно»). Добавлен `::warning::` при расхождении `attemptComments`/`attemptFiles`, привязка к номеру задачи и уточнение гарантии — все три направления, предложенные в r3, взяты одновременно | `scripts/review-doc-guard.mjs:452-486` (`stageVerdictComments`, `commentCounters`), коммит `d5e11452`; `.github/workflows/process.yml:97-190` (счёт по комментариям вынесен из inline-jq в модуль, `--comments`/`--spent-list`); `docs/specs/454-review-round-counter.md` §3 и таблица AC5; тест `вердикт этапа опознаётся по документу ЭТОЙ задачи (#454 AC5, #89)` и `чужой номер задачи не засчитывается своим (#454 AC5)`, `test/review-doc-guard.test.mjs:456-472`; мутант `review-comment-source-ignores-issue-number` (`scripts/mutation-gate.mjs:2442-2455`) |
**Перепроверено исполнением, не со слов автора.** Собрал реальные данные #454 (`gh issue view 454 --json comments`, файл `docs/reviews/CODE-REVIEW-454-r3.md` — единственный опубликованный код-ревью-документ на ветке) и прогнал новый CLI `node scripts/review-doc-guard.mjs --counters --marker=CODE-REVIEW --num=454 ...` буквально так, как его вызывает `process.yml`:
```
::notice::раунды по файлам 3; заход: файлы 4, комментарии 2; циклы: файлы 0, комментарии 1
attempt=4
spent=1
```
`attemptComments=2` (было 3 на живом логе `guard` r3-прогона) — оба посторонних совпадения (зелёный SPEC-REVIEW r2-вердикт и хендофф-комментарий «Реализация готова», оба цитировавшие чужие `CODE-REVIEW-*` документы в прозе) больше не матчат `own`-фильтр, потому что ни один не содержит буквальную подстроку `CODE-REVIEW-454`. Единственный засчитанный — сам r3-вердикт (жёлтый), `spentComments=1`. `attemptFiles=4` (раунд 3 существует → следующий r4), `spentFiles=0` — документ `CODE-REVIEW-454-r3.md` не объявляет вердикт машиночитаемой строкой внутри себя (раздел «## Вердикт» там — проза без строки `Вердикт: жёлтый · …`, это отдельный, унаследованный из ТЗ §2 класс «документ есть, строка `Вердикт:` в нём нет» — не новый дефект дельты и не относится к M1). `max(4,2)=4`, `max(0,1)=1` — совпадает с «заход r4 · циклов 1/4» из шапки задачи. M1 закрыта.
## Унаследовано из r3
Без повторной проверки принимаю (документ `docs/reviews/CODE-REVIEW-454-r3.md`, материал `4b443d8c`):
- AC1 (`attempt` = max(номер)+1), AC2/AC2b (фикстуры #449 реальная и реконструированная), AC3 (имя файла не повторяется), AC4 (зелёный цикл не тратит), AC6 (отказ публикации не занижает счёт), AC7 (нет ветки/мусор на входе не роняет guard), AC9 (логика в тестируемом модуле, не в inline-shell) — дельта их не касается, файлы/тесты, доказывающие их, не менялись между `4b443d8c` и `HEAD` (проверено `git diff 4b443d8c..HEAD -- test/review-doc-guard.test.mjs` — новые тесты только про AC5/комментарии).
- AC8 (`process.yml` идентичен в `main` и `dev`) — план зеркалирования после мержа обоснован в r3 и не изменился.
- Класс изменения B, `User-Visible: no` на всех коммитах — трейлеры проверены отдельно ниже для новых коммитов дельты, старые (`8d826320`, `dc76c5b2`, `4b443d8c`) не перепроверял.
- Наблюдение r3 (не находка): `docs/specs/README.md` — строка `#454` вставлена не по возрастанию номера. Косметика, не блокирует, не повторяю как находку.
## Вне дельты, но заслуживает упоминания — `2a883217`
Коммит `2a883217` (пересборка бандла) не относится к предмету #454 (счёт раундов ревью), это независимая починка красного `dev`, найденная и исправленная автором по собственной инициативе между r3 и r4 (дефект: `package.json`, изменённый в #455, не был прогнан через `bundle:sync`, фингерпринт разошёлся). Проверил сам, а не поверил описанию:
- `git show 2a883217 -M` для `houseplan-card-*.js` (крупнейший переименованный чанк, 96 изменённых строк из 5676): все 44 изменившиеся пары строк дают **одинаковую длину** старой и новой стороны (проверено построчно, включая гигантские минифицированные строки 20037/74688/193139 байт) — сильный признак того, что правки это подстановка фингерпринта и имён чанков, а не смена логики; я не нашёл ни одной пары разной длины.
- Трейлеры коммита: `User-Visible: no`, `Issue: #454`, `Baseline-Reviewed: .../actions/runs/33895243347` (ссылка на упавший прогон, который и обнаружил расхождение — `process-gate` требует `Release` либо `Baseline-Reviewed` для коммита только класса D, оба варианта допустимы по `scripts/process-gate.mjs:246-249`, содержательной проверки «зелёности» самой ссылки правило не делает).
- Дифф не трогает `src/**`, `custom_components/**/*.py` — не App-код.
Не блокирует и не относится к AC #454; упоминаю для полноты, не как находку.
## Как проверялось — гейты
**Дешёвые гейты уже подтверждены Validate на `2a883217`** (green, run 33900588440) — `tsc`, `npm test`, `npm run build` со сверкой бандла перегонять не обязан, но перегнал сам для дельты (код изменился с r3):
| Гейт | Команда | Результат |
|---|---|---|
| Typecheck | `npx tsc --noEmit` | чисто, без вывода |
| Unit-тесты | `npm test` | 1940 pass / 0 fail / 1 skip |
| Mutation gate | `node scripts/mutation-gate.mjs --check` | exit 0; все 4 `review-*` мутанта, включая новый `review-comment-source-ignores-issue-number`, пойманы (`ok`) |
| check-docs | `node scripts/check-docs.mjs` | passed (7 files, 12 links) — не обязателен (`src/**` не тронут), прогнан для полноты |
| Реальный прогон CLI на живых данных #454 | `node scripts/review-doc-guard.mjs --counters --marker=CODE-REVIEW --num=454 --comments=<gh issue view --json comments> --docs=<CODE-REVIEW-454-r3.md>` | `attempt=4, spent=1` — совпадает с ожидаемым и с шапкой задачи |
Не гонял: `npm run golden:verify`, `demo/smoke_*.mjs`, `python -m pytest tests_backend`, performance-профили, `npm run invariants` — дельта не трогает `src/**`, рендер, геометрию, `custom_components/**/*.py` ни бэкенд. `smoke-select.mjs` не запускал по той же причине (диапазон вне поверхностей демо-стенда).
## AC — таблица доказательств (только задетые дельтой)
| AC | Критерий | Доказано | Комментарий |
|---|---|---|---|
| AC5 | Вердикт чужого этапа/чужой задачи не влияет на счёт (#89) — по имени файла **и** по прозе комментария | unit + мутант, перепроверено исполнением на реальных данных #454 | `stageVerdictComments`/`commentCounters` (`review-doc-guard.mjs:452-486`), тесты `test/review-doc-guard.test.mjs:456-472`, мутант `review-comment-source-ignores-issue-number`. Живой прогон подтвердил: `attemptComments` упал с 3 (r3) до 2 (r4) — оба ложных совпадения исчезли |
| AC9 | Логика в тестируемом модуле, не в inline-shell | unit, чтением | тест «guard считает раунды скриптом, а не inline-shell» по-прежнему проходит после смены аргументов `--comment-attempt/--comment-spent` → `--comments/--spent-list` |
Остальные AC не задеты дельтой — см. «Унаследовано из r3».
## Что проверено и корректно
- M1 закрыта: причина (голая подстрока маркера) устранена, решение подтверждено и юнитом, и мутантом, и независимым прогоном на реальных данных задачи, а не только словами автора.
- Регекс `own = new RegExp(\`${marker}-${num}(?![0-9])\`)` устойчив к коллизиям номеров-подстрок (проверил вручную: `num=454` не матчит `CODE-REVIEW-4540-...`, не матчит `CODE-REVIEW-1454-...`; `num=45` не матчит `CODE-REVIEW-454-...` — во всех случаях out благодаря негативному lookahead и жёсткой смежности марker-num).
- CLI-обвязка (`--comments`, `--spent-list`) согласована с форматом `gh issue view --json comments` — проверил `gh issue view 454 --json comments` вживую: ключ `comments`, элементы несут `.body`/`.url`, ровно то, что читает `commentCounters`/`payload.comments || payload`.
- `spent_list` теперь строится тем же кодом, что и число (не рассинхронизируется).
- Трейлеры коммитов `d5e11452`, `9e7ae520`, `2a883217`: `Issue: #454` есть у всех, `User-Visible: no` корректно для класса B/D, changelog не требуется.
- `process.yml` идентичен между `HEAD` и веткой на момент проверки; расхождение с `main` ожидаемо и объяснено (зеркалирование после мержа).
## Чего не проверял
- `golden:verify`, `smoke_*.mjs`, `pytest tests_backend`, performance, `npm run invariants` — diff не касается рендера/геометрии/бэкенда/perf.
- Реальный прогон изменённого `guard`-джоба целиком на GitHub Actions (сам workflow ещё не в `main`/`dev`) — логика проверена юнитами, мутантом и прямым вызовом CLI на данных, снятых с живого API; часть про `git ls-remote`/постраничный лимит `contents` не менялась в этой дельте и не перепроверялась повторно (наследую из r3).
- Побайтовое сравнение бандла `2a883217` вне одного (крупнейшего) чанка `houseplan-card-*.js` — остальные переименованные чанки различаются 2 строками (импорт по новому имени), не разбирал их так же подробно; риск оценил как низкий (переименование = констант-строка, тот же паттерн).
## Вердикт
Один Medium закрыт без нового Medium/High. Дельта локальна, гейты зелёные (сам прогнал + Validate на `HEAD` уже зелёный), AC5 передоказан на реальных данных задачи.
Документ: `docs/reviews/CODE-REVIEW-454-r4.md` (публикуется шагом конвейера).
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/454-review-round-counter`, коммит `2a883217c156` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `a7f0666a126e40cb40f4ba8eb33b0278f3fe3ec1`
```
git log --all --format='%H %T' | grep a7f0666a126e
```
- ТЗ `docs/specs/454-review-round-counter.md`, блоб `2d236d4f481565d3188ceb2670f97df003783084`
```
git log --all --find-object=2d236d4f481565d3188ceb2670f97df003783084 -- docs/specs/454-review-round-counter.md
```