18 KiB
CODE-REVIEW-580-r2
Issue: #580 · Этап: code · Заход: r2 · Материал: c044e9ea3861b777c04233073a02a0a3e2da354a
(рабочая копия проверена на этом SHA, git fetch/checkout не выполнялись)
Почему это r2, а не продолжение r1
Первый код-ревью (CODE-REVIEW-580-r1.md) вынес зелёный вердикт на материале
4cb6827c3d1ea0e8307ff7f406b425262c25649a. Пока ревью шло, origin/dev продвинулся на
один коммит, автоматическое слияние отказало (§7.2 — «это другой код»), и автор
перебазировал ветку на новый origin/dev скриптом scripts/rebase-on-dev.mjs
(комментарий issue от 2026-09-15T06:07:14Z). Новая вершина — c044e9ea — и это
материал текущего раунда. Старые SHA r1 (4cb6827c, 23e66392, c22eaf7d) после
ребейза не существуют в истории (git cat-file -t — Not a valid object name),
поэтому дельта «дословно» через git diff <старый SHA>..HEAD невозможна.
Это ребейз на ушедший вперёд dev — по правилам раунда такой случай не
сокращается до дельты и требует полного разбора. Ниже — полный разбор, но
методом, который эксплуатирует то, что можно проверить дёшево: побайтовое
сравнение каждого изменённого файла в git diff origin/dev...HEAD с тем, что
цитировал и проверял r1, плюс независимая проверка, что тяжёлые CI-гейты на новом
SHA подтверждены не «переиспользованием ради переиспользования», а совпадением
хеша содержимого с ранее проверенным деревом.
Скоуп
git log --oneline origin/dev..HEAD — шесть коммитов, из них три содержательных
(остальные три — docs: review document for #580, коммиты документов SPEC-REVIEW
r1/r2 и этого самого CODE-REVIEW r1, наследие этапа spec и предыдущего раунда, не
трогаются):
d2c7e6f7(fix, User-Visible: yes) — окклюзия комнатной части внешнего луча внутренними откосами толстой стены.a32b280b(fix, User-Visible: no) — типизация того же кода (Geomвместоas any).8b8260b2(test, User-Visible: no, несётRelease: v1.76.0-beta.4иBaseline-Reviewed:) — принятие двух golden-эталонов (DPR1/DPR2).
git diff origin/dev...HEAD --stat: 57 файлов, из них по существу —
src/sun.ts, test/sun.test.mjs, test/golden-matrix.test.mjs,
demo/smoke_sun.mjs, demo/golden/matrix.mjs, scripts/mutation-registry.mjs,
docs/SUN.md, оба CHANGELOG; плюс два новых PNG-эталона,
demo/golden/baselines/baselines-index.json и весь бандл
(dist/**, custom_components/houseplan/frontend/**) — бандл пересобран с новыми
хешами файлов из-за нового dev в основании, это ожидаемо и не несёт логики.
custom_components/**/*.py в диффе отсутствует — AC7 по touch/i18n/схеме не
задет.
Трейлеры: d2c7e6f7 — User-Visible: yes, оба changelog в этом же коммите
(проверено git show --stat). 8b8260b2 — Release:/Baseline-Reviewed: со
ссылкой на реальный run.
Проверка того, что ребейз не изменил код по существу
Построчно сравнил git diff origin/dev...HEAD для каждого содержательного файла
с текстом, который CODE-REVIEW-580-r1.md цитировал и разбирал:
src/sun.ts— diff идентичен описанному в r1 (тот жеintersectRings, та же сигнатураrayRimEdges/rimSources, те же номера механик —intersectRings(quad, rayQuad(innerA, innerB, away, len), clipPoly)и дедупликация источников поeps=1e-4).test/sun.test.mjs— оба новых теста (#580: an oblique outer ray...,#580: normal incidence...) побайтово совпадают с тем, что цитировал r1, включая константу328.4529946162075.demo/smoke_sun.mjs— тот жеpointInRing, тот жеinnerFaceXчерез отражение экрана, те же четыре новыхcheck(...).demo/golden/matrix.mjs,test/golden-matrix.test.mjs— та же пара сценариевdpr{1,2}, версия матрицы62→63.scripts/mutation-registry.mjs— те же два новых мутанта (sun-ray-outer-jamb-occlusion-ignored,sun-ray-outer-occluded-rim-source-ignored),find-паттерны совпадают со строками текущегоsrc/sun.ts.docs/SUN.md, обаCHANGELOG— тот же текст.
Вывод: продуктовая дельта #580 после ребейза не изменилась ни на строку — изменился только бандл (новые хеши ассетов) и добавились три коммита документов ревью. Это подтверждает и сам автор в комментарии («продуктовая дельта #580 не менялась»), но здесь это установлено чтением диффа, а не принято на слово.
Как проверялось
Гейты
Валидация на точном материале c044e9ea — зелёная, дважды: run 34935586944
(упомянут во вводном сообщении) и более ранний 34935525859 того же SHA — оба
conclusion: success.
Не поверил заявлению «зелёный» буквально: посмотрел job-логи run 34935586944 и
обнаружил, что тяжёлые джобы (browser-смоки, golden, perf-смок, geometry-parity,
backend) в нём skipped через Переиспользование: это дерево уже проверено.
Чтобы отличить легитимный реюз от «зелёного, потому что не запускалось», прочитал
лог этого job'а: ключи реюза считает scripts/gate-reuse.mjs --job=<job> по
содержимому, не по SHA коммита и не по полному git-дереву (иначе ребилд бандла
сломал бы совпадение):
| job | результат |
|---|---|
smoke |
Cache hit for: reuse-smoke-bb7d10d9… |
golden |
Cache hit for: reuse-golden-ac206839… |
performance_smoke |
Cache hit for: reuse-performance_smoke-c2e55df8…-glow |
geometry_parity |
Cache not found (ожидаемо — diff не трогает модель геометрии) |
backend |
Cache not found (ожидаемо — custom_components/**/*.py не тронут) |
Кэш-хиты для smoke/golden/performance_smoke означают, что релевантное
содержимое (то, что реально проверяют эти гейты) на c044e9ea побайтово
совпало с деревом, на котором r1 уже нашёл реально выполненный (не
переиспользованный) прогон — 34933022019, зафиксированный в r1 как run с
3/3 browser-смоками, golden и 6/6 mutation-шардами зелёными. Это закрывает
AC4/AC5 без повторного локального прогона: реюз здесь не «дыра», а
детерминированная функция от неизменного содержимого, что я проверил, а не
предположил.
Мутационные джобы (Мутанты по диффу 1–6/6) на c044e9ea — не переиспользованы,
выполнены заново и зелёные: npx tsc --noEmit/typecheck и юнит-тесты прошли
свежо на этом самом SHA.
Не гонял локально: npx tsc --noEmit, npm test, npm run build,
node scripts/check-docs.mjs, npm run golden:verify — покрыты зелёным Validate
на точном SHA (см. выше), плюс отдельно проверенным содержательным реюзом.
npm run invariants, python -m pytest tests_backend — diff не касается
персистентной модели геометрии (рёбра/толщина/layout/marker.space/open_spans) и
не трогает custom_components/**/*.py; толщина стены здесь только читается
(wallDepthByOpening), не записывается.
Разбор кода
Продуктовый код (src/sun.ts) не изменился относительно того, что r1 уже
разобрал построчно (независимый вывод формулы окклюзии в базисе {нормаль,
тангенциальная ось окна}, ручной пересчёт константы 328.4529946162075 с
совпадением до 13 знаков, проверка что мутанты бьют именно по изменённым
строкам, проверка что demo/smoke_sun.mjs — независимая, не скопированная из
продукта реализация геометрии). Побайтовое совпадение диффа (раздел выше)
означает, что этот разбор остаётся в силе без повторного вывода — не потому что
я поверил документу r1, а потому что сверил текст, который он проверял, с
текстом, который лежит в origin/dev...HEAD сейчас.
Дополнительно к r1 проверил:
- что три «продуктовых» коммита (
d2c7e6f7,a32b280b,8b8260b2) после ребейза не имеют собственных CI-прогонов (gh run list --commit <sha>→[]для каждого) — Validate гонялся только на итоговом SHA ветки, что ожидаемо для push после ребейза без промежуточных пушей; - что коммиты
d37b2c9f(Prepare v1.76.0-beta.4) иe54ff33c(новый tiporigin/dev, docs-ревью #581), которые вошли в основание после ребейза, не трогаютsrc/sun.tsи вообще не пересекаются с темой солнечных лучей — подтвержденоgit diff d37b2c9f..e54ff33c -- src/sun.ts(пусто) иgit show --statобоих коммитов; - что коммиты #577 (
внешний луч, та же тема) целиком лежат в основании до ребейза (были вdevещё когда открывалась ветка #580) — новых пересечений с #577 не возникло,src/sun.tsв диапазонеd37b2c9f..e54ff33cне менялся.
Закрытие раунда r1
| находка r1 | статус |
|---|---|
| Блокирующих находок не было | — |
| Не-Medium наблюдение (неточность формулировки ТЗ «одно дополнительное пересечение») | не относится к коду; сам код и диагноз не изменились ребейзом — наблюдение остаётся зафиксированным для памяти, не требует действия |
Раздел «находка → чем закрыта» здесь вырожден: r1 был зелёным без замечаний в скоупе задачи, поэтому r2 не закрывает правки — он подтверждает, что зелёный вердикт остаётся верным на новом материале после механического (не содержательного) ребейза.
Унаследовано из r1
Из docs/reviews/CODE-REVIEW-580-r1.md (материал 4cb6827c3d1ea0e8307ff7f406b425262c25649a,
дерево eb607a98d8c5a3f34ff9545a589358b50988c20f) принято без повторного
самостоятельного вывода, поскольку побайтовое сравнение диффов (раздел выше)
подтвердило отсутствие изменений в этих файлах:
- независимый математический вывод формулы окклюзии и ручной пересчёт константы
328.4529946162075— сверено, что тест и код не изменились; - анализ
rayRimEdges/uniqueSources/отката на[ray.a, ray.b]приrimSources === undefined(AC3, режимinner/d<=0) — код не изменился; - проверка независимости
demo/smoke_sun.mjs(pointInRing,innerFaceXчерез отражение) от продуктовой формулы — файл не изменился; - проверка
demo/golden/matrix.mjs/хешей PNG на не-пустой принятый эталон и на корректный DPR при рендере — сценарии не изменились, только версия матрицы; - вывод «единственный источник числа» (обрезанная ширина луча входит в тот же
SunRay.polys, второго независимого вычисления в продукте нет) — код не изменился.
Найдено
Блокирующих находок нет.
Что проверено и корректно
- AC1–AC3 — код идентичен r1-проверенному, юнит-тесты не изменились.
- AC4 (browser smoke), AC5 (golden DPR1/DPR2) — реюз-кэш на точном SHA
c044e9eaподтверждён как совпадение по содержимому с деревом, где эти джобы реально выполнялись (см. таблицуgate-reuseвыше), а не как слепое доверие статусу Validate. - AC6 — Validate зелёный на точном материале раунда, двумя независимыми run.
- AC7 — diff по-прежнему ограничен солнечной геометрией/тестами/документацией и
пересборкой бандла;
custom_components/**/*.py, UI, i18n, touch-контракт и схема конфигурации не тронуты. - Трейлеры и оба changelog — в правильном коммите (не изменилось).
- Ребейз на новый
dev— чисто механический: без конфликтов исходников, продуктовая дельта #580 не изменилась ни на строку, новое основание (d37b2c9f,e54ff33c) не пересекается с темой солнечных лучей.
Чего не проверял
- Не запускал
npx tsc --noEmit,npm test,npm run build,node scripts/check-docs.mjs,npm run golden:verifyлокально — переиспользовал зелёный Validate на этом самом SHA, дополнительно проверив легитимность реюза тяжёлых джобов по ключам содержимого (см. выше), а не только по статусу. - Не запускал
npm run invariants— diff не касается персистентной модели геометрии (рёбра/толщина/layout/marker.space/open_spans). - Не запускал
python -m pytest tests_backend—custom_components/**/*.pyне тронут. - Не перевыводил независимо математику окклюзии и не пересчитывал константу
328.4529946162075— унаследовано из r1, поскольку строкиsrc/sun.tsиtest/sun.test.mjsне изменились (подтверждено побайтовым сравнением диффа).
Материал раунда
- Ветка:
issue/580-outer-sun-wall-occlusion, коммитc044e9ea3861— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
723c351607934580f0bfbbc19bef5b182273f939git log --all --format='%H %T' | grep 723c35160793 - Тело issue:
558be5cfc33a8fe1f475fbc5a0210392339265c20fad0c22e82858b57c96b848 - Вердикт конвейера:
green· High 0