From 5cd9d0419af3e1bd0dd81c2742c3d77c8bd9634b Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2026 22:21:03 +0000 Subject: [PATCH] docs: review document for #707 Issue: #707 User-Visible: no --- docs/reviews/INDEX.md | 3 +- docs/reviews/SPEC-REVIEW-707-r2.md | 164 +++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 docs/reviews/SPEC-REVIEW-707-r2.md diff --git a/docs/reviews/INDEX.md b/docs/reviews/INDEX.md index d8494950..d4717e66 100644 --- a/docs/reviews/INDEX.md +++ b/docs/reviews/INDEX.md @@ -1,6 +1,6 @@ # Индекс ревью -Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 209, issue: 102. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. +Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 210, issue: 102. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`. | Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы | |---|---|---|---|---:|---:|---|---| @@ -16,6 +16,7 @@ | #709 | [CODE-REVIEW-709-r1.md](CODE-REVIEW-709-r1.md) | code · r1 | 🟡 жёлтый | 0 | 1 | canon TESTING.md противоречит себе | `docs/TESTING.md` `scripts/smoke-select.mjs` `scripts/pre-push-gate.mjs` `TESTING.md` `process-digests.test.mjs` | | #709 | [CODE-REVIEW-709-r2.md](CODE-REVIEW-709-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — | | #707 | [SPEC-REVIEW-707-r1.md](SPEC-REVIEW-707-r1.md) | spec · r1 | 🟡 жёлтый | 0 | 1 | К1/AC1: strings.json заявлен источником риска ux, но класс A его не видит | `strings.json` `change-classes.mjs` `custom_components/houseplan/strings.json` `scripts/change-classes.mjs` `manifest.json` | +| #707 | [SPEC-REVIEW-707-r2.md](SPEC-REVIEW-707-r2.md) | spec · r2 | 🟢 зелёный | 0 | 0 | — | — | | #706 | [CODE-REVIEW-706-r1.md](CODE-REVIEW-706-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #705 | [CODE-REVIEW-705-r1.md](CODE-REVIEW-705-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | | #704 | [CODE-REVIEW-704-r1.md](CODE-REVIEW-704-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — | diff --git a/docs/reviews/SPEC-REVIEW-707-r2.md b/docs/reviews/SPEC-REVIEW-707-r2.md new file mode 100644 index 00000000..d4a83b47 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-707-r2.md @@ -0,0 +1,164 @@ +# SPEC-REVIEW-707-r2 + +Issue: #707 · этап: spec · трек: ask · заход: r2 · блокирующих циклов израсходовано (после этого раунда): 1/4 + +## Скоуп + +#707 — часть разбиения семипунктовой аналитики 29.09 (#707/#726/#727/#728/#729). В этот +issue входят п.1, п.2, п.4 исходного объёма: единое правило риска по изменённым участкам +диффа (К1), единая функция трека/основания/лимита (К2), решение конвейера на `S7` и +заметка ревьюеру show/ask (К3), новые разделы `task-packet.mjs` (К4), правка канона и +конспектов (К5). Продуктового кода задача не трогает (класс A не затрагивается), +`User-Visible: no`. ТЗ живёт в теле issue под `## ТЗ`. + +Этот раунд — правка по единственной находке r1 (жёлтый вердикт, Medium К1/AC1: +`strings.json` был заявлен источником риска `ux`, но `classify` даёт ему класс `?`, и +правило `ux` его никогда не достигало). Автор прислал точечную правку и попросил +повторное ревью тем же комментарием («Возвращаю на ревью ТЗ», 2026-09-30T22:16:42Z). + +## Как проверялось (объём по дельте, §2.10) + +Дельта — текст issue между версией, зафиксированной в материале r1 (тело с хэшем +`96589990…8025ff4`, комментарий Matysh 2026-09-30T20:59:00Z), и текущим телом (хэш +`4025a2c871e7f78ffa70ebff5c20f6a2fd5c8df06fa61d312bf0618c2427af95`). Дельта локальна и +касается ровно одной находки: три места в теле issue, все — в контексте К1/AC1/плана +тестов. + +1. Прочитал полный текст issue заново (не только дельту) — убедиться, что правка не + потеряла ни один из 16 обязательных разделов §7.1 и не создала противоречия с + остальным текстом. Противоречий нет, все разделы на месте, порядок тот же, что в r1. +2. Нашёл и сверил все три места правки (см. «Закрытие раунда r1» ниже) — построчно + против текста, а не по заявлению автора в комментарии. +3. Перепроверил утверждение `classify('custom_components/houseplan/strings.json')` на + текущей рабочей копии (`git rev-parse HEAD` = `bbcc88caf1c344c9d3ee0c843a066df5410e5b68` + — дальше по `dev`, чем материал r1 `a5a73d1511ae…`, но это ожидаемо: между раундами + `dev` продолжает жить). Проверил, что `scripts/change-classes.mjs`, + `scripts/process-track.mjs`, `scripts/task-packet.mjs`, `scripts/ship-review.mjs` + не менялись между `a5a73d1511ae…` и `HEAD` (`git diff --stat` — пусто по этим путям), + то есть код, который r1 сверял построчно, не мог разойтись с ТЗ за это время. + `scripts/mutation-registry.mjs` менялся, но правка не касается якорей К1–К5 + (`guard-infra-keeps-ask-limit`, `packet-infra-track-ignores-show-default`, + `pipeline-ship-ignores-limits`, `ship-review-ignores-merge-marker`) — это правка + другой задачи про `beta-derived.yml`/`_beta-derived.yml`. +4. Остальные ~30 утверждений, которые r1 сверил с кодом `dev` построчно и которые дельта + не затрагивает, заново не перепроверял — см. «Унаследовано из r1». +5. Гейты не гонял: задача не создаёт и не меняет ни одного файла репозитория на этом + этапе (только текст issue). `npx tsc --noEmit`/`npm test`/`npm run build` нечего + проверять; command-line сверка `classify()` выше — это не "гейт", а прямая проверка + единственного технического утверждения, которое изменилось. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где это видно | +|---|---|---| +| Medium К1/AC1: `strings.json` назван источником `ux`, но `classify` даёт ему `?`, правило `ux` его не судит | Строка `ux` таблицы К1 переписана: столбец «Токен в изменённой строке» теперь называет только `src/i18n/**/*.json` и `custom_components/**/translations/*.json`; `strings.json` убран | Тело issue, раздел 6 «Контракт поведения», таблица К1, строка `ux`, столбец 4 | +| То же | В «Не входит» добавлен явный пункт: `custom_components/*/strings.json` — `classify` даёт `?`, К1 его не судит; расширение `change-classes.mjs` вне скоупа (используется и `shipLimitViolations`, и признаком «инфраструктура») | Тело issue, раздел 5 «Скоуп и не-скоуп», последний пункт списка «Не входит» | +| То же | AC1 получил случай (к): новый ключ в `custom_components/houseplan/translations/en.json` → `ux`; тот же ключ в `custom_components/houseplan/strings.json` → нет (класс `?`) | Тело issue, раздел 8 «Критерии приёмки», строка AC1, последний пункт списка | +| То же | План автотестов получил отрицательный случай: «`strings.json` риска не даёт (AC1 (к))» | Тело issue, раздел 9 «План автотестов», список «Чем краснеет» | + +Все три правки внутренне согласованы друг с другом (проверил перекрёстно: таблица К1 ↔ +не-скоуп ↔ AC1(к) ↔ план тестов называют один и тот же факт одинаково — класс `?`, +путь `custom_components/houseplan/strings.json`, правило `ux` не судит). Прямая проверка +кода подтверждает: `classify('custom_components/houseplan/strings.json')` действительно +возвращает `'?'`, а `classify('custom_components/houseplan/translations/en.json')` — +`'A'`. AC1(к) теперь описывает поведение, которое реализуемо буквально как написано — +находка закрыта полностью, новой неоднозначности правка не вносит. + +## Унаследовано из r1 + +Всё, что r1 проверил и подтвердил, кроме самой находки, дельта не затрагивает — код +между материалом r1 (`a5a73d1511ae4c09277e16a41c076bfd5eb1fd8e`) и текущим `HEAD` +(`bbcc88caf1c344c9d3ee0c843a066df5410e5b68`) не менялся по путям +`scripts/process-track.mjs`, `scripts/change-classes.mjs`, `scripts/task-packet.mjs`, +`scripts/ship-review.mjs`, `.github/workflows/_process.yml`, так что верификация r1 +остаётся в силе без повторного прогона: + +- Существование и сигнатуры `resolveTrack`, `trackFromLabels`, `hasTrackLabel`, + `shipLimitViolations`, `parseNumstat`, `parseNameStatus`, `SHIP_SRC_LINE_LIMIT`. +- Реальное расхождение трека при двух метках (К2/AC2), которое ТЗ называет дефектом и + чинит. +- Устарелость безусловной строки ребейза `task-packet.mjs:223` (К4/AC8). +- Полное содержимое `CLASS_A`/`CLASS_B`/`CLASS_C`/`CLASS_D` и порядок шагов + `.github/workflows/_process.yml` (шаг трека до ребейза). +- Существование `SHIP_MERGE_MARKER_RE`, `renderShipBrief`, маркера `hp:ship-merge`. +- Все четыре якоря реестра мутаций (см. выше) существуют в `mutation-registry.mjs` и не + тронуты посторонней правкой. +- Порог «300 файлов» в guard, отсутствие `bash -n`-проверки шагов `_process.yml` (AC4). +- Полный список файлов геометрии/touch/migration/devices/perf/visual из таблицы К1 — + каждое имя, сверенное в r1 построчно (кроме самой находки, все подтвердились). +- Обязательные разделы §7.1 (присутствуют и в правильном порядке — перепроверено в + этом раунде по всему тексту, см. «Как проверялось» п.1). +- §10 п.8 (сужение «метка владельца окончательна» до «метка, подтверждённая строкой + владельца») — принято как есть в r1, дельта этот пункт не трогает. +- Соответствие «Не входит» реальным границам (`smoke-select.mjs`, `process-reconcile`, + `process-resume`, `merge-candidate`, тонкий `process.yml` в `main`). +- Метки на issue (`track:ask`, `S4-spec-review`, `P2`, `infra`, `process`, `tech-debt`). +- П.7 корректно вынесен в #729, раздел «Вопрос владельцу» помечен «не блокирует, + `blocked` не ставится». + +Документ и материал того раунда: `docs/reviews/SPEC-REVIEW-707-r1.md`, материал — +тело issue с хэшем `96589990…8025ff4`, рабочая копия ревью на `a5a73d1511ae4c09277e16a41c076bfd5eb1fd8e`. + +## Находки + +Нет. Единственная находка r1 закрыта точной и согласованной правкой; новых +расхождений между ТЗ и кодом `dev` дельта не вносит. + +## Что проверено и корректно + +- Правка К1/AC1/не-скоупа/плана тестов закрывает находку r1 буквально и непротиворечиво + (см. «Закрытие раунда r1»). +- `classify()` на текущем `dev` (`bbcc88ca…`) ведёт себя ровно так, как теперь описывает + ТЗ: `strings.json` → `'?'`, `translations/en.json` → `'A'`, `src/i18n/en.json` → `'A'`. +- Код, который r1 сверял построчно (`process-track.mjs`, `change-classes.mjs`, + `task-packet.mjs`, `ship-review.mjs`, `_process.yml`), не менялся между материалом r1 + и текущим `HEAD` — унаследованная верификация не протухла. +- Все 16 обязательных разделов §7.1 присутствуют в правильном порядке и без потери + контента относительно r1, кроме целевой правки. +- `mutation-registry.mjs` изменился между раундами, но не в якорях, которые называет + план тестов #707 (это правка другой задачи — обновление списка workflow-файлов в + `.github/workflows/validate.yml`/`beta-derived.yml`→`_beta-derived.yml`). + +## Чего не проверял + +- Гейты (`npx tsc --noEmit`, `npm test`, `npm run build`) не прогонял — задача не меняет + ни одного файла репозитория на этом этапе; они станут обязательны на `S7-code-review` + против реального диффа. +- Golden/смоки/бэкенд-pytest/invariants — не применимо: класса A нет, `User-Visible: no`. +- Не переоценивал заново все ~30 утверждений r1 вне находки (полный список — в + `SPEC-REVIEW-707-r1.md`, раздел «Что проверено и корректно») — дельта их не касается, + а код, который они описывают, не изменился (проверено `git diff --stat`, см. выше). + Это отличается от «не проверял»: это «проверил, что перепроверка не нужна». +- Эффективность эвристики К1 на исторических диффах — остаётся вне этого этапа, ТЗ сама + относит это к #728 (не изменилось с r1). + +## Вердикт + +Находка r1 закрыта полностью: точечная, согласованная правка трёх мест текста, прямая +проверка `classify()` подтверждает поведение. Новых находок нет. High: 0, Medium: 0. + +**Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0** + +## Материал раунда + +- Этап: spec. Материал — тело issue #707 на момент комментария Matysh + 2026-09-30T22:16:42Z («ТЗ исправлено по ревью r1… Возвращаю на ревью ТЗ»). +- Хэш тела issue на момент этого ревью: + `4025a2c871e7f78ffa70ebff5c20f6a2fd5c8df06fa61d312bf0618c2427af95`. +- Кода/ветки продукта не существует (инфраструктурная задача до реализации). +- Сверка кода `dev`: `git rev-parse HEAD` рабочей копии ревью = + `bbcc88caf1c344c9d3ee0c843a066df5410e5b68`. + +--- + + + +## Материал раунда + +- Ветка: `dev`, коммит `bbcc88caf1c3` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `ef1d4bcac0b46bf5a39b5b4392791b717a99c8a2` + ``` + git log --all --format='%H %T' | grep ef1d4bcac0b4 + ``` +- Тело issue: `33bb0430c3c3ef213d1d69d5993e0c5e4d180fa56c5e46cd5e7849d6dab6677d` +- Вердикт конвейера: `green` · High 0