13 KiB
SPEC-REVIEW-726-r1
Issue: #726 «Процесс: выход из неудачного show — неверная классификация → ask без нового лимита» Этап: spec (PROCESS.md §2.4) · Трек: ask · Заход: r1 · блокирующих циклов израсходовано 0 из 4
Скоуп
ТЗ (тело issue, раздел ## ТЗ) меняет контракт конвейера ревью:
- структурный вердикт модели получает поля
route(fix|reclassify) иcriterion; - на треке
show, этапеcode, не-зелёный вердикт сroute: reclassifyсам переводит задачу вtrack:ask/S3-spec(если трек не подтверждён строкой владельца) либо вblocked+вопрос владельцу (если подтверждён), вместо прежнего единственного маршрута вS6-in-progress; - бюджет циклов код-ревью становится общим на все треки задачи (до 4), и
вердикт, исчерпавший бюджет, сразу ставит
review-4, не дожидаясь следующегоS7.
Изменений класса A нет — это инфраструктура (файлы scripts/process-track.mjs,
scripts/review-result-gate.mjs, scripts/review-doc-guard.mjs,
scripts/wait-verdict.mjs, .github/workflows/_process.yml, PROCESS.md,
docs/process/*). Задача явно зависит от #707 (после его S8): часть
контракта (cycleLimit(track), строка подтверждения владельца
«Трек: <x> — решение владельца», один вызов process-track.mjs в шаге
трека, заметка ревьюеру show) вводит #707, а #726 только продолжает и
переиспользует её.
Как проверялось
Дельты нет (r1, документов ревью на #726 в дереве ещё не было) — разбор полный. Метод — не согласиться с автором, а перепроверить каждый факт из ТЗ чтением текущего кода, а не поверить формулировке:
- прочитаны
docs/SCOPE.md,AGENTS.md,docs/process/REVIEWER.md, PROCESS.md §2.4, §2.5, §4, §5, §7.1, §7.2, §10.4; - тело issue #726 и его единственный комментарий («Оценка… трек ask…»);
- зависимость #707 — открыта её issue, сверены обещанные контракты
(
cycleLimit(track), строкаТрек: <x> — решение владельца,process-track.mjs) на совпадение с тем, что #726 берёт как данность; - каждая ссылка «
_process.yml:NNNN» и утверждение о текущем поведении из раздела «Проблема» ТЗ сверены построчным чтением.github/workflows/_process.ymlна HEAD40607aa3(факты в ТЗ сверены сorigin/dev108427dc— дифф108427dc..40607aa3не затрагивает ни один упомянутый в ТЗ файл, провереноgit diff --stat, разница пуста); - прочитаны целиком
scripts/process-track.mjs,scripts/review-result-gate.mjs, значимые фрагментыscripts/review-doc-guard.mjs(materialAnchorBlock,anchorVerdictFrom,reusableGreenVerdict),scripts/status-label.mjs,scripts/wait-verdict.mjs(PIPELINE_EVENTS,stateOf) — проверено, что структуры данных, которые ТЗ просит расширить, действительно в том виде, в каком ТЗ их описывает; - найден и прочитан мутант
process-label-step-combined-again(scripts/mutation-registry.mjs:4085) — AC9 требует, чтобы его якорь (буквальный текст шага «Переставить метку») уцелел после правки К4; подтверждено, что этот текст относится к шагу, который К4 не трогает (К4 меняет «Решение по вердикту», не «Переставить метку»), то есть риск, который называет AC9, реален и ровно там, где его называет ТЗ; - проверено существование всех тестовых файлов, которые план автотестов
называет местом для новых кейсов (
test/process-track.test.mjs,test/review-result-gate.test.mjs,test/review-doc-guard.test.mjs,test/wait-verdict.test.mjs,test/process-digests.test.mjs) и канона (docs/process/AUTHOR.md,docs/process/REVIEWER.md) — все существуют, ссылки не на фантомные файлы.
Находки
Блокирующих (High) и находок в скоупе (Medium) нет.
- Low, снято ревьюером с записью. К1 не уточняет, что происходит на
границе доверия, если
criterionпришёл не строкой (число, объект): явно описан только случайrouteвне словаря. На практике это не меняет поведение — К2 уже относит любойcriterion, не входящий в таблицу из шести идентификаторов (в т.ч. нестроковый после сериализации), к ветке «без критерия из таблицы → какfixсnote», то есть система сходится к безопасному исходу независимо от типа. Технический, не продуктовый вопрос — решает реализатор; спецификацию менять не нужно.
Что проверено и корректно
- Обязательные разделы §7.1 все на месте: сценарий, что человек увидит до/ после, проблема, скоуп/не-скоуп, контракт поведения (К1–К6), раздел UX/данные/i18n/миграция/perf/touch, критерии приёмки с доказательством, план автотестов, риски, откат, release-артефакты.
- Продуктовые открытых вопросов владельцу нет — весь текст помечен как
решаемый технически («Принято предположительно», 6 пунктов) или закрыт
ссылкой на решение владельца из #707/#695/#696. Это ожидаемо для
инфраструктурной/процессной задачи:
docs/SCOPE.mdеё не ограничивает (задача не продуктовая, ни одной строки Core user jobs не касается —AGENTS.mdотносит процессные изменения к отдельной ветке чтения, минуя SCOPE.md). - Таблица критериев К1 (
complexity,surfaces,migration,ux-contract,perf-touch,undocumented) — дословное соответствие шести пунктам «Подсказка аналитику» §5 (PROCESS.md, шесть буллетов), без лишнего и без пропуска. - Таблица маршрутов К2 прогнана вручную по всем строкам AC3:
show/spent 1/fix→spentAfter=2 ≥ limit(show)=2→review-4— сходится; тот же вход сreclassify→limitAfter=cycleLimit(ask)=4,spentAfter=2<4— безreview-4, сходится;ask/spent 3→spentAfter=4≥4— сходится;ask/spent 2→spentAfter=3<4— сходится; зелёный вердикт бюджет не трогает (§4, «зелёный цикла не образует») — сходится. - AC6 (якорь):
anchorVerdictFrom—/Вердикт конвейера:(green|yellow|red)· High (\d+)/без$-якоря — подтверждено чтениемscripts/review-doc-guard.mjs:516, добавление хвоста «· маршрутreclassify(критерийundocumented)» после существующего текста не ломает этот regex: правка описана точно. - Факты из раздела «Проблема» (схема
verdict/high/medium/summaryна_process.yml:1336, безусловный перевод не-зелёного вердикта этапаcodeвS6-in-progressна:1764независимо от причины, проверкаspent -ge limitтолько при входе вS7на:288) — все три подтверждены построчным чтением тех же мест в текущем файле. - Зависимость на #707 не голословна: контракт, который #726 заимствует
(
cycleLimit(track), формат строки владельца, единственный вызовprocess-track.mjsв шаге трека), сверен с телом #707 (строки 106, 109, 112) — совпадает дословно с тем, что #726 называет унаследованным. #707 сейчасS6-in-progress(спека уже зелёная, код не смёржен) — #726 корректно фиксирует это как «послеS8#707», а не как готовую базу; это дисциплинирует порядок работы, а не создаёт скрытую невыполнимость ТЗ. - Test targets существуют и не выдуманы (см. «Как проверялось»).
Чего не проверял
- Гейты
npx tsc --noEmit,npm test,npm run buildне гонял: на этапе spec зависимости и toolchain не ставятся (#696), задача правит только ТЗ/процесс, продуктового кода нет. Материал для code-review ещё не существует — «код» этой задачи появится только послеS5-ready. - Мутанты по диффу не запрашивались (по заголовку задачи) и не применимы: диффа продуктового кода нет, весь диапазон АС проверяется unit-тестами существующих скриптов, а не мутациями продукта.
- Не проверял реализацию (
reviewRoute, обновлённые промпт/шаг_process.yml, новые regexwait-verdict.mjs) — её ещё нет, ТЗ её не содержит, только контракт. Проверено, что контракт для неё достаточен, чтобы писать тест прежде кода (AC1–AC9 у каждого назван oracle и конкретный тестовый файл). - Не проверял актуальность #707 после её собственного код-ревью (что там
не изменится
cycleLimit/строка подтверждения до слияния) — это риск следующего раунда, если #707 смёржится с отличным контрактом; ТЗ #726 прямо предупреждает об этом рисках-разделе («Тело конвейера читается изdevв момент события») и делает ревизию идемпотентной по смыслу (откат — просто revert). - Браузерные смоки, golden, performance,
pytest tests_backend— не применимы: задача не трогаетsrc/**, демо, Python.
Вердикт
Зелёный. ТЗ полно, каждый AC однозначен и назван способ доказательства, факты о текущем поведении конвейера перепроверены чтением и подтвердились, единственная находка — Low, снята ревьюером без правки спецификации.
Материал раунда
- Ветка:
dev, коммит40607aa37f13— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
901e6cbd1964ef2dcd9a0e08e8ec01a5c47dcac7git log --all --format='%H %T' | grep 901e6cbd1964 - Тело issue:
daf13164d67eb2612f80437127463957f152876d86adf9f60eda40d55848ef33 - Вердикт конвейера:
green· High 0