diff --git a/docs/reviews/CODE-REVIEW-701-r1.md b/docs/reviews/CODE-REVIEW-701-r1.md new file mode 100644 index 00000000..9927bfd1 --- /dev/null +++ b/docs/reviews/CODE-REVIEW-701-r1.md @@ -0,0 +1,138 @@ +# CODE-REVIEW-701-r1 + +- Issue: #701 «Канон: 26 расхождений документов между собой и с кодом, дубли правил, уроки одного случая» +- Трек: `show` · заход r1 · блокирующих циклов израсходовано 0 из 2 +- Материал: `git log --oneline origin/dev..HEAD` → один коммит `8dcc1cad4edeed369f751d6b9fe96b798b4061e4` + поверх `origin/dev` @ `224d0106`; `git diff origin/dev...HEAD` — 21 файл, + 232 вставки / 111 удалений +- Класс изменений: B (scripts, tests, `.github/workflows/_process.yml`) + C + (docs) — нет файлов класса A; задача инфраструктурная (PROCESS.md §1), + ТЗ не пишет — соответствует правилу +- Validate на этом SHA зелёный: https://github.com/Matysh/houseplan-card/actions/runs/36486646199 + +## Скоуп + +Issue фиксирует 26 расхождений (D1–D26) между `PROCESS.md`, ролевыми +конспектами (`AUTHOR.md`, `REVIEWER.md`), `AGENTS.md`, `TESTING.md`, +`CONTRIBUTING.md`, `docs/DEVELOPMENT.md`, `docs/STATUS.md`, `docs/LESSONS.md`, +`docs/specs/README.md`, промптом `_process.yml` и исполняемым кодом +(`process-gate.mjs`, `validate-commit-provenance.mjs`, `mutation-registry.mjs`, +`entry-cost.mjs`, `gate-small.mjs`). Автор решает каждое расхождение «в пользу +кода, если код — действующее решение владельца, иначе чинится код» и добавляет +одно материальное поведенческое изменение: **документационный коммит (только +файлы класса C) больше не требует трейлеров `Issue:`/`User-Visible:`** — вынесен +общий модуль `scripts/change-classes.mjs`. + +Работа обслуживает J6 «Keep the plan true as the home evolves» лишь косвенно — +это сам процесс поддержки продукта в согласованном состоянии, разрешено §1 +AGENTS.md как «infrastructure» и подтверждено меткой `process` + `docs`. + +## Как проверялось + +Прочитан весь `git diff origin/dev...HEAD` (все 21 файл, все 15 hunks в +`PROCESS.md`), сопоставлен построчно с таблицей решений D1–D26 из комментария +автора. Ниже — таблица только по пунктам, где проверка потребовала выйти за +простое чтение диффа (код + тест + мутант); остальные D-пункты — точечные +правки текста, сверенные визуально построчно с диффом и не приведённые +отдельной строкой, чтобы не раздувать документ. + +| D | Что проверено | Результат | +|---|---|---| +| D1 | `scripts/change-classes.mjs` — новый общий модуль; `validate-commit-provenance.mjs` импортирует `classify`, добавляет `isDocsOnlyCommit`; `process-gate.mjs` импортирует `classify` вместо локальной копии | код идентичен по регэкспам исходной копии из `process-gate.mjs` (diff — чистый вырез/вставка), порядок D→A→B→C сохранён | +| D1 (тест) | `isDocsOnlyCommit` доказана | `node --test test/commit-provenance.test.mjs` — зелёный; вручную применены оба мутанта реестра (`docs-only-commit-needs-trailers-again`, `docs-only-exemption-leaks-to-code`) — тест краснеет на обоих, рабочая копия восстановлена (`git status --porcelain` пуст) | +| D1 (хук) | `.githooks/commit-msg` зовёт `--staged`, значит `changedFiles` — реальный staged-список, а не пустой список из документного примера | прочитан `.githooks/commit-msg:13-14` | +| D1 (реестр) | `legacy/**` классифицируется как C с комментарием «только Markdown» | `find legacy -type f \| grep -v '\.md$'` → 0 файлов, подтверждено | +| D2 | `REVIEW_DOC_LIMIT = 6` в `process-gate.mjs` не менялся, только текст PROCESS.md подгонян под код | `grep -n REVIEW_DOC_LIMIT scripts/process-gate.mjs` совпадает с новой формулировкой «шесть документов одного вида» | +| D14 | Порядок чтения ревьюера в `_process.yml` (SCOPE→AGENTS→REVIEWER) совпадает с `ROUTES.reviewer.files` в `entry-cost.mjs` | тест `test/entry-cost.test.mjs` «#701 D14» зелёный; `node scripts/entry-cost.mjs` — совпадение подтверждено | +| Слова входа | Автор заявляет 5345→4703 (в тексте issue) / 5171→4703 (комментарий); коммит называет 5345→4703 | `node scripts/entry-cost.mjs` на HEAD даёт 4706 слов (расхождение в 3 слова — рероллы markdown/пробелы, не расхождение по существу) | +| Гейты | Юниты, задетые диффом | `node --test test/commit-provenance.test.mjs test/entry-cost.test.mjs test/process-digests.test.mjs test/pre-push-gate.test.mjs` — все зелёные (19+13+1+12 тестов) | +| Смоки | Есть ли исполняемый frontend-дифф | `node scripts/smoke-select.mjs --base origin/dev --head HEAD` → «Исполняемого frontend-диффа нет … Browser-smoke этим диффом не выбираются — выбирать нечего» — прямой и однозначный ответ инструмента, ни один смок не пропущен | +| Трейлеры | `Issue:`/`User-Visible:` коммита | `git show -s --format=full HEAD` — `Issue: #701`, `User-Visible: no`; коммит сам содержит файлы класса B (scripts/tests/workflow), поэтому по новому правилу трейлеры обязательны и присутствуют — код применён к себе корректно | + +## Что не проверял (и почему это ничего не пропускает) + +- `npx tsc --noEmit`, `npm test` (полный), `npm run build` + сверка бандла — + не перегонял: Validate на этом же SHA `8dcc1cad` зелёный (ссылка выше), + бюджет раунда потрачен на чтение кода, как разрешает промпт ревью. +- `npm run golden:verify` — не запускался: метки `ci:golden` на issue нет, + дифф не касается `demo/golden/**` и рендера. +- `python -m pytest tests_backend -q` — не запускался: дифф не касается + `custom_components/**/*.py`. +- `npm run invariants -- --config ` — не запускался: дифф не меняет + геометрию модели ни ссылки на неё. +- Performance-профили — не запускались: не названы в AC/issue. +- Полный `npm run inventory` / полный прогон `mutation-gate.yml` (все шесты + шардов) — не запускался; автор заявляет локальный прогон диф-мутантов + «184 из 184» на `show`, где диф-мутанты не обязательны (REVIEWER.md, «Трек + show»): проверены точечно только два новых мутанта, относящихся к диффу + (см. таблицу выше), остальные 182 не переисполнялись — трек `show` этого не + требует. +- Не перечитывал все 26 точечных текстовых правок построчно вслух в этом + документе — свёл к таблице выше плюс визуальному сопоставлению с полным + диффом (`git diff origin/dev...HEAD -- PROCESS.md` и остальные файлы, + прочитаны целиком инструментом чтения, не по фрагментам). + +## Находки + +Нет находок уровня High или Medium. Ниже — один пункт уровня Low, снятый без +правки. + +- **Low, снят.** Число слов входа автора в коммите/issue (5345/5171→4703) и на + измеренном HEAD (4706) расходятся на 2–3 слова. Причина, скорее всего, — + разница момента замера (до/после финальной правки одного предложения) или + особенность подсчёта `wc -w`-подобной функции на переносах строк; описанный + порядок величины (экономия ~640–700 слов, цель 3000 не достигнута, остаток + назван) не меняется, инструмент (`node scripts/entry-cost.mjs`) сам + показывает актуальное число при каждом запуске, а не текст документа — + учебная находка, не поведенческая. Снимаю без возврата автору. + +## Что проверено и корректно + +- Общий модуль классов (`change-classes.mjs`) устраняет дублирование логики + между `process-gate.mjs` и `validate-commit-provenance.mjs`, поведение не + изменилось для не-docs-only коммитов (тесты на классах A/B/D в + `test/commit-provenance.test.mjs` не тронуты и зелёные). +- Новое освобождение docs-only коммитов от трейлеров реализовано корректно: + пустой список файлов не считается docs-only («судить нечем»), любой файл вне + класса C возвращает коммит под старое правило, указанный трейлер всё равно + проверяется на валидность (тест `docs: typo\n\nIssue: #x` всё ещё краснеет). + Оба защитных инварианта доказаны мутантами и я лично воспроизвёл оба падения. +- Изменение маршрута автора (`docs/STATUS.md` убран из обязательного входа) + синхронно отражено в `entry-cost.mjs`, `AGENTS.md` и тексте PROCESS.md — + один источник, три места ссылаются, а не повторяют число. +- Переупорядочение маршрута ревьюера в промпте `_process.yml` (SCOPE→AGENTS→ + REVIEWER) сопровождается новым тестом, который сверяет промпт и + `entry-cost.mjs` исполнением, а не на слово доверия. +- Автор честно перечислил недоделанное (п.4 «уроки → чек-листы подсистем» и + остаток до 3000 слов) как отдельное issue-предложение, а не спрятал в тексте. +- Одно число, видимое дважды в этом диффе (порог `REVIEW_DOC_LIMIT`), имеет + один источник — константу в `process-gate.mjs`; текст PROCESS.md её называет, + не дублирует. +- Риск, названный самим автором (файл, ошибочно отнесённый к классу C, + пройдёт без трейлеров), — не находка ревью: он не увеличился этим диффом + (тот же риск существовал и раньше в неявном виде, для `process-gate.mjs`), + а сведение классов в один модуль его уменьшает, а не создаёт. + +## Раздел «Унаследовано» — не применяется + +Это первый заход (r1) по этому issue; предыдущего раунда и материала нет. + +## Вердикт + +Зелёный. AC (D1–D26 плюс материальное изменение трейлеров) доказаны кодом, +тестами и исполнением мутантов там, где они заявлены; гейты, применимые к +этому диффу, зелёные или обоснованно не запускались; High/Medium находок нет. + +--- + + + +## Материал раунда + +- Ветка: `issue/701-canon-consistency`, коммит `8dcc1cad4ede` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `18f1bb93547b43c41d19aecdcecb67e0fe35f3c2` + ``` + git log --all --format='%H %T' | grep 18f1bb93547b + ``` +- Тело issue: `592acae7c08ffffa64b312987ca7cff1e28155412a2c6531cb3e4eab0877eedf` +- Вердикт конвейера: `green` · High 0