Issue: #454 User-Visible: no
16 KiB
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— три коммита:9e7ae520docs: публикация документа r3 (сам ревью-файл, не код);d5e11452fix: закрытие M1 (комментарий засчитывается вердиктом только по документу своей задачи), 5 файлов, +174/−27;2a883217chore: пересборка бандла под новый отпечаток исходников — несвязанная поддержка (см. «Вне дельты» ниже), уже с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 (публикуется шагом конвейера).
Материал раунда
- Ветка:
issue/454-review-round-counter, коммит2a883217c156— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
a7f0666a126e40cb40f4ba8eb33b0278f3fe3ec1git log --all --format='%H %T' | grep a7f0666a126e - ТЗ
docs/specs/454-review-round-counter.md, блоб2d236d4f481565d3188ceb2670f97df003783084git log --all --find-object=2d236d4f481565d3188ceb2670f97df003783084 -- docs/specs/454-review-round-counter.md