From 14e56c03993ae35a5c47817321161e55906d7a6c Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:53:54 +0000 Subject: [PATCH] docs: review document for #641 Issue: #641 User-Visible: no --- docs/reviews/CODE-REVIEW-641-r2.md | 80 ++++++++++++++++++++++++++++++ docs/reviews/INDEX.md | 3 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/CODE-REVIEW-641-r2.md diff --git a/docs/reviews/CODE-REVIEW-641-r2.md b/docs/reviews/CODE-REVIEW-641-r2.md new file mode 100644 index 00000000..f9dc6288 --- /dev/null +++ b/docs/reviews/CODE-REVIEW-641-r2.md @@ -0,0 +1,80 @@ +# Код-ревью #641 · заход r2 + +Вердикт: **зелёный** · заход r2 · блокирующих циклов 0/4 · High: 0 · Medium: 0 + +Материал: `2b63dd854878d2f24850b7ba4fe1c817e5ae735e` (рабочая копия уже на нём). Предыдущий раунд (r1) вынес вердикт на `ee6ca4f3c9a8099e066b5d94c9a6815cd3f0c6e7`, документ — `docs/reviews/CODE-REVIEW-641-r1.md` (закоммичен в этой же ветке в `bf3e8a9b`). + +## Скоуп раунда + +Задача инфраструктурная (WSL-аттестация локальной golden-съёмки), `src/**` и `custom_components/**/*.py` диффом не тронуты ни в r1, ни в r2. + +Дельта r2 = `git diff ee6ca4f3..2b63dd85`: + +``` +docs/reviews/CODE-REVIEW-641-r1.md | 251 +++++++++++++++++++++++++++ +docs/reviews/INDEX.md | 3 +- +test/golden-capture-provenance.test.mjs | 19 ++- +``` + +Два первых файла — публикация документа предыдущего раунда (процессный артефакт, не предмет разбора). Единственная содержательная правка — `test/golden-capture-provenance.test.mjs`: новый параметр `captureEnv` в фикстуре плюс один новый тест `#641: локальная Linux-съёмка без CI и WSL-аттестации отвергается до записи`. Продуктовый код (`demo/golden/accept.mjs`, `scripts/golden-wsl-artifact.mjs`, `scripts/capture-environment.mjs` и т.д.) в этом раунде не менялся вообще — значит все выводы r1 по нему, кроме закрываемой находки, наследуются без риска регрессии от самой правки. + +## Закрытие раунда r1 + +| находка r1 | чем закрыта | где это видно | +|---|---|---| +| Medium (в скоупе): guard в `demo/golden/accept.mjs:86-103` — единственный механизм, не дающий обычной Linux-съёмке (`golden:capture`, без CI-провенанса и без `wsl-attestation.json`) выдать себя за отрецензированный источник — не был покрыт ни одним тестом, гоняющим настоящий `accept.mjs` именно в этом сценарии; все фикстуры `test/golden-capture-provenance.test.mjs` подставляли `GITHUB_RUN_ID` по умолчанию | Добавлен тест `#641: локальная Linux-съёмка без CI и WSL-аттестации отвергается до записи` (`test/golden-capture-provenance.test.mjs:130-142`), плюс параметр `captureEnv` в `fixture()` (`test/golden-capture-provenance.test.mjs:30-31, 73`), позволяющий собрать отчёт без `GITHUB_RUN_ID`/`GITHUB_SHA` | Тест строит артефакт с `captureEnv: {}` (нет CI-переменных → `provenance.ci` ложно) и без `wsl-attestation.json` (явно проверено `assert.equal(existsSync(...), false, ...)`), запускает настоящий `demo/golden/accept.mjs` через `execFileSync` (не мок) и ожидает отказ с текстом `/локальная Linux-съёмка не аттестована/` до записи `baselines-index.json` (`assert.deepEqual(index, before, ...)`) | + +Проверено не по заявлению автора, а инструментально: я прогнал `node --test test/golden-capture-provenance.test.mjs` на этом SHA — 8/8 зелёные, включая новый тест. Затем временно (в рабочей копии, не в коммите) заменил условие guard в `demo/golden/accept.mjs` (строки 100-102) на `if (false) {`, запустил только новый тест — он **упал** с тем самым сообщением о непойманном отказе (`'приёмка обязана была отказать, а прошла'`), после чего восстановил файл из бэкапа и подтвердил чистое дерево (`git status --porcelain` пусто). Это прямое доказательство: тест реально исполняет guard и умеет падать при его поломке — ровно то, чего требовала находка r1. + +Других находок в r1 не было (0 High, финального Medium — 1, он закрыт выше). + +## Унаследовано из r1 + +Без повторной проверки в r2 принято (документ `docs/reviews/CODE-REVIEW-641-r1.md`, SHA `ee6ca4f3c9a8099e066b5d94c9a6815cd3f0c6e7`), так как продуктовый код этих механизмов в дельте r2 не менялся: + +- fail-closed предусловия WSL-съёмки: dirty tree, detached HEAD, расхождение с `origin/`, неподдерживаемая ФС; +- самохеширующийся манифест/паспорт аттестации с независимой реконструкцией на приёмке; +- эксклюзивный trailer `Baseline-Reviewed-Local`, проверка формата и сверка с индексом baseline; +- участие WSL-аттестации в составном CI-proof evidence; +- покрытие AC модульными тестами (dirty tree, stale fingerprint, несовпадающий toolchain, неполная матрица, unexpected diff, подмена SHA) — кроме единственного пробела, закрытого в этом раунде; +- обновления `AGENTS.md`, `PROCESS.md`, документации golden/WSL и `docs/STATUS.md`; +- соответствие AC ТЗ #641 в целом (все пункты чек-листа issue, кроме проверки самого guard, r1 разобрал по коду и тестам). + +## Что проверено в r2 (сверх наследования) + +- **Диапазон дельты.** `git log --oneline ee6ca4f3..2b63dd85` и `git diff --stat` — подтверждено: только тестовый файл + публикация документа r1 + индекс. Продуктовый код не тронут → полный повторный разбор AC не требуется (правка локальна, поведение не меняет, новую подсистему не задевает). +- **Реальный запуск нового теста и его фикстуры**, включая целевой mutation-check (guard отключён → тест падает; guard включён → тест зелёный), см. выше. +- **Полный прогон файла тестов** — `node --test test/golden-capture-provenance.test.mjs` — 8/8, 0 fail, 0 skip (среда — Linux, целевой guard не skip-ится). +- **Точный SHA Validate.** `gh run view` для обоих упомянутых прогонов: + - `35897181655` (из комментария автора) — `headSha: 2b63dd854878d2f24850b7ba4fe1c817e5ae735e`, `conclusion: success`; + - `35897805104` (из инструкции задания) — тот же `headSha`, `conclusion: success`, `event: workflow_dispatch`. + Job-лист второго прогона: `Фронтенд: типы, юниты, мутанты, синхрон бандла` — success (включает изменённый тестовый файл), `Мутанты по диффу` (все 6 шардов) — success, `Предполёт: документация, провенанс, процесс` — success; `golden`, `смоки` (3 шарда), `перф`, `Бэкенд`, `Геометрия`, `HACS`, `Hassfest` — закономерно `skipped`, т.к. `src/**`, baselines, geometry и Python диффом не задеты. +- **`node scripts/smoke-select.mjs --base ee6ca4f3 --head 2b63dd85`** → «Исполняемого frontend-диффа нет (`src/**/*.ts` не тронут). Browser-smoke этим диффом не выбираются — выбирать нечего». Смоки не прогонялись, и это корректно: выбирать нечего, а не «пропущено». +- **Трейлеры.** `2b63dd85`: `Issue: #641`, `User-Visible: no` — верно, изменение только тестового кода, для пользователя карточки невидимо, changelog не требуется. +- **Чистота рабочей копии после ревью** (в т.ч. после временной мутации для проверки теста) — `git status --porcelain` пуст, `git diff` пуст. + +## Что не проверял и почему + +- `npx tsc --noEmit`, `npm test` (полный набор), `npm run build` со сверкой трёх копий бандла, `node scripts/check-docs.mjs` — не перегонял: дешёвые гейты уже подтверждены на этом точном SHA (`35897805104`, `success`), а `src/**` дельтой r2 не тронут (`check-docs` не устареет). Свежесть подтверждена напрямую через `gh run view`, а не по слову автора. +- `npm run invariants` (инварианты модели) — не требовался: дельта не касается геометрии, `layout`, толщины стен, `open_spans`. +- `python -m pytest tests_backend -q` — не требовался: `custom_components/**/*.py` не тронут (и в r1, и в r2). +- `npm run golden:verify`, браузерные смоки любых шардов, performance-профиль — не требовались: `smoke-select.mjs` прямо подтвердил отсутствие исполняемого фронтенд-диффа; видимый рендер/геометрия/стили не менялись. +- Повторная ручная проверка WSL-паспорта, `foreignCaptureRefusal`, композитного CI-proof и остальных механизмов r1 — не повторял целиком: продуктовый код этих модулей в дельте r2 не менялся (см. «Унаследовано из r1»); риск регрессии от самой правки r2 (только тест) на них не распространяется. + +## Итог + +Единственная Medium-находка r1 закрыта точным, целевым тестом, который инструментально подтверждён как реально исполняющий боевой `accept.mjs` и как способный упасть при поломке guard'а. Дельта r2 локальна (тестовый файл + публикация документа), продуктовый код не тронут, точный SHA зелёный в CI. Новых находок не выявлено. + +--- + + + +## Материал раунда + +- Ветка: `issue/641-wsl-golden-attestation`, коммит `2b63dd854878` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `ad3826fd48aaf89c6ab66487b18ce9bc590e6180` + ``` + git log --all --format='%H %T' | grep ad3826fd48aa + ``` +- Тело issue: `1a1d7660a1cab43873f74127511d21fecf30767f7af959c6ecf820e6efbd2a51` +- Вердикт конвейера: `green` · High 0 diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index b4bb4a85..1ae85383 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,10 +1,11 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1006, issue: 350. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1007, issue: 350. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| | #641 | [CODE-REVIEW-641-r1.md](CODE-REVIEW-641-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | нет исполняемого автотеста на ключевой guard в accept.mjs | `accept.mjs` `demo/golden/accept.mjs` `test/golden-wsl-artifact.test.mjs` `wsl-attestation.json` `test/golden-capture-provenance.test.mjs` `scripts/mutation-registry.mjs` `scripts/golden-wsl-artifact.mjs` | +| #641 | [CODE-REVIEW-641-r2.md](CODE-REVIEW-641-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — | | #640 | [SPEC-REVIEW-640-r1.md](SPEC-REVIEW-640-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | AC3 называет browser-smoke «unit»-тестом | `demo/smoke_furniture_lazy_art.mjs` | | #640 | [CODE-REVIEW-640-r1.md](CODE-REVIEW-640-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #639 | [CODE-REVIEW-639-r1.md](CODE-REVIEW-639-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | Новая запись smoke-links.mjs для smoke_space_settings_form.mjs описывает проверку, кото… | `smoke-links.mjs` `smoke_space_settings_form.mjs` `scripts/smoke-links.mjs` `demo/smoke_space_settings_form.mjs` `src/editors/space-form.ts` `form-kit.ts` |