mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 20:29:00 +00:00
171 lines
13 KiB
Markdown
171 lines
13 KiB
Markdown
# CODE-REVIEW-400-r2
|
||
|
||
- Issue: https://github.com/Matysh/houseplan-card/issues/400
|
||
- ТЗ: `docs/specs/400-beta-polish.md` (r1), ревью ТЗ зелёное (комментарий 2026-08-31T04:44:56Z)
|
||
- Ревью r1: `docs/reviews/CODE-REVIEW-400-r1.md`, вердикт жёлтый, SHA `73ecfbd1d74a6d194f62e8e83766294018f8eb81`, опубликовано коммитом `f07e3c54` (2026-08-31T05:06:35Z)
|
||
- Диапазон материала r2: `origin/dev...HEAD`, HEAD на момент разбора и на момент вердикта — `f07e3c54ffea88b0d77b12065bf318fc820d0ebf`
|
||
- Заход r2, блокирующих циклов израсходовано **1 из 4** до этого вердикта
|
||
|
||
## Дельта раунда (§2.10)
|
||
|
||
Предыдущий вердикт получен на SHA `73ecfbd1`. Дельта:
|
||
|
||
```
|
||
$ git diff 73ecfbd1..HEAD --stat
|
||
docs/reviews/CODE-REVIEW-400-r1.md | 196 +++++++++++++++++++++++++++++++++++++
|
||
1 file changed, 196 insertions(+)
|
||
```
|
||
|
||
Это **единственный** коммит между r1 и r2 — публикация документа r1-ревью самим
|
||
конвейером. `git diff 73ecfbd1..HEAD -- src/ scripts/ demo/` пуст. Ни один файл
|
||
кода, теста или мутанта не изменился с момента r1.
|
||
|
||
Однако в issue после публикации r1 есть комментарий автора (2026-08-31T05:14:07Z,
|
||
**позже** документа r1 на 5:06:35Z): *«Medium закрыт, HEAD обновлён»*, описывающий
|
||
конкретную правку — именованную константу `HANDLE_PAINT_ORDER = ['edges',
|
||
'corners']`, изменённый патч мутанта, замену `handles[3]` на выбор ручки по роли
|
||
в `smoke_furniture`. Это и есть предмет разбора r2: делает ли фактический
|
||
репозиторий то, что утверждает комментарий.
|
||
|
||
**Ответ: нет.** Ни одна из трёх заявленных правок не существует ни в одном
|
||
коммите ни одной ветки:
|
||
|
||
```
|
||
$ git grep -l "HANDLE_PAINT_ORDER" $(git rev-list --all) -- src/
|
||
(пусто — по всей истории репозитория)
|
||
|
||
$ for b in $(git branch -a --format='%(refname)' | grep issue/400); do git log $b --oneline -3; done
|
||
f07e3c54 docs: review document for #400
|
||
73ecfbd1 build: refresh bundle trees and the doc capture for #400
|
||
fe3b85c0 fix: the corner handle wins on small furniture, guides exclude the real drag (#400)
|
||
(других веток с #400 нет)
|
||
|
||
$ grep -n "handles\[3\]" demo/smoke_furniture.mjs
|
||
360: const se = handles[3] || stageEl(); // SE — четвёртый угол
|
||
```
|
||
|
||
`git fetch origin issue/400-beta-polish` не принёс новых коммитов — `HEAD` на
|
||
удалённой ветке совпадает с локальным. Единственное отдалённо связанное действие
|
||
после комментария — коммит `f07e3c54`, но это публикация r1-ревью, а не фикс.
|
||
|
||
## Закрытие раунда r1
|
||
|
||
| Находка r1 | Чем закрыта | Где это видно |
|
||
|---|---|---|
|
||
| **M1** — мутант `furniture-edge-handles-steal-the-corner` правит только текст JS-комментария, не порядок отрисовки; регрессию AC1 не ловит | **Не закрыта.** Автор заявил фикс в комментарии, но код не изменился | `git diff 73ecfbd1..HEAD -- src/ scripts/` пуст; повторный прогон ниже даёт тот же результат, что в r1 |
|
||
|
||
Повторный прогон того же гейта, что дал находку в r1:
|
||
|
||
```
|
||
$ node scripts/mutation-gate.mjs --id=furniture-edge-handles-steal-the-corner
|
||
ok чистый прогон: node demo/smoke_furniture_polish.mjs
|
||
FAIL furniture-edge-handles-steal-the-corner: тест остался зелёным на сломанном коде
|
||
поймано 0 из 1
|
||
```
|
||
|
||
Идентично записи в CODE-REVIEW-400-r1.md. Патч мутанта в
|
||
`scripts/mutation-gate.mjs:756-759` по-прежнему меняет только строку внутри
|
||
`/* ... */`.
|
||
|
||
## Унаследовано из r1
|
||
|
||
Всё, что предметно не связано с M1, дельта не задевает (дельта нулевая), поэтому
|
||
принимается без повторной проверки по документу `docs/reviews/CODE-REVIEW-400-r1.md`,
|
||
SHA `73ecfbd1`:
|
||
|
||
- AC1/AC2 (угловая ручка выигрывает хит на мелкой мебели) — доказаны живым
|
||
браузерным смоком `smoke_furniture_polish.mjs` (`smallFurnitureCornerWinsTheHit:
|
||
true`, `largeFurnitureKeepsBothHandles: true`), прогнано вживую в r1.
|
||
- AC4/AC5 (`_alignCandidates` исключает по `_deviceDrag`) — доказаны смоком
|
||
`smoke_align_guides.mjs` и вторым мутантом (`align-guides-exclude-dead-source`,
|
||
«поймано 1 из 1»); перепрогнан в r2 с тем же результатом (см. таблицу гейтов).
|
||
- AC3/AC6 (решение по 38 help-строкам в `docs/ARCHITECTURE.md`, бюджет
|
||
285 425 / 300 000) — подтверждены в r1 чтением записи и прогоном `bundle:budget`;
|
||
в r2 бюджет перепрогнан и даёт то же число (см. ниже) — код не менялся, значит
|
||
и вывод не мог измениться.
|
||
- Трейлеры четырёх содержательных коммитов (`60c211c8`, `532743b0`, `fe3b85c0`,
|
||
`73ecfbd1`) — проверены в r1, дельта их не касается.
|
||
- Смок-выборка `scripts/smoke-select.mjs --base origin/dev --head HEAD` и 9
|
||
зелёных прямых совпадений — не перезапускались в r2: набор файлов, который они
|
||
покрывают, не изменился (дельта r2 — один docs-файл).
|
||
|
||
## Как проверялось (r2)
|
||
|
||
Дешёвые гейты гоняются в каждом раунде независимо от локальности дельты (§2.10).
|
||
Диапазон src/scripts не менялся, но числа сверены заново, а не унаследованы вслепую.
|
||
|
||
| Гейт | Команда | Результат |
|
||
|---|---|---|
|
||
| typecheck | `npx tsc --noEmit` | чисто |
|
||
| unit | `npm test` | 1668 tests, 1667 pass, 0 fail, 1 skipped — совпадает с r1 |
|
||
| build | `npm run build` | успешно, 15.6s |
|
||
| сверка трёх копий бандла | `npm run bundle:sync` | `git status --porcelain` пуст до и после — `dist`, `custom_components/houseplan/frontend`, `demo/srv/assets` уже синхронизированы, дрейфа нет |
|
||
| бюджет | `npm run bundle:budget` | initial 285 425 / 300 000, тот же варнинг про запас < 15 000 Б (#367, фоновый, не следствие этой задачи) — число идентично r1 |
|
||
| мутант (предмет M1) | `node scripts/mutation-gate.mjs --id=furniture-edge-handles-steal-the-corner` | **красный, как в r1**: поймано 0 из 1 |
|
||
| мутант (контроль) | `node scripts/mutation-gate.mjs --id=align-guides-exclude-dead-source` | зелёный: поймано 1 из 1, без изменений |
|
||
|
||
Не прогонялось (дельта — один docs-файл, ничего из перечисленного её не
|
||
задевает и было закрыто в r1): `check-docs.mjs` (diff r2 не трогает `src/**`),
|
||
`no-new-any.mjs` (нет новых строк кода), `smoke-select.mjs` (набор символов не
|
||
менялся), `model-invariants.mjs` (diff не про геометрию), `golden:verify`,
|
||
`pytest tests_backend`, performance-профили, полный набор смоков.
|
||
|
||
## Находки
|
||
|
||
### Medium (в скоупе задачи — по-прежнему открыта из r1)
|
||
|
||
**M1 (перенесена из r1, не закрыта).** Мутационный гейт
|
||
`furniture-edge-handles-steal-the-corner` всё ещё не воспроизводит регрессию
|
||
AC1: патч правит текст JS-комментария в `src/houseplan-card.ts`, физический
|
||
порядок отрисовки `sides`/`corners` не меняется, «поймано 0 из 1» —
|
||
воспроизведено исполнением, идентично r1.
|
||
|
||
Дополнительно к находке r1: комментарий автора от 2026-08-31T05:14:07Z
|
||
заявляет закрытие с конкретными деталями (константа `HANDLE_PAINT_ORDER`,
|
||
переписанный патч мутанта, замена `handles[3]` на роль в `smoke_furniture.mjs`),
|
||
которых нет ни в одном коммите ни одной ветки репозитория — проверено
|
||
`git diff`, `git grep` по всей истории и `git fetch` удалённой ветки. Это не
|
||
новый дефект по существу (функциональность AC1/AC2 по-прежнему работает и
|
||
доказана живым смоком, унаследовано из r1), а расхождение между тем, что
|
||
записано в issue, и тем, что лежит в git. Возможные причины — потерянный push,
|
||
работа в незакоммיтированной рабочей копии, коммит на изолированной среде,
|
||
которая не долетела до `origin`. Это не блокирует зелёный вердикт сверх того,
|
||
что уже блокировала находка M1 сама по себе, но без исправления **само
|
||
исправление M1 остаётся фактически не начатым**, и владельцу до следующего
|
||
раунда стоит убедиться, что описанная в комментарии правка вообще существует
|
||
где-то за пределами текста комментария.
|
||
|
||
**Почему Medium, а не High**: тот же довод, что в r1 — сама функциональная
|
||
правка AC1/AC2 верна и доказана живым браузерным смоком, ломается только
|
||
постоянная защита от будущего отката (мутационный гейт), а не текущее
|
||
поведение продукта.
|
||
|
||
**Ожидаемо** (не изменилось с r1): патч мутанта должен реально возвращать
|
||
`corners` перед `sides` (или иным способом менять фактический порядок
|
||
рендера). Проверка приёмки: `node scripts/mutation-gate.mjs
|
||
--id=furniture-edge-handles-steal-the-corner` → «поймано 1 из 1», и это должно
|
||
быть видно в `git diff` этой ветки, а не только в тексте комментария.
|
||
|
||
## Что проверено и корректно
|
||
|
||
- Все AC, кроме предмета M1, — без изменений с r1, унаследовано с указанием
|
||
источника выше.
|
||
- Дешёвые гейты r2 воспроизводят те же числа, что в r1 (tsc чист, 1667/0 тестов,
|
||
бюджет 285 425/300 000, три копии бандла синхронизированы) — ожидаемо, так как
|
||
дельта нулевая по коду.
|
||
- Контрольный мутант `align-guides-exclude-dead-source` по-прежнему ловит свою
|
||
регрессию (1 из 1) — AC4/AC5 не деградировали.
|
||
- Ветка `issue/400-beta-polish` — единственная с материалом по #400; других
|
||
мест, где могла бы жить заявленная правка, не найдено.
|
||
|
||
## Чего не проверял
|
||
|
||
- Не искал вне git (например, в артефактах CI-запусков или локальных стейджах
|
||
автора) заявленную правку — ревью материалом считает только репозиторий, как
|
||
предписано; если правка существует где-то ещё, её нужно закоммитить и
|
||
запушить, тогда она попадёт в следующую дельту.
|
||
- Не прогонял `check-docs.mjs`, `no-new-any.mjs`, `smoke-select.mjs`,
|
||
`model-invariants.mjs`, `golden:verify`, `pytest tests_backend`,
|
||
performance-профили и полный набор смоков — дельта r2 их не касается
|
||
(единственный файл дельты — docs), и они были закрыты в r1 на том же коде.
|