diff --git a/docs/reviews/SPEC-REVIEW-425-r1.md b/docs/reviews/SPEC-REVIEW-425-r1.md new file mode 100644 index 00000000..5903693f --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-425-r1.md @@ -0,0 +1,212 @@ +# SPEC-REVIEW-425-r1 + +- Issue: https://github.com/Matysh/houseplan-card/issues/425 +- ТЗ: `docs/specs/425-core-file-budget.md`, ветка `issue/425-core-file-budget`, + SHA `4eae3398a6510ea19b403fd1ac33a5a3cc44881b` (единственный коммит поверх + `origin/dev`, класс C: `docs: specify the core file budget gate (#425)`, + `Issue: #425` · `User-Visible: no`). +- Заход: r1 · трек: полный (снят с `small` автором — «метка small конвейер не + запускает»; техническая причина смены трека вне моей компетенции, к + содержанию ТЗ отношения не имеет). +- Вердикт: **жёлтый**. + +## Скоуп задачи + +Ядро #425: заменить #34 узким, автоматизируемым ограничителем — гейт-храповик +на размер `src/houseplan-card.ts` и `src/houseplan-editor-runtime.ts` (растёт +выше потолка → красный тест; падает больше чем на 250 строк ниже потолка → +тоже красный, чтобы потолок опускали, а не забывали). Только тестовая +инфраструктура: один тест, один мутант, строка в `docs/TESTING.md`, закрытие +#34. Продуктового кода, UX, i18n, миграций конфига задача не касается +(`User-Visible: no`). + +## Как проверялось + +1. `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` — прочитаны целиком. +2. Тело issue #425 и оба комментария (переход на `small`, затем откат на + полный трек) — прочитаны через `gh issue view 425 --json ...` (MCP-доступ к + `get_issue`/`get_issue_comments` не выдан в этой сессии). +3. Тело ТЗ прочитано целиком (`docs/specs/425-core-file-budget.md`, 103 + строки). +4. Проверено по факту, а не на слово: + - `#34` существует, открыт, `S3-spec` — ссылка и статус в ТЗ не выдуманы; + - текущие размеры ядер: `wc -l src/houseplan-card.ts` → 13658, + `src/houseplan-editor-runtime.ts` → 14322 — совпадают с колонкой `dev` в + таблице ТЗ день в день; + - заявленные «42% всего TypeScript» — при подсчёте строками выходит 38.97% + (27980/71793), но при подсчёте байтами (как считает `bundle-budget.mjs` + — прецедент похожего гейта в этом же репозитории) — 42.66% + (1312569/3076509 Б по `src/**/*.ts` на `origin/dev`). Автор посчитал + байтами; расхождение с интуитивным «строками» — не ошибка, а другая + единица измерения, оставляю как проверенный факт; + - `scripts/mutation-gate.mjs`, `test/mutation-gate.test.mjs`, + `.github/workflows/mutation-gate.yml` существуют — приём «тест + сопровождается мутантом в `scripts/mutation-gate.mjs`» это не догадка, а + действующая конвенция репозитория (`docs/TESTING.md`, правило 4); + - `scripts/bundle-budget.mjs` — единственный похожий по духу гейт в + репозитории — проверен на предмет пересечения: он про initial-view gzip + бандла, не про строки исходника; дублирования функциональности нет; + - `test/*.test.mjs` — гейта на размер файлов исходников сегодня нет + (`grep` по «budget/потолок» ничего похожего не находит) — задача + действительно новая, а не повтор существующего. +5. `node scripts/process-gate.mjs` на диапазоне `origin/dev..HEAD` — «гейт + пройден, предупреждений 0» (класс C, трейлеры корректны, веткование верно). +6. Продуктового кода коммит не содержит (`git diff origin/dev...HEAD --stat` + — один файл, `docs/specs/425-core-file-budget.md`), поэтому дешёвые гейты + (`typecheck`/`test`/`build`) к материалу этого раунда неприменимы — они + отвечают на вопрос «работает ли код», а кода в этом раунде нет. Зелёный + Validate на `4eae3398` (ссылка в контексте задачи) это подтверждает + попутно. + +## Находки + +### Medium-1 — нет обязательных разделов «Сценарий» и «Что человек увидит до и после» (§7.1) + +`docs/specs/425-core-file-budget.md`, весь документ. + +PROCESS.md §7.1 называет эти два раздела первыми не случайно: «ТЗ, которое не +может ответить на эти два вопроса, описывает работу, а не изменение +продукта». В документе их нет вообще — ни в явном виде, ни как «не +применимо» (для секции «UX, модель данных, i18n» автор такую отметку сделал: +строка 62 — «Не применимо: продуктового кода задача не касается»; для +Сценария и «что увидит человек» — не сделал). + +**Сценарий воспроизведения:** открыть файл и поискать заголовки «Сценарий» и +«Что человек увидит» — их нет; DoR-чеклист §2.5 требует полный набор разделов +§7.1 перед переводом в `S5-ready`. + +Задача действительно не имеет пользовательской видимости (`User-Visible: no`, +гейт CI), поэтому по существу ответ тривиален — но именно поэтому его нужно +написать явно, тем же приёмом, что уже применён к UX-разделу: «Сценарий: не +применимо — персона отсутствует, единственный наблюдатель контракта — +разработчик, читающий вывод `npm test`». Без этой строки документ не проходит +формальный чеклист §2.5, хотя по сути вопрос закрыт. + +Серьёзность: Medium, в скоупе — правится добавлением двух коротких абзацев, +без изменения контракта. + +### Medium-2 — AC4 (и частично AC5) не называют способ доказательства + +`docs/specs/425-core-file-budget.md:45-46`. + +DoR (§2.5) требует у каждого AC «указано, чем он доказывается: unit / backend +/ smoke / golden / «ревью кода»». AC1–AC3 это делают явно («Доказательство: +мутант...», «Доказательство: тот же юнит»). AC4 — нет: + +> **AC4**. Потолки записаны числами в самом тесте: любое их изменение видно в +> дифе и проходит ревью как решение, а не как побочный эффект. + +Способ доказательства здесь по смыслу — «ревью кода» (структурное свойство: +константа лежит в тесте, а не читается из внешнего конфига), но текст этого +не говорит, и план автотестов (строки 70–75) AC4 не упоминает вовсе — только +AC1, AC2, AC3, AC5. AC5 хотя бы косвенно закрыт пунктом 5 плана +(«потолки заданы для обоих ядер и ни для чего больше (AC5)»); у AC4 такой +связи нет ни в тексте AC, ни в плане. + +**Как проявится, если не поправить:** на код-ревью придётся решать самому, +чем считать AC4 доказанным — юнитом или чтением кода; при полном треке это +дало бы почву для расхождения между автором и ревьюером кода. + +Серьёзность: Medium, в скоупе — правится одной строкой +(«Доказательство: ревью кода — константы `...` лежат в теле теста, изменение +видно в diff»). + +### Low-1 — раздел «Откат» задублирован + +`docs/specs/425-core-file-budget.md:48-50` и `:94-96` — два одинаковых +раздела `## Откат` с идентичным текстом «Удаление одного тестового файла и +одного мутанта.» (первый явно перенесён из тела issue, второй добавлен при +расширении до полного трека, старый не убран). + +Содержательного расхождения нет, ambiguity не создаёт. Снимаю с записью: +чинится удалением одного из двух блоков при следующей правке ТЗ, отдельного +цикла не требует. + +## Что проверено и корректно + +- **Замена #34.** Ссылка живая, статус (`S3-spec`, открыт) соответствует + описанию «за 25 дней не сдвинулся»; заявление не выдумано. +- **Числа в таблице долга** (13658 / 14322 на `dev`) сверены с деревом + напрямую — точное совпадение день в день. +- **AC1–AC3, AC5** — однозначны, каждый привязан к конкретному проверяемому + условию и (кроме AC5 частично) к явному способу доказательства; план + автотестов на чистой функции `coreBudgetViolations(sizes, caps, slack)` + описывает все ветки, включая обе границы (строка 74: «границы + включительно») — асимметрия «рост без люфта / падение с люфтом 250 строк» + прочитана из контракта верно и без противоречий. +- **Мутант** соответствует действующей конвенции `docs/TESTING.md` (правило + 4): 2–5-строчный патч в реальный файл, а не в тест, тест обязан покраснеть. +- **Не найдено ни одной догадки, выданной за факт.** Все технические + утверждения (существование `scripts/mutation-gate.mjs`, конвенция + мутантов, текущие размеры файлов, отсутствие похожего гейта) проверены по + дереву репозитория, а не приняты на слово. +- **Открытых продуктовых вопросов владельцу нет** — и не должно быть: задача + целиком техническая, ни одного вопроса о том, что видит или делает человек, + в ней нет. +- **`docs/USER-GUIDE.ru.md` и канонические документы подсистем** (`SUN.md`, + `LIGHT.md`, `CANVAS.md`, `WALL-THICKNESS.md`, `UX-MODES.md`, + `CONFIG-COMPATIBILITY.md`, `TOUCH-SUPPORT.md`) не относятся к этой задаче — + видимое поведение не меняется, интерфейсная терминология не используется; + проверено тем, что задача помечена `User-Visible: no` и раздел UX ТЗ прямо + это фиксирует. +- **`docs/SCOPE.md` / Core user jobs.** Задача не закрывает ни одну строку + J1–J7 — и не обязана: это не продуктовая фича, а инженерный гейт качества + (`User-Visible: no`, класс B/C по DoD), аналогичный уже принятым в этом же + репозитории `scripts/bundle-budget.mjs` (#337/#367) и самому + `scripts/mutation-gate.mjs` (#85). SCOPE.md ограничивает, что становится + видимой функцией продукта; техдолг разработки под этот ограничитель не + подпадает. Это не находка, а явно проверенное и подтверждённое отсутствие + конфликта. +- **Класс изменений и трейлеры коммита r1** — `process-gate.mjs` подтвердил + автоматически (см. «Как проверялось», п.5). + +## Чего не проверял и почему + +- **Дешёвые гейты кода** (`npx tsc --noEmit`, `npm test`, `npm run build`, + сверка бандла) — не прогонял: материал раунда не содержит продуктового или + тестового кода, только текст ТЗ; прогонять их не на чем. +- **Мутационный гейт, golden, смоки, инварианты модели, perf-профили, + бэкенд-тесты** — не прогонял: код гейта ещё не написан (это стадия ТЗ, не + `S6`/`S7`), диф не трогает `src/**`, геометрию, рендер, Python или touch. + Ни один из этих гейтов не относится к материалу этого раунда по diff'у или + AC. +- **`docs/specs/README.md`** — не требую внесения записи об issue #425/#34 в + этот индекс: свежие специфицированные задачи (#422, #416) там тоже не + зарегистрированы, реестр по факту не поддерживается синхронно (см. и + собственную пометку PROCESS.md §7.3 п.1 о его частичном устаревании), это + не критерий приёмки ни этой, ни соседних задач. +- **Точность исторических чисел** (18 файлов на v1.58, 20287 строк на + v1.66.0) — не перепроверял по тегам: это фон мотивации, не AC, ошибка в нём + не меняет проверяемость контракта. + +## Материал раунда + +- Ветка: `issue/425-core-file-budget` +- SHA: `4eae3398a6510ea19b403fd1ac33a5a3cc44881b` +- ТЗ: `docs/specs/425-core-file-budget.md` (единственный файл в диффе с + `origin/dev`) + +## Вердикт + +Жёлтый: обе находки Medium в скоупе задачи, High нет. Обе правятся точечно — +двумя короткими разделами и одной строкой доказательства у AC4 — без +изменения контракта, AC или объёма задачи. Low снят с записью, отдельного +действия не требует. + +`Вердикт: жёлтый · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 2 → в задаче · Документ: docs/reviews/SPEC-REVIEW-425-r1.md` + +--- + + + +## Материал раунда + +- Ветка: `issue/425-core-file-budget`, коммит `4eae3398a651` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `d37bea6a940c33f8197d96b008432931ad7edb8f` + ``` + git log --all --format='%H %T' | grep d37bea6a940c + ``` +- ТЗ `docs/specs/425-core-file-budget.md`, блоб `213aaf2a92ffc550f9fd87d2b4b81338a82359a6` + ``` + git log --all --find-object=213aaf2a92ffc550f9fd87d2b4b81338a82359a6 -- docs/specs/425-core-file-budget.md + ```