17 KiB
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, SHA4eae3398a6510ea19b403fd1ac33a5a3cc44881b(единственный коммит поверх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).
Как проверялось
docs/SCOPE.md,AGENTS.md,PROCESS.md— прочитаны целиком.- Тело issue #425 и оба комментария (переход на
small, затем откат на полный трек) — прочитаны черезgh issue view 425 --json ...(MCP-доступ кget_issue/get_issue_commentsне выдан в этой сессии). - Тело ТЗ прочитано целиком (
docs/specs/425-core-file-budget.md, 103 строки). - Проверено по факту, а не на слово:
#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/потолок» ничего похожего не находит) — задача действительно новая, а не повтор существующего.
node scripts/process-gate.mjsна диапазонеorigin/dev..HEAD— «гейт пройден, предупреждений 0» (класс C, трейлеры корректны, веткование верно).- Продуктового кода коммит не содержит (
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— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
d37bea6a940c33f8197d96b008432931ad7edb8fgit log --all --format='%H %T' | grep d37bea6a940c - ТЗ
docs/specs/425-core-file-budget.md, блоб213aaf2a92ffc550f9fd87d2b4b81338a82359a6git log --all --find-object=213aaf2a92ffc550f9fd87d2b4b81338a82359a6 -- docs/specs/425-core-file-budget.md