docs: review document for #511

Issue: #511
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-09 14:27:52 +00:00
parent 6842b69eed
commit 590b3a7e67
+165
View File
@@ -0,0 +1,165 @@
# 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:
```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`.
---
<!-- material-anchors: заполняется конвейером -->
## Материал раунда
- Ветка/дерево: `dev`, коммит `6842b69eed1a6530d7475f4427132b4a1b501e49` (код не менялся с r1; дельта — только тело issue).
- Материал ТЗ: тело issue #511 на момент вывода вердикта; правка зафиксирована `userContentEdits` (GraphQL), `editedAt: 2026-09-09T14:20:49Z`, editor `Matysh`.
- Вердикт: `green` · High 0 · Medium 0
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Якоря снять не удалось: ветки задачи нет, материал читался по `dev`.
- Вердикт конвейера: `green` · High 0