docs: review document for #729

Issue: #729
User-Visible: no
This commit is contained in:
claude[bot]
2026-10-01 05:23:15 +00:00
parent 76558bf2a0
commit 712d41b6d6
2 changed files with 215 additions and 1 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
# Индекс ревью
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 234, issue: 114. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 235, issue: 115. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
| Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы |
|---|---|---|---|---:|---:|---|---|
@@ -14,6 +14,7 @@
| #730 | [CODE-REVIEW-730-r2.md](CODE-REVIEW-730-r2.md) | code · r2 | 🟢 зелёный | 0 | 0 | — | — |
| #730 | [CODE-REVIEW-730-r3.md](CODE-REVIEW-730-r3.md) | code · r3 | 🟢 зелёный | 0 | 0 | — | — |
| #730 | [CODE-REVIEW-730-r4.md](CODE-REVIEW-730-r4.md) | code · r4 | 🟢 зелёный | 0 | 0 | — | — |
| #729 | [SPEC-REVIEW-729-r1.md](SPEC-REVIEW-729-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — |
| #728 | [SPEC-REVIEW-728-r1.md](SPEC-REVIEW-728-r1.md) | spec · r1 | 🟡 жёлтый | 1 | 0 | 1. АС3/К3: заявленное различение причин validate-red и conflict «на текстах из констант…; 2. АС8: заявленное доказательство правки process-metrics.yml (fetch-depth: 0, timeout-m… | `wait-verdict.mjs` `review-doc-guard.mjs` `scripts/wait-verdict.mjs` `.github/workflows/_process.yml` `_process.yml` `_process-metrics.yml` `test/process-metrics.test.mjs` |
| #728 | [SPEC-REVIEW-728-r2.md](SPEC-REVIEW-728-r2.md) | spec · r2 | 🟢 зелёный | 0 | 0 | — | — |
| #728 | [CODE-REVIEW-728-r1.md](CODE-REVIEW-728-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
+213
View File
@@ -0,0 +1,213 @@
# SPEC-REVIEW-729-r1
Issue: #729 «Процесс: черновая реализация ask параллельно ревью ТЗ (изменение
правила №1 — решение владельца)»
Этап: spec (PROCESS.md §2.4) · Трек: ask · Заход: r1 · блокирующих циклов
израсходовано 0 из 4
## Скоуп
ТЗ (тело issue, раздел `## ТЗ`) вводит новое исключение из правила №1: на
`track:ask`, в статусе `S4-spec-review`, автор вправе вести локальный
непушенный черновик продуктового кода (класс A) в рабочей копии, если каждый
черновой коммит несёт трейлер `Spec-Draft: sha256:<хеш нормализованного тела
issue>`. Правило 10 (`checkCommitEraStatuses`, `scripts/process-gate.mjs`)
получает исключение, которое принимает такой коммит только если:
- трек на момент написания коммита — `ask`;
- эпоха `S4`, в которую попадает коммит, закрыта именно `S5-ready`;
- в этой эпохе есть зелёный `SPEC-REVIEW-<NN>-rK.md` (найден в `<head>` или
`origin/dev`) с «Тело issue:», равным трейлеру коммита.
Исключение строится **поверх модели #738** (эпохи статуса для правила 10),
которая на момент ревью ещё не смёржена (`S6-in-progress`) — ТЗ это прямо
называет зависимостью («после `S8` #738») и критически для реализации не
маскирует как решённый факт. Также правятся `scripts/task-packet.mjs` (права
и раздел «Черновик» в пакете на `S4`/`S5`), тесты
(`test/process-gate.test.mjs`, `test/task-packet.test.mjs`,
`test/process-digests.test.mjs`) и канон (PROCESS.md §1, §2.4–2.6, §3 п.1,
§7.2, §9, §10.2, новый §11.8, §12, `docs/process/AUTHOR.md`,
`docs/process/REVIEWER.md`, `AGENTS.md`). Файлов класса A в этой задаче нет —
трек `ask` взят явно (меняет правило №1 и публичный контракт процесса), что
соответствует §5.1. Решение владельца на изменение правила №1 дано в теле
issue текстом «по #729 - разрешаю» (01.10) — ревьюер судит исполнимость и
проверяемость контракта, а не само разрешение, как и требует задание.
## Как проверялось
Раунд первый, документов ревью на #729 в дереве ещё нет — разбор полный.
Метод — не поверить формулировкам «сверено с кодом», а перепроверить каждую
построчную ссылку чтением текущего файла на материале ревью
(`76558bf2a0bf72dcfed369743639c989b4099450`, рабочая копия уже на нём):
- `docs/SCOPE.md`, `AGENTS.md`, `docs/process/REVIEWER.md`, PROCESS.md §1,
§2.3–2.7, §4, §5, §5.1, §7.1, §7.2, §8, §11.7, §12 — целиком по ссылкам
промпта;
- тело issue #729 целиком (раздел `## ТЗ`, все 11 подразделов) и его
единственный комментарий («Оценка… трек ask…», решение владельца);
- статус и зависимости: `gh issue view` для #738 (`S6-in-progress`, не
смёржено — подтверждает, что ТЗ корректно называет его незавершённой
зависимостью, а не фантомной), #707 и #726 (оба `S8-merged`, их контракт
уже в `dev` — трековые метки, формат строки владельца, `trackFromLabels`);
- `3b9f25ea` (SHA, с которым ТЗ сверяет «что сейчас») подтверждён как предок
текущего `HEAD` (`git merge-base --is-ancestor`) и как коммит #727 — ссылка
не мёртвая;
- построчно сверены все ключевые ссылки раздела «Что сейчас (сверено с
кодом)» с текущими файлами:
- `scripts/process-gate.mjs`: `isInfrastructureRange` (строка 407),
`checkCommitEraStatuses` (ровно строки 505–556, включая сигнатуру и
`return out`), использование `statusOptional` и вызов правила 10 только
при `!statusOptional` (строки 778, 788–797) — всё сходится дословно; эта
функция сейчас реализует **старую**, безэпоховую модель (`readyAt` —
первое когда-либо событие допустимого статуса), что ожидаемо: #738 ещё
не смёржен, и ТЗ честно пишет будущий контракт «поверх» неё, а не выдаёт
его за текущее поведение;
- `scripts/review-doc-guard.mjs`: `normalizeIssueBody` (266–273),
`issueBodyDigest` (276–278), `anchorIssueBodyFrom` (281–287),
`issueBodyChanged` (298–308), `materialAnchorBlock` (315…, блок «Тело
issue:» начинается на 335) — сходится;
- `scripts/validate-commit-provenance.mjs`: `TRAILER`-регэксп (строка 9),
`terminalTrailers` (42) — подтверждает заявление «любой трейлер вида
`Имя: значение` в финальном блоке проходит, `Spec-Draft:` не ломает
требование терминального `Issue:`»;
- `scripts/task-packet.mjs`: `rightsFor` (33), `collectInputs` (404),
строки 44 и 52 — ровно те тексты, что цитирует ТЗ («продуктовый код
трогать НЕЛЬЗЯ…», «идёт ревью ТЗ: ждать вердикт…»); чтение ветки и
`reviewDocs` — строки 409–412 (fetch/for-each-ref) и 437–438
(`ls-tree`/`git show` по `docs/reviews`) — сходится;
- `.github/workflows/_process.yml`: снятие хеша тела issue (645–657, блок
`m.issueBodyDigest(`), публикация документа ревью **до** перестановки
метки (шаг «Опубликовать документ ревью» на 1485 действительно идёт
раньше шага «Переставить метку» на 1873; переход `S4→S5` — строка 1736,
в ТЗ названа «:1735», расхождение на одну строку, не искажает факт) —
сходится;
- `scripts/process-track.mjs`: `trackFromLabels` (72–77, дефолт `ask` при
пустом списке меток), `labelTrack` (88, инфраструктура-осведомлённая
обёртка) — ТЗ сознательно берёт `trackFromLabels`, а не `labelTrack`:
это корректно, потому что правило 10 судит только коммиты с файлом
класса A, а такой коммит по определению §1 не принадлежит
инфраструктурному диапазону — защита от «дефолт `show`» здесь не нужна;
- PROCESS.md §5.1: «продуктовая задача без трековой метки — как
`track:ask`» — цитата К3 п.2б «Событий нет → ask» дословно совпадает с
каноном, а не придумана;
- `test/process-gate.test.mjs`: тест `rule 10 pins DoR…` существует
(строка 869, #311), AC #562-стиль прогона с временным git-репозиторием и
подставным `gh` существует (строка 776) — оба ориентира плана автотестов
реальны, не выдуманы;
- `docs/reviews/` сейчас плоский каталог (`SPEC-REVIEW-<NN>-r<K>.md`,
235 файлов, включая существующие `SPEC-REVIEW-651..742`), архив
`legacy/reviews/<тег>/` наполняется только `reviews-archive.mjs` после
стабильного релиза (прочитан целиком) — подтверждает «принято
предположительно» п.5 (документы читаются только из `docs/reviews/` на
`<head>`/`origin/dev`, `legacy/reviews/**` не участвует) и снимает
опасение, что недавние коммиты «индекс после сдвига каталога» (#727,
#730) могли переименовать путь `docs/reviews/SPEC-REVIEW-*` — не
переименовали;
- PROCESS.md §11 — секций 11.1–11.7 ровно семь, 11.8 свободен, коллизии
анкоря заголовка не будет;
- вручную прогнаны все граничные сценарии AC1–AC6 по описанным в ТЗ шкалам
времени (две эпохи `S4`, повтор `S4` reconcile, два зелёных документа в
одной эпохе, эпоха без `S5`, коммит вне `S4`) — результат (findings/
отсутствие findings) в каждом случае соответствует порядку проверок
а→д, который описывает К3 п.2, расхождений не найдено;
- проверено отсутствие файлов класса A в диапазоне (`git diff --stat
3b9f25ea..HEAD -- src/ custom_components/` — пусто), что подтверждает
заявление ТЗ «Файлов класса A нет».
## Находки
Нет. Блокирующих (High) и находок в скоупе (Medium) не обнаружено.
## Что проверено и корректно
- Обязательные разделы §7.1 — полный комплект: сценарий (три персоны:
агент-автор, владелец, ревьюер ТЗ — корректная адаптация для процессной, не
продуктовой задачи), что человек увидит до/после, проблема, скоуп/не-скоуп,
контракт поведения (К1–К5), UX, модель данных и миграция, i18n, критерии
приёмки AC1–AC10 с доказательством и oracle, план автотестов (включая
отдельный блок «чем краснеет»), риски, откат, release-артефакты.
- Каждый AC однозначен и привязан к конкретному тестовому файлу и
конкретному входу/выходу (явные хеши `H`/`H1`/`H2`/`H3`, временные метки,
ожидаемый текст находки) — ни один не сформулирован описательно без
оракула.
- Защитные AC (AC1–AC6 — гард по трейлеру, эпохе, треку, соответствию
документу) имеют явный отрицательный случай либо в столбце
«Доказательство/Oracle» самой таблицы, либо в отдельном перечне «чем
краснеет» — пустого третьего столбца нет ни у одной защитной строки.
- Продуктовых вопросов владельцу нет, и это обоснованно: единственный
продуктовый вопрос задачи — само изменение правила №1 — уже решён
владельцем явной строкой в теле issue («по #729 - разрешаю»), остальное —
технические решения, корректно вынесенные в «Принято предположительно»
(11 пунктов), а не выданные за факт. `docs/SCOPE.md` эту задачу не
ограничивает: она процессная, ни одной строки Core user jobs не касается,
как и соседние #726/#727/#728/#738.
- Зависимость на #738 названа честно и не замаскирована: #738 сейчас
`S6-in-progress` (проверено `gh issue view`), контракт эпох, на который
опирается К3, в коде ещё не существует (`checkCommitEraStatuses` на
текущем HEAD — дочерняя, безэпоховая модель) — ТЗ прямо пишет «DoR #729
требует `S8` у #738» и даёт план на случай расхождения формулировок
(строить поверх фактического кода #738, AC5 держит тесты #738
неизменными). Это дисциплинирует порядок работы, а не создаёт скрытую
невыполнимость спецификации.
- Технический выбор `trackFromLabels` вместо «единой» `labelTrack` в К3 п.2б
корректен по смыслу §1 (коммит класса A не может принадлежать
инфраструктурному диапазону), а не недосмотр совместимости функций.
- Ссылки на существующие тестовые ориентиры (`:776`, `:869` в
`test/process-gate.test.mjs`) и на существующие функции хеша/якоря
(`review-doc-guard.mjs`) реальны, не фантомны.
- Откат описан верно: ревёрт коммита задачи возвращает правило №1 без
исключения; уже прошедшие Validate черновые коммиты границей диапазона
(#703) повторно не судятся — соответствует существующей модели ревью.
## Чего не проверял
- `npx tsc --noEmit`, `npm test`, `npm run build` не гонял: зависимости
(`node_modules`) не установлены — на этапе spec они не ставятся (#696), что
подтверждено (`npm run typecheck` на материале даёт только ошибки
`Cannot find module 'lit'`/`'polyclip-ts'`, то есть отсутствие `npm ci`, а
не дефект кода). У задачи #729 нет диффа продуктового или тестового кода —
ветки `issue/729-*` не существует ни локально, ни на origin, класс A в
диапазоне `3b9f25ea..HEAD` отсутствует (проверено `git diff --stat`) —
гонять эти гейты не над чем.
- Мутанты по диффу не запрашивались (см. заголовок задачи) и не применимы:
диффа продуктового кода нет.
- Смоки, golden, `pytest tests_backend`, инварианты модели, performance — не
применимы: задача не трогает `src/**`, `demo/**`, Python, геометрию.
- Не проверял, останется ли сопоставление «реализатор пишет исключение в
`checkCommitEraStatuses` рядом с кодом #738» дословно жизнеспособным после
фактического код-ревью #738 — это риск следующего раунда (код-ревью #729),
явно признанный в разделе «Риски» ТЗ и ограниченный требованием AC5 «тесты
#738 неизменны».
- Не проверял форматирование трейлера `Spec-Draft` хуком `commit-msg` в
реальном git-хуке (его и не должно быть — К2 прямо говорит, что формат
судит правило 10 при push, а не `commit-msg`) — это заявлено как принятое
предположение, а не как факт текущего кода, и реализация ещё не
существует.
- Не проверял живое поведение `process-gate.mjs --issues` на реальном GitHub
API (сетевой вызов `gh`) — AC1–AC5 рассчитаны на unit-фикстуры с
инъекцией timeline/документов, AC6 — на временный git-репозиторий с
подставным `gh`, как и у #562; живой прогон по плану тестов не требуется
для приёмки ТЗ.
## Вердикт
Зелёный. ТЗ полно по §7.1, каждый AC однозначен и привязан к оракулу,
многочисленные ссылки «сверено с кодом» перепроверены построчным чтением
текущих файлов и подтвердились без расхождений, продуктовый вопрос (само
изменение правила №1) уже решён владельцем, остальные решения корректно
зафиксированы как технические допущения. Зависимость на не смёрженный #738
названа прямо и не выдаётся за готовую базу. Находок нет.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `dev`, коммит `76558bf2a0bf` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `e4d6aac31897c3f952332ec219cff7fbd5e9c793`
```
git log --all --format='%H %T' | grep e4d6aac31897
```
- Тело issue: `94cd1bca3f851c8c9d9fc64b3b6227fb2fd3dac9f47715053a95dd133ae40bed`
- Вердикт конвейера: `green` · High 0 · маршрут `fix`