mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 04:09:17 +00:00
@@ -0,0 +1,175 @@
|
||||
# CODE-REVIEW #695 r2
|
||||
|
||||
Материал: `origin/dev..HEAD`, ровно `f6c76b7351b1d0b9a61954b0153a44bb098bc7f3`
|
||||
(рабочая копия уже на нём). Диапазон трёх коммитов: `57ce1072` (реализация r1,
|
||||
уже разобрана в CODE-REVIEW-695-r1), `51854aea` (публикация документа r1,
|
||||
служебный коммит конвейера), `f6c76b73` (правка Medium из r1 — материал этого
|
||||
раунда). Дельта этого раунда — ровно `57ce1072..f6c76b73`:
|
||||
`.github/workflows/_process.yml`, `scripts/mutation-registry.mjs`,
|
||||
`scripts/task-packet.mjs`, `test/review-doc-guard.test.mjs`,
|
||||
`test/task-packet.test.mjs`.
|
||||
|
||||
## Скоуп
|
||||
|
||||
Единственная блокирующая находка r1 (Medium, в скоупе) — канон §5.1
|
||||
(«инфраструктурная задача (§1) без трековой метки — как `track:show`») не
|
||||
был реализован ни в `_process.yml` (лимит циклов), ни в `task-packet.mjs`
|
||||
(отображаемый трек). Автор заявляет это закрытым коммитом `f6c76b73`
|
||||
(комментарий «Сделано (r1)»). Разбор по PROCESS.md §2.10 — по дельте: полный
|
||||
пересчёт находки r1, остальное (таблица треков §5, `trackFromLabels()` для
|
||||
явно помеченных задач, якоря конспектов, трейлеры) унаследовано без повтора —
|
||||
дельта их не задевает (ни один из пяти изменённых файлов не входит в
|
||||
доказательную базу этих пунктов r1, кроме `task-packet.mjs`, где тронута
|
||||
только инфраструктурная ветвь `track`, разобранная ниже).
|
||||
|
||||
## Как проверялось
|
||||
|
||||
| Гейт | Команда | Результат |
|
||||
|---|---|---|
|
||||
| Validate на материале | CI run на `f6c76b73` (ссылка в задаче ревью) | зелёный; дешёвые гейты (`tsc`, `npm test`, `build`+`bundle-policy`) не перегонял — приняты по этой ссылке (#343) |
|
||||
| Целевой юнит-набор | `node --test test/task-packet.test.mjs test/review-doc-guard.test.mjs` | 80/80 и 64/64 pass, 0 fail |
|
||||
| `process-gate.mjs` (офлайн) | `node scripts/process-gate.mjs --range origin/dev..HEAD` | «гейт пройден, предупреждений 0» |
|
||||
| `mutation-gate --check` | `node scripts/mutation-gate.mjs --check` | `guard-infra-keeps-ask-limit` — ok; `packet-infra-track-ignores-show-default` — ok; `browser guards: 200/200`; 3 предупреждения — все про `#650` (baseline, не связаны с диффом — совпадают с r1) |
|
||||
| Мутант `guard-infra-keeps-ask-limit` | вручную заменил `limit=2` на `limit=4 # mutant` в `_process.yml`, прогнал `--test-name-pattern="r1 #695" test/review-doc-guard.test.mjs`, вернул файл (`git diff --stat` после — пусто) | **краснеет**: `AssertionError`, тест ловит мутацию |
|
||||
| Мутант `packet-infra-track-ignores-show-default` | вручную заменил тернарник `hasTrackLabel(labels) ? trackFromLabels(labels) : 'show'` на `trackFromLabels(labels)` в `task-packet.mjs`, прогнал `--test-name-pattern="r1 #695" test/task-packet.test.mjs`, вернул файл | **краснеет**: `AssertionError: expected 'инфраструктурный · show', actual 'инфраструктурный · ask'` |
|
||||
| Исполнение bash-ветки guard (не только чтение) | Извлёк новый блок `.github/workflows/_process.yml:224-242` в отдельный скрипт с mock `gh`/`has`, прогнал 6 сценариев (нет меток+только инфра-файлы; нет меток+файл класса A; явный `track:ask`; явный `track:show`; отказ `gh api`; legacy `small`) | все 6 дали ожидаемый `limit` — см. таблицу «Что проверено» |
|
||||
| Синтаксис bash-шага | `python3 -c "yaml.safe_load(...)"` извлёк `run:` строку `guard`, `bash -n` на неё | синтаксис корректен |
|
||||
| Node-однострочник guard | Прогнал ровно ту же `node --input-type=module -e '...'` строку на трёх наборах путей (только `scripts/`+`test/`; с `src/houseplan-card.ts`; пустой список) | exit 0 / 1 / 1 — соответствует логике «инфраструктура доказана только непустым списком путей без класса A» |
|
||||
| `smoke-select.mjs` | `node scripts/smoke-select.mjs --base 57ce1072 --head f6c76b73` | «Исполняемого frontend-диффа нет (src/**/*.ts не тронут)» — смоки не выбираются, выбирать нечего |
|
||||
| Трейлеры и провенанс коммита | `git show -s --format=full f6c76b73` | `Issue: #695`, `User-Visible: no`, корректно: изменение автоматизации/скриптов, ни одного пользовательского поведения продукта не задето |
|
||||
| Сверка со сформированным пакетом | `node scripts/task-packet.mjs --issue 695` | трек issue #695 (само помечено `track:show` владельцем) печатается как `инфраструктурный · show` — согласуется с явной меткой |
|
||||
|
||||
Не прогонял (и почему): golden/скриншоты, браузерные смоки (подтверждено
|
||||
`smoke-select.mjs` — нечего выбирать), `pytest tests_backend`, инварианты
|
||||
модели, `check-docs.mjs` (диапазон не касается `src/**`), performance-профили —
|
||||
диапазон не затрагивает ни одного файла класса A и не меняет геометрию/рендер.
|
||||
Полный `npm test` (3223 теста) не перегонял целиком — принят по зелёному
|
||||
Validate на этом SHA (#343); перегонял точечно только изменённые тестовые
|
||||
файлы и мутации по ним, плюс собственноручный харнесс исполнения bash-ветки
|
||||
(таблица выше) — этого требует #454 (inline-shell без исполнения не
|
||||
доказывает поведение), выполнено сверх минимума, а не вместо него.
|
||||
|
||||
## Закрытие раунда r1
|
||||
|
||||
| Находка r1 | Чем закрыта | Где это видно |
|
||||
|---|---|---|
|
||||
| Medium: §5.1 («инфраструктура без трековой метки — `track:show`») не реализован ни в `_process.yml` (лимит циклов), ни в `task-packet.mjs` (отображаемый трек); зелёный тест `task-packet.test.mjs:171` прямо утверждал старое поведение | `_process.yml`: новая ветка `guard` (строки 224-242) — при отсутствии `track:*`/`small`/`trivial` берёт диффа ветки против `dev` через `compare` API, классифицирует пути `classify()` из `process-gate.mjs`; при непустом списке (< 300, потолок ответа) без единого файла класса A ставит `limit=2`. `task-packet.mjs`: `infraTrack = hasTrackLabel(labels) ? trackFromLabels(labels) : 'show'` (строка 189), трек инфраструктурной задачи теперь печатается как `` инфраструктурный · ${infraTrack} `` вместо голого `'инфраструктурный'`. Тест `task-packet.test.mjs:171` (`#632`), на который указывала находка, переписан: `assert.equal(packet.track, 'инфраструктурный · show', ...)` — прежнее ожидание `'инфраструктурный'` больше не в коде. | `.github/workflows/_process.yml:224-242`; `scripts/task-packet.mjs:143-144,189-191`; `test/task-packet.test.mjs:110,180,231-241`; `test/review-doc-guard.test.mjs:971-982`; оба новых мутанта (`scripts/mutation-registry.mjs`) реально ловят регресс — проверено воспроизведением (таблица «Как проверялось»), не по названию. Исполнение bash-ветки (6 сценариев харнессом) подтверждает: без метки трека и без класса A → `limit=2`; с любой явной меткой трека → блок не трогает `limit`; при отказе `gh api` или файле класса A → `limit` остаётся консервативным (не понижается ошибочно). |
|
||||
|
||||
Находка полностью закрыта: и механизм (§1: «ни одного файла класса A» —
|
||||
ровно та же формула, что в PROCESS.md §1), и обе точки, которые r1 назвал
|
||||
нереализованными, и тест, который r1 предъявил как доказательство обратного
|
||||
поведения, — всё сходится с текстом §5.1 дословно («инфраструктурная задача
|
||||
(§1) без трековой метки — как `track:show`»).
|
||||
|
||||
## Унаследовано из r1 (без повторной проверки — дельта не задевает)
|
||||
|
||||
- **Таблица треков §5 и её колонки**, согласованность PROCESS.md / AGENTS.md /
|
||||
`docs/process/AUTHOR.md` / `docs/process/REVIEWER.md` — документ
|
||||
`CODE-REVIEW-695-r1.md`, дерево `2faf4770f1ba6a32a599552db9c611bfb5cc5a18`.
|
||||
Ни один из этих четырёх файлов не входит в дельту `57ce1072..f6c76b73`.
|
||||
- **`trackFromLabels()` для явно помеченных задач** (`track:ship` /
|
||||
`track:show` / `track:ask` / legacy `trivial`/`small` / без меток → `ask`),
|
||||
приоритет меток, лимит циклов для явно помеченных `track:show`/`track:ship`/
|
||||
`track:ask` в `_process.yml:87-99` — там же, дерево `2faf4770f1ba6a3...`.
|
||||
Дельта r2 добавляет только новую ветку ПОСЛЕ этой логики (строки 224-242) и
|
||||
не меняет ни один из проверенных r1 путей; сама функция `trackFromLabels`
|
||||
в дельте не тронута (diff `scripts/task-packet.mjs` добавляет только
|
||||
`hasTrackLabel` и меняет строку сборки `track`, не трогая тело
|
||||
`trackFromLabels`).
|
||||
- **Якоря конспектов (AC2 #634), ключевые формулировки, обратная
|
||||
совместимость легаси-меток `small`/`trivial`, трейлеры провенанса,
|
||||
отсутствие продуктового кода в диффе** — там же, дерево
|
||||
`2faf4770f1ba6a3...`; ни один из файлов этой доказательной базы
|
||||
(`PROCESS.md`, `AUTHOR.md`, `REVIEWER.md`, `test/process-digests.test.mjs`)
|
||||
не входит в дельту r2.
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- **Механический признак §1 применён идентично канону**: и в `_process.yml`
|
||||
(список файлов диффа `dev...branch`, ни одного `classify() === 'A'`), и в
|
||||
`PROCESS.md` §1 («ни одного файла класса A») — то же условие, что уже
|
||||
реализовано в `branchIsInfrastructure()` (`task-packet.mjs`, не тронут
|
||||
этим диффом) и в самом `process-gate.mjs`. Никакого нового, отличного от
|
||||
канона определения «инфраструктуры» дифф не вводит.
|
||||
- **Приоритет явной метки владельца сохранён**: guard пропускает новую ветку
|
||||
целиком (`&& ! has track:ship && ! has track:show && ! has track:ask && !
|
||||
has small && ! has trivial`), если стоит любая из пяти меток — идентичный
|
||||
набор в JS (`hasTrackLabel`). Подтверждено исполнением (харнесс, сценарии
|
||||
3, 4, 6) и юнит-тестом `'метка владельца главнее'`.
|
||||
- **Fail-safe при неполном доказательстве**: пустой список файлов, отказ
|
||||
`gh api`, наличие файла класса A или обрезанный (≥300) ответ compare — во
|
||||
всех случаях `limit` остаётся 4 (не понижается ошибочно), задача не
|
||||
наказывается лимитом 2 без доказанной инфраструктуры. Подтверждено
|
||||
исполнением (харнесс, сценарии 2, 5) и отдельным прогоном
|
||||
node-однострочника на пустом списке.
|
||||
- **Мутанты `guard-infra-keeps-ask-limit` и
|
||||
`packet-infra-track-ignores-show-default`** реально ловят регресс —
|
||||
проверено ручным воспроизведением обеих мутаций (не по названию `ok` в
|
||||
`mutation-gate --check`, а прогоном упавшего теста).
|
||||
- **Синтаксис нового bash-блока и YAML-документа** — `bash -n` и
|
||||
`yaml.safe_load` не нашли ошибок; блок стоит внутри уже существующего
|
||||
`if [ -n "$stage" ]`, использует уже установленное `limit` до последующих
|
||||
проверок `EXHAUSTED`/`spent -ge limit` (строки 270-299) — порядок
|
||||
вычисления корректен, «состояния гонки» с более поздним использованием
|
||||
`limit` нет.
|
||||
- **Трейлеры коммита** — `Issue: #695`, `User-Visible: no` (корректно: не
|
||||
задето ни одно пользовательское поведение продукта), ветка
|
||||
`issue/695-track-labels`.
|
||||
- **Согласованность с самим issue #695**: у issue стоит метка `track:show` —
|
||||
собранный пакет (`task-packet.mjs --issue 695`) печатает
|
||||
`инфраструктурный · show`, то есть явная метка отражена корректно и
|
||||
задокументированный пример (issue #695 сам себе) воспроизводится.
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- **Живой прогон `_process.yml` guard job** на реальном GitHub Actions
|
||||
раннере с настоящим `gh api compare` — не воспроизводил; логика проверена
|
||||
чтением синтаксиса, ручным bash-харнессом с мок-`gh`/`has` (6 сценариев,
|
||||
см. таблицу) и юнит-тестом на текст блока. **Записываю явно: для самого
|
||||
факта исполнения на реальном GitHub API — проверено чтением и
|
||||
контролируемым харнессом, не живым запуском workflow.** Это не новый
|
||||
пробел этой задачи — тот же пробел зафиксирован в r1 для всей ветки guard
|
||||
job (тестов, исполняющих `_process.yml` напрямую, в репозитории нет ни для
|
||||
старой, ни для новой логики).
|
||||
- **Поведение конвейера по треку** (мутанты на диффе кандидата `ship`,
|
||||
слияние без ревью модели, ребейз-семантика) — вне скоупа #695, это #696,
|
||||
не проверял.
|
||||
- **`process-labels/labels.tsv`** (папка владельца, вне git-дерева) — файл
|
||||
недоступен ревью, как и в r1.
|
||||
- **golden/скриншоты, браузерные смоки** (кроме факта, что `smoke-select.mjs`
|
||||
ничего не выбрал), `pytest tests_backend`, инварианты модели,
|
||||
performance-профили — диапазон не касается визуала, геометрии или Python.
|
||||
- **Ребейз-устойчивость якорей мутантов** `guard-infra-keeps-ask-limit` /
|
||||
`packet-infra-track-ignores-show-default` на дальнейших ребейзах — не
|
||||
тестировал долгосрочную устойчивость find/replace патчей, только их
|
||||
текущую верность материалу.
|
||||
|
||||
## Вердикт
|
||||
|
||||
Единственная находка r1 (Medium, в скоупе) закрыта построчно: оба места,
|
||||
которые она называла нереализованными, реализованы правилом, дословно
|
||||
совпадающим с §5.1; тест, который r1 предъявил как живое доказательство
|
||||
старого поведения, переписан и подтверждает новое; оба новых мутанта реально
|
||||
ловят регресс — проверено воспроизведением, а не по имени `ok`; сама bash-
|
||||
ветка проверена не только чтением, но и контролируемым исполнением на шести
|
||||
сценариях. Новых находок дельта `57ce1072..f6c76b73` не даёт: правка узкая,
|
||||
ограничена ровно заявленным скоупом, не трогает ни один файл класса A, не
|
||||
меняет ни одну ранее проверенную ветвь `trackFromLabels`/таблицы §5.
|
||||
|
||||
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<!-- material-anchors: сгенерировано конвейером (#414) -->
|
||||
|
||||
## Материал раунда
|
||||
|
||||
- Ветка: `issue/695-track-labels`, коммит `f6c76b7351b1` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
|
||||
- Дерево материала: `2645a194ffcd661ca9d05eb38db68d9e378faae9`
|
||||
```
|
||||
git log --all --format='%H %T' | grep 2645a194ffcd
|
||||
```
|
||||
- Тело issue: `c74209278f8dd164514eda40d8841d6eefdeffd3b490a90f47b20e3ff2b667e7`
|
||||
- Вердикт конвейера: `green` · High 0
|
||||
Reference in New Issue
Block a user