17 KiB
CODE-REVIEW-729-r1
Материал раунда: git log --oneline origin/dev..HEAD / git diff origin/dev...HEAD
на SHA 0e44f8a69f01c94b15b1ef48b411f5081b8e686d (ветка issue/729-spec-draft,
один коммит поверх dev@7ff2b5ae). Трек: ask · заход r1 · блокирующих
циклов 0/4 · маршрут вердикта: fix.
Скоуп
Issue #729 (выделено из #707) вводит одно явное исключение из правила №1:
локальный, непушимый черновик кода класса A на track:ask, пока задача стоит
в S4-spec-review, принимается правилом 10 (checkCommitEraStatuses,
scripts/process-gate.mjs), если:
- коммит несёт ровно один трейлер
Spec-Draft: sha256:<64 hex>; - трек на момент написания (
authorDate) —ask; - эпоха
S4-spec-review, в которой написан коммит, закрытаS5-ready; - трейлер равен хешу «Тело issue» зелёного (High 0)
SPEC-REVIEW-<NN>-r*этой эпохи, прочитанного из git (вершина диапазона илиorigin/dev).
Пакет задачи (scripts/task-packet.mjs) печатает новый раздел «Черновик
(#729)»: в S4 — право вести черновик и готовую строку трейлера; в S5/S6 —
какое ревью ТЗ зелёное и изменилось ли тело после него. Канон (PROCESS.md
§11.8 и ссылки на него из §1, §2.4–2.6, §3 п.1, §7.2, §9, §10.2, §12),
docs/process/AUTHOR.md, docs/process/REVIEWER.md, AGENTS.md и
test/process-digests.test.mjs обновлены синхронно. _process.yml не
менялся — так и было заявлено в ТЗ (не-скоуп).
Изменённые файлы (все входят в заявленный в ТЗ список «Затронутые файлы»,
новых — нет): AGENTS.md, PROCESS.md, docs/process/AUTHOR.md,
docs/process/REVIEWER.md, scripts/process-gate.mjs, scripts/task-packet.mjs,
test/pre-push-gate.test.mjs, test/process-digests.test.mjs,
test/process-gate.test.mjs, test/task-packet.test.mjs.
Коммит несёт Issue: #729 и User-Visible: no; изменение не видно продуктовым
пользователям House Plan (процесс разработки, не продукт из docs/SCOPE.md),
changelog корректно не тронут.
Как проверялось
Дешёвые гейты на этом SHA подтверждены зелёным Validate (ссылка в промпте) —
tsc/npm test/npm run build+bundle-policy не перегонялись. Дополнительно
к этому прогнано:
| Гейт | Команда | Результат |
|---|---|---|
| Целевые юниты диффа | node --test test/process-gate.test.mjs test/task-packet.test.mjs test/process-digests.test.mjs test/pre-push-gate.test.mjs |
89/89 pass (совпадает с заявленным автором числом) |
| Монолит-якоря (не регрессия) | node --test test/monolith-text-anchors.test.mjs |
2/2 pass |
| Мутации (реестр, без новых запусков) | node scripts/mutation-gate.mjs --check |
4 предупреждения — совпадает с dev, новых не добавилось |
| Бюджет чтения | node scripts/entry-cost.mjs --check |
author 5367/12000, reviewer 4750/9000 — совпадает с хендоффом |
| Процессный гейт на себя | node scripts/process-gate.mjs --range origin/dev..HEAD |
чисто, 0 нарушений |
| Трек/маршрут | node scripts/process-track.mjs stage --stage=code --labels=track:ask,S7-code-review ... |
track=ask, route_note → route: fix |
| Мутационная проверка AC «чем краснеет» (ручная, не из реестра) | временно if (false) вместо сравнения хешей в judgeDraft, затем откат |
4 теста AC1/AC2/AC4 красные — подтверждает, что тест на сверку хеша умеет падать |
Прочитаны построчно: весь диапазон scripts/process-gate.mjs (новые функции
trackAt, draftEpoch, greenSpecReviewOf, judgeDraft,
gitSpecReviewReader, правка checkCommitEraStatuses), весь диапазон
scripts/task-packet.mjs (rightsFor, latestGreenSpecReview,
specDraftState, buildPacket, renderPacket, collectInputs), полные
диффы PROCESS.md §11.8 и правок к §1/§2.4–2.6/§3/§7.2/§9/§10.2/§12,
AUTHOR.md, REVIEWER.md, AGENTS.md, test/process-digests.test.mjs,
test/pre-push-gate.test.mjs. Проверена полнота HOOK_FILES
(test/pre-push-gate.test.mjs) прямым чтением import-блоков
review-doc-guard.mjs, process-track.mjs, change-risk.mjs,
review-result-gate.mjs — список действительно покрывает новое дерево
импортов process-gate.mjs.
Прочитано, но не исполнено: сопоставление ТЗ (АК1–АК10, тело issue #729) с кодом — построчно, без отдельного прогона (доказательство — тесты автора, воспроизведённые выше).
AC → доказательство
| AC | Что | Чем доказан | Чем краснеет |
|---|---|---|---|
| AC1 | Черновик принят/отклонён по трейлеру | test/process-gate.test.mjs «#729 AC1», прогнан |
ручная мутация сравнения хешей в judgeDraft красит тест (см. таблицу гейтов) |
| AC2 | Границы эпохи и раунда | «#729 AC2», прогнан | тест сам содержит отрицательные случаи (эпоха закрыта S3/S6, не закрыта, timeline без allowed) |
| AC3 | Трек на момент записи и формат трейлера | «#729 AC3», прогнан | формат проверен 4 негативными значениями трейлера в самом тесте |
| AC4 | Сопоставление с зелёным документом своей эпохи | «#729 AC4», прогнан | негативные случаи (yellow, High 1, без «Тело issue», вне окна, более старый раунд) — в тесте |
| AC5 | Совместимость с #738 — без читателя исключение выключено | «#729 AC5», прогнан | тест сравнивает plain === strip(c) на 8 сценариях и напрямую дергает warn/fail-ветки |
| AC6 | Чтение документов из git + CLI | «#729 AC6» (reader) и «#729 AC6» (CLI), оба прогнаны на временном git-репозитории с заглушкой gh |
тест проверяет оба кода выхода (0/1) и текст находки на 4 сценариях (rebased/fromDev/stale/unproven) |
| AC7 | Один источник хеша | «#729 AC7» в обоих файлах теста, прогнаны | тест читает _process.yml и проверяет тождество функций issueBodyDigest |
| AC8 | Пакет задачи | «#729 AC8» ×2 в test/task-packet.test.mjs, прогнаны |
негативные случаи (track:show, blocked, review-4, устаревшее тело) — в тесте |
| AC9 | Канон и конспекты | test/process-digests.test.mjs, прогнан целиком |
новые ключевые правила и привязка к заголовку ### 11.8 проверены assert'ами на реальный текст файлов |
| AC10 | Гейт | gate:small, mutation-gate --check, entry-cost --check воспроизведены выше |
якоря task-packet-* и packet-infra-track-ignores-show-default не сдвинуты (сверено diff'ом mutation-registry.mjs — пусто) |
Все десять AC — защитные по характеру (гейт либо принимает, либо отказывает коммит), и у каждого в таблице есть непустой третий столбец — требование §2.7/REVIEWER.md выполнено.
Находки
Нет High. Нет Medium. Нет Low.
Читал реализацию на предмет типичных мест ошибок в такой логике (границы
эпохи, порядок проверок «находка одна — по первой невыполненной», ленивое
чтение git, инъекция specReviews, согласованность issueBodyDigest между
тремя модулями, нормализация \r\n) — расхождений с ТЗ не нашёл. Отклонения
от ТЗ, о которых автор написал в хендоффе (правка фикстуры
test/pre-push-gate.test.mjs, предупреждение «трейлер вне S4» только с
читателем, кэш документов по задаче, trailer: null в --json при
запрещённом черновике) — все мелкие технические решения в объявленном
скоупе «реализатору на выбор» (ТЗ, «Принято предположительно», пп. 6, 9, 10),
находок не образуют.
Побочные дефекты, найденные при реализации и правомерно вынесенные в
отдельные issue (не чинятся в этой задаче, не TODO в этом документе):
#752 (process-metrics), #748 п.1 (устаревшая строка пакета для S3),
#751 п.4 (метрика черновиков), плюс названные в хендоффе кандидаты (формат
Spec-Draft в commit-msg, вывод HOOK_FILES из дерева импортов) — по
заявлению автора заведены или добавлены как кандидаты; это корректный путь
по §12 («Оставили в тексте ревью» не считается закрытием), ревью их не
заводит повторно.
Что проверено и корректно
- Правило 10 (
judgeDraft) проверяет условия строго в порядке ТЗ (К3 п.2: формат → трек → эпоха → документ → хеш), «находка одна — по первой невыполненной» выполнено буквально (return fail(...)на первой же). draftEpochкорректно учитывает reconcile (#555): шагает назад по непрерывной серииS4-spec-reviewв уже отфильтрованном списке статусных событий, не путает начало эпохи с повторной постановкой метки.trackAtна коммите без трековых событий возвращаетask— соответствует §5.1 («продуктовая задача без метки трека — ask»), совпадает сtrackFromLabels([]).gitSpecReviewReaderленив (ни одного вызоваgit, пока правило 10 не спросит документы чернового коммита) и кэширован по issue — подтверждено тестом AC5 (reader.reads) и AC6.issueBodyDigest— действительно одна функция на гейт, пакет и конвейер:scripts/task-packet.mjsреэкспортирует её же изreview-doc-guard.mjs(не копию),scripts/process-gate.mjsимпортирует оттуда же якоряanchorIssueBodyFrom/anchorVerdictFrom. «Одно число — один источник» (§8) выполнено: хеш тела issue виден в трейлере коммита, в пакете задачи и в документе ревью — везде один источник.test/pre-push-gate.test.mjsHOOK_FILESрасширен корректно и полно: прямой разборimport-блоков показал, что список покрывает всё новое транзитивное дерево зависимостейprocess-gate.mjsбез пропусков.- Без инъекции
specReviews(или если в диапазоне нет чернового коммита) поведение и тексты находок побайтово равны #738 — проверено тестом AC5 и чтением кода (веткиif (specReviews ...)вокруг каждого нового куска). User-Visible: noобоснован: изменение процесса разработки, не продукта изdocs/SCOPE.md; changelog не нужен и не тронут.- Коммит несёт трейлеры
Issue: #729/User-Visible: noкорректно; сам этот коммит не является черновиком (Spec-Draftна нём не требуется — он сделан послеS5, что подтверждает хендофф «Взял: ... по зелёному ревью ТЗ»).
Чего не проверял
- Полный
npm run gate:small,npx tsc --noEmit,npm run buildс полной сверкой трёх копий бандла — не перегонял: зелёный Validate на этом SHA уже подтверждён (ссылка в промпте), диффа вdist/,src/,custom_components/,demo/golden/baselines/нет (провереноgit diff --stat— пусто). - Браузерные смоки,
golden:verify,pytest tests_backend,npm run invariants, performance-профили — не прогонял и не выбирал поsmoke-select.mjs: изменение не трогает ни один из путей, которые эти гейты проверяют (нет файловsrc/**,custom_components/**/*.py, геометрии или рендера в диффе); ни один AC их не требует. - Реальный прогон сценария «живой» ревью ТЗ → черновик → гейт на настоящем
GitHub issue (end-to-end через CI) — не воспроизводил; AC6 покрывает CLI с
заглушкой
ghна временном git-репозитории, этого достаточно для доказательства логики гейта, но не для проверки, что реальныйgh api .../timelineотдаёт точно тот формат событий, который ожидаетtrackAt/statusEvents(риск уже назван автором в разделе «Риски» хендоффа и в самом ТЗ, п. «Часы автора отстают от GitHub»). - Не проверял исполнением фактическое поведение
_process.yml(шаг «Взять SHA материала», публикация SPEC-REVIEW) — по ТЗ этот файл не менялся (не-скоуп), а материал ревью кода не включает ревью ТЗ.
Вердикт
Все 10 AC доказаны автотестами, тесты воспроизведены и умеют падать (одна мутация проверена вручную дополнительно к имеющимся негативным случаям внутри тестов). Реализация соответствует контракту ТЗ буквально — К1–К5 покрыты файл-в-файл. High/Medium не найдено. Побочные находки корректно вынесены в отдельные issue, а не оставлены как TODO.
Зелёный.
Материал раунда
- Ветка:
issue/729-spec-draft, коммит0e44f8a69f01— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
c7dc00f61e25ed2b0dae9d0ed9dea6275d3510a9git log --all --format='%H %T' | grep c7dc00f61e25 - Тело issue:
94cd1bca3f851c8c9d9fc64b3b6227fb2fd3dac9f47715053a95dd133ae40bed - Вердикт конвейера:
green· High 0 · маршрутfix