Files
houseplan-card/docs/reviews/CODE-REVIEW-276-r3.md
T
claude[bot] 29a0305558
Validate / process-workflow-sync (push) Successful in 34s
Validate / docs (push) Failing after 36s
Validate / process-gate (push) Failing after 41s
Validate / provenance (push) Successful in 42s
Validate / changes (push) Successful in 22s
Validate / hacs (push) Failing after 13s
Validate / reuse (push) Successful in 40s
Validate / hassfest (push) Failing after 17s
Validate / frontend (push) Successful in 6m56s
Validate / backend (push) Failing after 16m13s
Validate / smoke (1) (push) Failing after 24m11s
Validate / smoke (2) (push) Failing after 25m33s
Validate / smoke (3) (push) Failing after 16m12s
Validate / smoke_done (push) Skipped
Validate / golden (push) Failing after 18m2s
Validate / performance_smoke (push) Failing after 33m56s
docs: review document for #276
Issue: #276
User-Visible: no
2026-08-24 03:29:16 +00:00

197 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-276-r3
- **Issue:** https://github.com/Matysh/houseplan-card/issues/276
- **Ветка:** `issue/276-reconcile-coincident-partition`
- **Проверенный HEAD:** `ff2f2063cf5b1f6292a6a4369274d0b59ea228dc` (совпадает с заявленным в хендоффе автора)
- **Предыдущий раунд:** `docs/reviews/CODE-REVIEW-276-r2.md`, HEAD `82fe98bcd3fb76833c27dd888d265fc15583a43b`, вердикт жёлтый (High: 0, Medium: 1 — M1-r2)
- **Заход:** r3 (код-ревью) · блокирующих циклов до этого раунда: 2/4
## 1. Скоуп проверки
Разбор по дельте (PROCESS.md §2.10): `git diff 82fe98bc..HEAD` (=`git diff 82fe98bc..ff2f2063`).
Коммиты дельты:
```
b5519e99 docs: review document for #276 ← публикация CODE-REVIEW-276-r2 (инфраструктура)
ff2f2063 test: stabilize Optimize overhead benchmark ← дельта r3
```
Дельта строго локальна — `git diff --stat` показывает только:
```
demo/benchmark_coincident_partitions.mjs | 22 +-
demo/golden/baselines/baselines-index.json | 26 ++-
demo/golden/baselines/coincident-partition-*.png | (4 новых файла)
demo/golden/baselines/{9 существующих сцен}.png | (обновлены байты)
docs/reviews/CODE-REVIEW-276-r2.md | 222 +++ (публикация r2)
```
Ни один файл `src/**`, `test/**`, `custom_components/**` не тронут. Продуктовый
код (`src/coincident-partitions.ts`, `src/plan-optimizer.ts`) дельтой не
задет — значит контракт поведения не меняется, новая подсистема не
затрагивается, ребейза на ушедший вперёд `dev` не было. Разбор по дельте, а
не заново, оправдан по всем критериям §2.10.
Коммит `ff2f2063` несёт `Issue: #276`, `User-Visible: no` — верно, видимого
поведения нет. Поскольку коммит трогает `demo/golden/baselines/**`, обязательны
и присутствуют `Release: v1.67.0-beta.8` и `Baseline-Reviewed:
https://github.com/Matysh/houseplan-card/actions/runs/32684802336`.
## 2. Закрытие раунда r2
| Находка r2 | Чем закрыта | Где видно |
|---|---|---|
| **M1-r2** — `benchmark:coincident-partitions` гейтит `pass` по разности двух независимых `p95` (`candidateSummary.p95 - baselineSummary.p95`) вместо уже вычисленной корректной парной статистики (`overheadSummary.p95`), из-за чего ~⅓ прогонов красные/зелёные без единой правки кода | Закрыта. `measuredOverheadP95 = Math.max(0, overheadSummary.p95)` — гейт теперь считает именно парную разницу `candidateMs - baselineMs` на каждой итерации, а не разность независимых квантилей. Дополнительно введены `BATCH_SIZE=10` (усреднение таймер-шума внутри одного замера) и ABBA/BAAB-порядок (`first,second,third,fourth` со средним `(second+third)/2` и `(first+fourth)/2`), гасящий линейный дрифт: для арифметической прогрессии позиций `(1+4)/2 == (2+3)/2`, поэтому линейный член дрифта вычитается точно | `demo/benchmark_coincident_partitions.mjs:26-53,67`; воспроизведено мной (см. §4) — 4/4 прогона стабильно `pass: true`, `relativeP95` в диапазоне 12.2–14.1 % против 4 прогонов r2, где расчётная (но не используемая тогда) `pairedOverhead.p95` не проходила бюджет все 4 раза |
## 3. Унаследовано из r2 (без повторной проверки)
Источник: `docs/reviews/CODE-REVIEW-276-r2.md`, HEAD `82fe98bc`. Дельта не
касается перечисленного, поэтому вывод r2 (который для AC1,2,4,6-10,12-14
сам был унаследован из r1, HEAD `496e79a6`) принят без повторного исполнения:
- **AC1, AC2, AC4** (exact-match условие, byte-preserved fail-closed
варианты, nested narrower/wider, orphan/overlap/draft/column/unknown-field)
— `src/coincident-partitions.ts` дельтой не тронут ни в r2, ни в r3.
- **AC3** (несколько hosted door/window/gate) — тесты из r2
(`test/coincident-partitions.test.mjs:74-121`) дельтой r3 не тронуты.
- **AC5** (targeted golden: 5-см офсеты + hosted door до/после 10/30/virtual)
— сценарии и тест формы из r2 (`demo/golden/matrix.mjs`,
`test/golden-matrix.test.mjs:258-286`) дельтой r3 не тронуты; сама
визуальная приёмка baseline произошла именно в дельте r3 (см. §4) и
проверена там впрямую, а не по доверию.
- **AC6, AC7, AC8** (Preview/atomic Apply/report/Undo/идемпотентность) —
`smoke_optimize_coincident_partition.mjs` не менялся с r1; вывод принят.
- **AC9** (preflight гейтит Apply), **AC10** (consumer parity) —
соответствующий код дельтой не тронут; выводы r1/r2 приняты как есть.
- **AC12, AC13** (мутации, дешёвые гейты) — идентификаторы мутантов и состав
гейтов не изменились дельтой r3; тем не менее дешёвые гейты
(`typecheck`/`test`/`build`+sync/`check-docs`) перезапущены заново в этом
раунде, а не унаследованы (см. §4), как и в r2.
- **AC14** (changelog/docs/терминология) — уже закрыт в `a6056111`; дельта r3
не добавляет пользовательских документов (только review-документ и golden
baseline).
- Раздел «Одно число — один источник» — дельта r3 не добавляет и не меняет
ни одной пользовательски видимой величины (тесты, бенчмарк, эталонные
изображения); вывод r1/r2 принят.
## 4. Как проверялось в этом раунде (гейты)
Дешёвые гейты — все перезапущены на HEAD `ff2f2063`, все green:
| Гейт | Результат |
|---|---|
| `npx tsc --noEmit` | green, без вывода |
| `npm test` | **1180/1180 passed**, 0 skipped, 0 failed |
| `npm run build && npm run bundle:sync` | green; `git status` чист после сборки; `cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js` и `cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js` — идентичны |
| `node scripts/check-docs.mjs` | green: «Documentation checks passed (7 files, 10 external links)» — дельта `src/**` не трогает, но гейт дёшев и перезапущен |
| `node scripts/process-gate.mjs --issues` | «гейт пройден, предупреждений 0» |
`node scripts/smoke-select.mjs --base 82fe98bc --head HEAD`:
```
Исполняемого frontend-диффа нет (src/**/*.ts не тронут).
Browser-smoke этим диффом не выбираются — это не «пропустить проверки»,
а «выбирать нечего»: смоки проверяют собранную карточку.
```
Корректно: инструмент подтверждает, что дельта не касается рендер-пути,
браузерные смоки в этом раунде не нужны.
**Целевая проверка находки M1-r2** — сам предмет дельты, разобран не по
чтению, а исполнением:
```
$ for i in 1 2 3 4; do npm run benchmark:coincident-partitions; done
RUN 1: overheadP95Ms=3.47ms relativeP95=12.2% pass=true
RUN 2: overheadP95Ms=3.75ms relativeP95=13.4% pass=true
RUN 3: overheadP95Ms=3.93ms relativeP95=14.1% pass=true
RUN 4: overheadP95Ms=3.59ms relativeP95=13.0% pass=true
```
4/4 стабильно зелёные (в r2 корректная-но-неиспользуемая метрика проваливала
бюджет все 4 раза подряд при том же коде реконсиляции — реальный оверхед не
менялся между раундами, поменялась только надёжность его измерения).
Дополнительно проверено, что метрика **умеет падать**: временно (без
коммита, только в рабочей копии) понижен `ABSOLUTE_OVERHEAD_MS` с `25` до
`0.001` — `pass` корректно стал `false`; файл возвращён в исходное состояние,
`git status`/`git diff` после возврата пусты.
**Проверка легитимности golden-приёмки** (класс D, коммит только с
`Release`/`Baseline-Reviewed`, PROCESS.md §8/правило 13):
```
gh run view 32684802336 → headSha 82fe98bcd3fb76833c27dd888d265fc15583a43b (= HEAD r2, как и требуется —
артефакт снят с ветки на проверенном ревью SHA, а не откуда попало)
job golden: шаг «Capture or verify golden matrix» — 4× missing-baseline для новых сцен coincident-partition-*
(ожидаемое поведение для «initial no-baseline CI run», demo/golden/README.md:24)
job «Upload golden candidates/diffs»: «With the provided path, there will be 105 files uploaded» — полный артефакт
Общий conclusion прогона «failure» — это штатно: golden-job фейлится на отсутствующих
baseline ровно для того, чтобы получить артефакт для локального `golden:accept --reviewed --from=...`
(механизм описан в demo/golden/README.md), а не признак сломанного прогона.
```
`baselines-index.json`: `matrixVersion` 41→42, `acceptedAt` 2026-08-24T03:17:51Z
(после `createdAt` прогона 02:58:12Z — порядок корректный), `chromium`
`151.0.7922.34` — совпадает с пином CI. Изменившихся хэшей ровно 9
(существующие сцены) + 4 новых — совпадает с формулировкой хендоффа «девять
byte-различий» и «четыре новых сцены».
Не запускался (по необходимости, обосновано):
- Полный `golden:verify`/`golden:capture` — предрелизный гейт (§8/§11.4);
сами эталоны уже приняты штатным `golden:accept --reviewed` на полном
Linux CI артефакте (см. выше), повторная локальная съёмка ничего не
добавляет к ревью и дала бы другой байтовый PNG на другой машине
(demo/golden/README.md).
- `python -m pytest tests_backend` — дельта не касается `custom_components/**/*.py`.
- Остальные browser-смоки — инструмент выбора не вернул ни одной связи, дельта
не трогает `src/**`.
- Мутации (`optimizer-coincident-*`, `optimize-preflight-bypassed`) и
`model-invariants` — не перезапускались в этом раунде: код, который они
проверяют (`src/coincident-partitions.ts`, `src/plan-optimizer.ts`),
дельтой r3 не тронут, а в r2 они уже были перезапущены (не по доверию) на
HEAD, ближайшем к текущему.
## 5. Находки
Новых находок нет. M1-r2 закрыта полностью — по существу («тест переживёт
будущую правку и умеет упасть»), не только по букве. High: 0, Medium: 0,
Low: 0.
## 6. Проверка AC — что изменилось в этом раунде
| AC | Статус r2 | Статус r3 | Доказательство дельты |
|---|---|---|---|
| AC5 | ✅ (данные/фикстура; визуальная приёмка — предрелизный гейт) | ✅ (визуальная приёмка выполнена: 4 новых baseline приняты `golden:accept --reviewed` на полном Linux CI артефакте прогона `32684802336`, headSha совпадает с проверенным ревью r2) | `demo/golden/baselines/baselines-index.json` (matrixVersion 42, 4 новых записи); проверено `gh run view` выше |
| AC11 | 🟡 частично (call-count/ownership ✅ твёрдо; budget-часть недетерминирована — M1-r2) | ✅ (обе половины доказаны: call-count/ownership не менялся, budget-бенчмарк теперь гейтится по корректной парной статистике и стабилен 4/4) | `demo/benchmark_coincident_partitions.mjs:62-67`; воспроизведено мной 4× + проверка «умеет падать» (см. §4) |
Остальные AC (1-4,6-10,12-14) дельтой r3 не задеты — статус наследуется из
r2 (§3).
## 7. Чего не проверял и почему
- Полный `golden:verify`/`golden:capture` матрица целиком — предрелизный
гейт по процессу; новые baseline уже приняты штатным путём, что я
проверил через историю CI-прогона, а не повторным захватом.
- `python -m pytest tests_backend` — дельта не касается Python-кода.
- Мутационные гейты и `model-invariants` — не перезапускались повторно в
r3, так как затрагиваемый ими код не входит в дельту `82fe98bc..HEAD`
(унаследовано из r2, где они были перезапущены не по доверию).
- Пиксельные диффы 9 изменившихся сцен «вручную» — не пересчитывал побайтово
сам; доверился штатному механизму `golden:accept --reviewed` на полном
CI-артефакте (что и есть предписанный процессом способ приёмки, а не
повторная ручная проверка ревьюером).
## 8. Вывод
Единственная находка предыдущего раунда (M1-r2) закрыта предметно: гейт
бенчмарка теперь считает именно ту статистику, которая измеряет реальный
парный оверхед, и подтверждён экспериментально как стабильный (4/4 зелёных
без правок) и как способный упасть (искусственно ужесточённый бюджет дал
`pass: false`). Дельта раунда не касается продуктового кода и не меняет
контракт поведения — разбор по дельте с наследованием AC1-4,6-10,12-14 из
r1/r2 корректен по PROCESS.md §2.10. Новых находок нет.
**Вердикт: зелёный.**