Files
houseplan-card/docs/reviews/SPEC-REVIEW-511-r2.md
T
2026-09-09 14:27:52 +00:00

15 KiB
Raw Blame History

SPEC-REVIEW-511-r2

  • Issue: #511 — «release-gate: судить по последнему завершённому прогону на SHA, отменённые не блокируют»
  • Этап: ТЗ на ревью (PROCESS.md §2.4), лёгкий трек (small)
  • Заход: r2 · блокирующих циклов израсходовано 1 из 2 (этот раунд — зелёный, бюджет не тратится, #227)
  • Вердикт: зелёный

Скоуп раунда и объявление дельты

Предыдущий вердикт — r1, жёлтый, документ docs/reviews/SPEC-REVIEW-511-r1.md, опубликован коммитом 6842b69e (текущий HEAD, дерево между раундами не менялось вовсе — задача лёгкого трека, ТЗ живёт в теле issue, кода ещё нет). Материал раунда r1 сам называл SHA пустым («ребейз его осиротит» — якорь не резолвился, ветки задачи не было, читали по dev); в r2 сверка проще: между раундами не было ни одного коммита, только правка тела issue.

Дельта объявлена через историю правок issue (userContentEdits GraphQL, единственный способ увидеть точный до/после тела issue, раз обычный git diff тут неприменим — ТЗ не файл). Правка сделана 2026-09-09T14:20:49Z, через 17 секунд после публикации вердикта r1 (14:20:32Z). Точный diff:

- AC3. `docs/performance/README.md`/`docs/TESTING.md` — одна фраза о семантике «последний завершённый».
+ AC3. `docs/DEVELOPMENT.md` (канонический документ релиза; строка «A missing, failed, cancelled or one-hour-timed-out Validate withholds the asset» становится неверной) описывает новую семантику: «последний завершённый прогон, `cancelled` не считаются»; `demo/performance/README.md` — та же фраза рядом с требованием Full Performance для stable. Доказательство AC2 — `release.yml` без диффа; доказательство AC3 — grep этих фраз в тесте `release-gate.test`.
+
+ ## Откат
+
+ Revert одного коммита; данных и форматов нет.

«Проблема», «Решение владельца», AC1, AC2 — байт в байт без изменений. Дельта локальна по всем критериям §2.10: не ребейз, не смена контракта поведения, не новая подсистема, объём — одна строка AC плюс один трёхстрочный раздел. Разбор ограничен дельтой; AC1/AC2 наследуются из r1 без повторного вывода алгоритма.

Закрытие раунда r1

Находка r1 Чем закрыта Где это видно
Medium — AC3 указывал на несуществующий docs/performance/README.md и топически неподходящий docs/TESTING.md; реальная строка docs/DEVELOPMENT.md:360 не была названа AC3 переписан: целевой файл — docs/DEVELOPMENT.md, с точной цитатой строки, которая станет неверной; docs/performance/README.md/docs/TESTING.md убраны Тело issue #511, раздел AC, пункт AC3 (см. diff выше); подтверждено чтением docs/DEVELOPMENT.md:359-360 — цитата совпадает дословно (перенос строки в исходнике не меняет фразу)
Low 1 — раздел «откат» отсутствовал в теле issue дословно Раздел ## Откат добавлен в тело: «Revert одного коммита; данных и форматов нет» Тело issue #511, последний раздел
Low 2 — AC2/AC3 не называли явно способ доказательства Дописано прямым текстом: «Доказательство AC2 — release.yml без диффа; доказательство AC3 — grep этих фраз в тесте release-gate.test» Тело issue #511, конец пункта AC3

Все три находки r1 закрыты содержательно, не декларативно — по каждой указана конкретная строка текста, а не заявление автора.

Унаследовано из r1

Без повторной проверки принято из docs/reviews/SPEC-REVIEW-511-r1.md (материал: dev, документ опубликован коммитом 6842b69e, тем же, что и текущий HEAD, — дерево кода между раундами идентично):

  • AC1 полностью и однозначно описывает алгоритм: cancelled исключаются целиком, из оставшихся берётся хронологически последний (run_started_at/created_at); все шесть пар вход/выход в тексте взаимно непротиворечивы. Текст AC1 не менялся дельтой — переверять нечего.
  • AC2 структурно подтверждён чтением release.yml (оба вызова release-gate.mjs идут через общую classifyValidateRuns, третьего места с отдельной логикой нет). Текст AC2 не менялся дельтой.
  • Продуктовая рамка: задача не расширяет скоуп, не трогает src/**, не создаёт новый UX-контракт, User-Visible: no подразумевается верно.
  • Отсутствие догадок, выданных за решение: «Решение владельца» — прямая цитата ретроспективы 09.09, п.5, алгоритм AC1 полностью выводится из неё.
  • Продуктовых вопросов владельцу не требуется — весь материал технический.
  • Трек small выбран корректно (одна поверхность класса B — scripts/** + test/**, риск 2/10, нет конфига/i18n/перфа/touch).

Что проверено заново в этом раунде

  • Цитата в AC3 для docs/DEVELOPMENT.md. Прочитан файл, строки 359–360: «A missing, failed, cancelled or one-hour-timed-out Validate withholds the asset» — фраза реальна, совпадает с цитатой в AC3 дословно (в источнике перенесена по мягкому переносу markdown между «failed,» и «cancelled», это не меняет содержание). grep -n подтверждает построчно (359, 360).
  • Путь demo/performance/README.md. Файл существует (ls demo/performand/README.md → есть), в отличие от использованного в r1 ошибочного docs/performance/README.md (docs/performance/ не существует вовсе — перепроверено ls docs/performance → «No such file or directory»). Так что сама подмена пути — реальное исправление, не косметика.
  • Смысл «та же фраза» для demo/performance/README.md. Проверил построчно (grep -n -i "exact-SHA|stable release|withhold|asset") — в этом файле нет существующей фразы вида «A missing, failed, cancelled...», которая «становится неверной»; единственное релевантное место — строки 122–124 («Stable release assets require both exact-SHA Validate and exact-SHA Full Performance»), и это утверждение остаётся истинным после AC1 (требование «нужен зелёный Validate» не меняется, меняется только то, как это «зелёный» вычисляется). Прочитав AC3 целиком («описывает новую семантику: «последний завершённый прогон, cancelled не считаются»; … та же фраза…»), нахожу более естественным прочтение «та же фраза» = та же новая поясняющая фраза, добавляемая в оба файла, а не тождественная старая формулировка, которую надо «исправить» во втором файле (там исправлять нечего — искажённого утверждения там сейчас нет). Это не единственно возможное прочтение, но при этом чтении AC3 однозначно выполнимо и проверяемо (grep новой фразы в обоих файлах), а неоднозначность — не о продукте (не «что видит пользователь», а «в какой документ разработки идёт вспомогательное предложение») и не годится для эскалации владельцу по правилу §7.1. Не блокирую: пограничная формулировка, а не фактическая ошибка или неисполнимость — граница между «дефект» и «стилистика», по-моему, здесь пройдена в пользу автора, потому что оба чтения ведут к одному и тому же безопасному действию разработчика (добавить/поправить одну поясняющую фразу в названном месте) и к проверяемому тесту.
  • Тест-цель release-gate.test. test/release-gate.test.mjs существует уже сегодня (класс B, правится в этой же задаче), текущие тесты (release gate fails closed for red, cancelled and skipped runs, one red duplicate blocks a green duplicate for the same SHA) кодируют именно старую семантику, которую AC1 переворачивает, — подтверждает, что задача не вакуумна и есть что менять и проверять. Новых assert'ов на grep docs-файлов в тесте пока нет (ожидаемо — реализации ещё нет), но добавление такого теста ничем не блокировано: docs/DEVELOPMENT.md и demo/performance/README.md — обычные текстовые файлы, readFileSync + includes тривиален.
  • Раздел «Откат». «Revert одного коммита; данных и форматов нет» — точно для скоупа (правка одного CI-скрипта, одного теста и двух документационных файлов, без миграций, без хранимого состояния, без config-полей). Проверено чтением, не исполнением (откатывать нечего — кода ещё нет).

Чего не проверял

  • Продуктовые команды (typecheck/test/build) не гонял — на этапе ТЗ кода нет, гонять нечего (наследуется из r1, ситуация не изменилась).
  • Историческую точность инцидента 09.09 (конкретные ID прогонов) — факт прошлого CI, не проверяемый чтением репозитория; для ревью ТЗ достаточно, что баг воспроизводится логикой текущего classifyValidateRuns (принято в r1, дельта этого не касалась).
  • Не открывал docs/CHANGELOG.md/.ru.md — User-Visible: no, оба changelog не требуются (наследуется из r1).
  • Не проверял, действительно ли задача подходила бы под инфраструктурный обход без спецификации (AGENTS.md, «ни одного файла класса A» — она бы подошла, scripts/** + test/** только класс B). Это выбор автора/ аналитика идти полным лёгким треком, а не нарушение процесса — необязателен к проверке ревьюером ТЗ.

Итог

Все три находки r1 (1 Medium, 2 Low) закрыты конкретным текстом, не заявлением. Дополнительная проверка второй половины переписанного AC3 (demo/performance/README.md) не вскрыла блокирующего дефекта — формулировка пограничная, но исполнима и проверяема при разумном прочтении, последствия обеих трактовок безопасны и совпадают в действии. High-находок нет, новых Medium/Low не заводится. AC1/AC2 наследуются из r1 без повторной проверки алгоритма — дельта их не касалась. Вердикт — зелёный; переход в S5-ready.


Материал раунда

  • Ветка/дерево: dev, коммит 6842b69eed1a6530d7475f4427132b4a1b501e49 (код не менялся с r1; дельта — только тело issue).
  • Материал ТЗ: тело issue #511 на момент вывода вердикта; правка зафиксирована userContentEdits (GraphQL), editedAt: 2026-09-09T14:20:49Z, editor Matysh.
  • Вердикт: green · High 0 · Medium 0

Материал раунда

  • Ветка: dev, коммит `` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Якоря снять не удалось: ветки задачи нет, материал читался по dev.
  • Вердикт конвейера: green · High 0