diff --git a/docs/reviews/CODE-REVIEW-330-r4.md b/docs/reviews/CODE-REVIEW-330-r4.md new file mode 100644 index 00000000..cc21895f --- /dev/null +++ b/docs/reviews/CODE-REVIEW-330-r4.md @@ -0,0 +1,185 @@ +# CODE-REVIEW-330-r4 + +Issue: #330 — «Ограничения стыков (#329) блокируют event loop HA и дёргают ресайз на больших планах» +Этап: code (PROCESS.md §2.7) +Заход: r4 · блокирующих циклов израсходовано 3 из 4 (до этого раунда) +Ветка: `issue/330-junction-limits-performance`, HEAD ревью — `d33aa0a7` + +## 0. Разбор по дельте — почему и от какого SHA + +Предыдущий вердикт (code-review r3, 2026-08-28T00:49:49Z — жёлтый, High: 1, +Medium: 0) назван на HEAD `04bb54ae`. Проверено, что этот SHA — прямой предок +текущего HEAD и что ребейза не было: + +``` +$ git merge-base --is-ancestor 04bb54ae HEAD && echo ancestor +ancestor +$ git log --oneline 04bb54ae..HEAD +d33aa0a7 docs: refresh the screenshot pair after the cache-key fix (#330 r3-H1) +90a3313d docs: review document for #330 +``` + +Также проверено, что `dev` не ушёл вперёд за это время: + +``` +$ git fetch origin dev --quiet +$ git log --oneline -1 origin/dev +eff786fa docs: review document for #62 +$ git merge-base --is-ancestor origin/dev HEAD && echo "dev is ancestor of HEAD" +dev is ancestor of HEAD +``` + +Дельта — два коммита: `90a3313d` — публикация документа r3 (класс C, не код), +`d33aa0a7` — точечный фикс единственной находки r3 (H1). Контракт поведения не +менялся, новая подсистема не задета, объём дельты меньше даже r2→r3. Условия +§2.10/§7.2 для полного разбора не выполнены — разбираю по дельте +`git diff 04bb54ae..HEAD`. + +## 1. Скоуп дельты + +`git diff 04bb54ae..HEAD --stat`: + +``` + docs/images/screenshots.json | 22 ++-- + docs/reviews/CODE-REVIEW-330-r3.md | 226 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 237 insertions(+), 11 deletions(-) +``` + +Только r3-H1 (докс-гейт красный на HEAD предыдущего раунда): + +- `docs/images/screenshots.json` — `sourceFingerprint` и все десять + `sourceSha256` заменены с устаревшего `2a5ae6c1…` на актуальный + `dbac4a84d0eb558e66066f5072363977ff4a78c0a032e6f2b9a5d0848cd20f0f` — ровно то + значение, которое r3 уже вычислил независимо (`visualFingerprint()` на + дереве r3, см. документ r3 §3) как «реальное». Ни один `imageSha256` + не изменился ни в одной из десяти сцен — предсказание r3 («UI не менялся, + PNG, вероятно, останутся байт-в-байт те же») подтвердилось буквально. +- `src/**`, `test/**`, `demo/**`, `scripts/**`, `custom_components/**`, + `dist/**` — не тронуты вовсе. Никакого продуктового или тестового кода в + дельте нет. +- `docs/reviews/CODE-REVIEW-330-r3.md` — публикация документа предыдущего + раунда (класс C, инфраструктурный шаг, не предмет код-ревью). + +## 2. Закрытие раунда r3 + +| Находка r3 | Чем закрыта | Где это видно | +|---|---|---| +| H1 (в скоупе) — `node scripts/check-docs.mjs` завершался `exit 1`: записанный `sourceFingerprint` (`2a5ae6c1…`) разошёлся с реальным `visualFingerprint()` дерева (`dbac4a84…`) после того, как `04bb54ae` поменял `src/houseplan-card.ts` без пересчёта скриншот-манифеста | Манифест пересчитан прогоном `npm run build && node demo/docs/capture.mjs` и принят: новый `sourceFingerprint`/все `sourceSha256` равны `dbac4a84…` — ровно значению, которое r3 назвал ожидаемым. `imageSha256` не изменился ни в одной сцене, то есть пересчитан именно отпечаток источника, а не подменены сами PNG | `docs/images/screenshots.json` (диф выше); я прогнал `node scripts/check-docs.mjs` на текущем HEAD лично (не со слов автора) | + +Находка закрыта по существу и подтверждена исполнением, не только чтением +коммита. + +## 3. Как проверялось (дельта, r4) + +Validate на этом SHA (`d33aa0a7`) уже зелёный (см. вводную задачи, ссылка на +прогон), поэтому `tsc`/`npm test`/`npm run build` + сверка бандла не +перегоняю — они не относятся к предмету этой дельты (дельта не трогает +`src/**`/`test/**`) и уже подтверждены на этом самом SHA. + +Единственный релевантный дельте гейт — сам докс-гейт, ради которого сделан +коммит: + +| Гейт | Команда | Результат | +|---|---|---| +| Докс-гейт | `node scripts/check-docs.mjs` | `Documentation checks passed (7 files, 10 external links).`, exit 0 | +| Ручная сверка значения фингерпринта | `git diff 04bb54ae..HEAD -- docs/images/screenshots.json` | все 11 вхождений `sourceFingerprint`/`sourceSha256` заменены на один и тот же новый хеш; все 10 `imageSha256` не изменились | +| Trailers коммитов дельты | `git show 90a3313d -s --format=%B`, `git show d33aa0a7 -s --format=%B` | оба несут `Issue: #330`, `User-Visible: no` — корректно: `90a3313d` публикует документ ревью (класс C, не продукт), `d33aa0a7` пересчитывает служебный отпечаток без изменения видимого результата (PNG идентичны) | +| Рёбейз/уход dev | `git merge-base --is-ancestor 04bb54ae HEAD`, `git fetch origin dev && git merge-base --is-ancestor origin/dev HEAD` | оба — да; условие полного разбора (§2.10, ребейз на ушедший вперёд dev) не выполнено | + +Дельта не трогает геометрию, рендер, стили, слои, публичный контракт, +`custom_components/**` и ни один файл, упомянутый в §5 текста ревью +(инварианты модели, смоки, golden, perf-профили, бэкенд-тесты) — поэтому эти +гейты не перегоняю, наследую решениеr3 не гонять их (см. §5 ниже). + +## 4. Находки + +Находок нет. Единственная находка предыдущего раунда (r3-H1) закрыта точным, +минимальным коммитом, который меняет ровно то, что было названо дефектным +(отпечаток источника), и ничего больше. + +## 5. Унаследовано из r3 (без повторной проверки) + +Дельта r4 не касается ни одной строки продукта, теста или конфигурации — +наследую весь корпус r3 целиком, включая то, что сам r3 унаследовал из r2: + +- **Архитектура срезов §4.1–§4.7** (executor-цепочка, rev-кэш `previous`, + byNode-индекс П3, bucket-решётка П4, §4.6 «v9 как есть», общий проход §4.7) + — признана верной в code-review r2 (`docs/reviews/CODE-REVIEW-330-r2.md`, + HEAD `85636a65`) и подтверждена неизменной в r3 + (`docs/reviews/CODE-REVIEW-330-r3.md`, HEAD `04bb54ae`, §5). Ни r3, ни r4 её + не трогают. +- **AC1 (event loop/executor)** — `pytest -k 330` → `1 passed`, исполнено в + r2, не затронуто с тех пор (`custom_components/**` не в дельте ни r3, ни + r4). +- **AC2/AC3/AC5 (линейный П3/П4, rev-кэш бэкенда, эквивалентность §4.6)** — + паритет-тесты TS↔Python, `pytest tests_backend -q` (423 passed), исполнены + в r2, не затронуты в r3/r4. +- **AC4 (баланс кэша фронта)** — закрыто по существу в r3 (см. таблицу закрытия + r2→r3 в `docs/reviews/CODE-REVIEW-330-r3.md` §2): ключ кэша заменён на + identity документа + `spacePhysicalGeometryFingerprint`, мутант + `junction-limit-baseline-cache-stale` ловится смоком, `mutation-gate.mjs + --id=junction-limit-baseline-cache-stale` зелёный. Дельта r4 не трогает + `src/houseplan-card.ts`, `demo/smoke_junction_limits.mjs`, + `test/junction-limits.test.mjs`, `scripts/mutation-gate.mjs` — код кэша + байт-в-байт тот же, что был подтверждён исполнением в r3. +- **AC7/перф-контракт §5, включение в `validate.yml`** — подтверждено + исполнением в r2 и r3 (`benchmark:junction-limits` → `pass: true`, запас + ≥2.6×). Не в дельте r4. +- **golden:verify** — не гонял, как и в r2/r3: ни один раунд с r1 не касался + рендера/геометрии/стилей/слоёв, r4 тем более (дельта — только + `screenshots.json`, а он не входит в golden-контур). +- **Полная матрица `demo/smoke_*.mjs` и полный `mutation-gate.mjs`** — не + гонял целиком: предрелизные гейты (PROCESS.md §8), не гейт ревью. По дельте + r4 гонять нечего — она не содержит кода, который могла бы затронуть + какая-либо смок-проверка. +- **`pytest tests_backend`** — не гонял; дельта r4 не содержит ни одного + файла `.py`. +- **`npm run invariants -- --config <...>`** — не гонял; дельта не вводит и + не меняет геометрию, `layout`, `marker.space`, `open_spans` или записи + толщины ни в r3, ни в r4. +- **Одно число — один источник** — неприменимо: дельта r4 не вводит и не + меняет ни одной пользователю видимой величины. Более того, она подтверждает + обратное намеренно: `imageSha256` (то, что реально видит пользователь на + скриншотах) не изменился ни на бит — изменился только служебный + `sourceFingerprint`/`sourceSha256`, внутренний отпечаток дерева исходников + для докс-гейта, невидимый конечному пользователю карточки. +- **CHANGELOG** — не требуется ни для `90a3313d` (публикация документа + ревью, класс C, не входит в DoD задачи по видимому поведению), ни для + `d33aa0a7` (`User-Visible: no`, подтверждено фактом: PNG идентичны, + меняется только служебный манифест). + +## 6. Что проверено и корректно (эта дельта) + +- Значение нового `sourceFingerprint` в `docs/images/screenshots.json` + совпадает с тем, которое r3 независимо вычислил как «реальное» + (`dbac4a84…`) на том же дереве до этого коммита — не просто «файл + изменился», а изменился на правильное значение. +- Ни один `imageSha256` не менялся — фикс не подменяет и не портит сами + скриншоты, трогает только служебное поле идентификации источника. +- `node scripts/check-docs.mjs` зелёный на текущем HEAD, прогнан лично. +- Trailers обоих коммитов дельты корректны для их класса изменений. +- Дельта не расширяет и не сужает скоуп задачи: единственная цель коммита — + закрыть ровно ту находку, которая была названа, ничего лишнего не задето. + +## 7. Чего не проверял и почему + +- `npx tsc --noEmit`, `npm test`, `npm run build` + сверка бандла — Validate + зелёный на этом самом SHA (`d33aa0a7`, ссылка в вводной задачи), а дельта + не трогает ни `src/**`, ни `test/**` — перегонять нечего нового. +- `pytest tests_backend`, `golden:verify`, инварианты модели, смоки помимо + докс-гейта, perf-бенчи — дельта r4 не содержит ни одного файла, который + могли бы затронуть эти гейты (только `docs/images/screenshots.json` и + публикация документа ревью); все они наследуются из r2/r3 без повторного + прогона (см. §5). +- Ручное тестирование в браузере — вне цикла ревью по регламенту; предмет + этого раунда — сугубо служебный докс-манифест, для него замена (докс-гейт) + прогнана. + +## 8. Итог + +High: 0. Medium: 0. Единственная находка r3 (H1) закрыта точным, +минимальным, верифицированным коммитом — значение фингерпринта совпало с +независимо вычисленным ожиданием, PNG не изменились, докс-гейт зелёный на +исполнении, не со слов автора. Весь остальной корпус задачи (§4.1–§4.7, +AC1–AC7, AC4-фикс r2→r3) наследуется без повторной проверки — дельта r4 его +не касается ни одной строкой. Зелёный вердикт, бюджет циклов не тратится.