Issue: #276 User-Visible: no
16 KiB
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, HEAD82fe98bcd3fb76833c27dd888d265fc15583a43b, вердикт жёлтый (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. Новых находок нет.
Вердикт: зелёный.