av-dev-pipeline: починены находки ревью, бриф заводится скиллом

- скилл project-brief: бриф собирается из CLAUDE.md, архитектуры, Taskfile
  и конвенций и показывается человеку. Раньше единственная инструкция по
  его созданию лежала внутри шаблона, поэтому деградированный режим был не
  аварийным, а единственным: critical по основанию «нарушен инвариант»
  недостижим ни на одной задаче
- rebase перенесён внутрь worktree задачи: прежняя форма падала на занятой
  ветке, и агент уводил весь батч в провалившиеся с ложной причиной
- контракт брифа дополнен восемью слотами; проверен заполнением на обоих
  проектах, незаполнимых нет. Прецедент healthlog вынут из общего charter'а
  в бриф — там он вмёрз вместе с числами
- шов: пайплайн задачу не закрывает и записи учёта не трогает, урожай
  отдаёт списком, правило остатка — ссылкой на av-dev-tasks
- деградированный абзац во всех девяти проходах, вопрос 9 в ops,
  пространство имён в вызовах, раздел предпосылок
This commit is contained in:
av
2026-08-03 11:45:40 +03:00
parent 20dca29add
commit 0eca206460
18 changed files with 1021 additions and 214 deletions
+65 -27
View File
@@ -29,28 +29,61 @@ description: Конвейер ревью изменения — детермин
обнаружено» потребляет ощущение проверенности, ничего не гарантируя. Секция
границ покрытия обязательна и не сокращается — в том числе в докладе человеку.
## Предпосылки
Конвейер опирается на внешнюю обвязку и без неё работает не целиком. Проверь это
один раз, при установке плагина в проект:
- **OpenSpec и скиллы `opsx:*`.** Профиль `design`, проход `review-specs` и
вызывающий пайплайн задачи завязаны на дельта-спеки
(`openspec/changes/<id>/specs/*/spec.md`), на актуальные спеки
(`openspec/specs/`) и на `openspec validate --strict`. В проекте без OpenSpec
шаги, зовущие `opsx:explore` / `opsx:propose` / `opsx:apply` / `opsx:archive`,
упадут на «нет такого скилла», а `review-specs` останется без источника
требований. Такой проект либо подключает OpenSpec, либо сознательно не зовёт
`review-specs` и профиль `design` — и тогда это идёт строкой «не запускался» в
границы покрытия, как любой другой пропуск.
- **Бриф проекта** — см. следующий раздел. Заводится скиллом, а не руками.
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
проекте уже лежат свои `.claude/skills/review-pipeline`,
`.claude/skills/task-pipeline`, `.claude/skills/task-batch` или
`.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится
в устаревшую проектную копию, молча и без признаков подмены. По той же причине
**скиллы этого плагина зовутся с пространством имён**:
`av-dev-pipeline:review-pipeline`, `av-dev-pipeline:task-pipeline`,
`av-dev-pipeline:task-batch`, `av-dev-pipeline:project-brief`.
## Что конвейер защищает — приходит из брифа
Проходы общие, а нарушать нельзя проектное. Список инвариантов, команду гейта,
объёмы и модель угроз конвейер **не знает** — он читает их в брифе проекта:
[references/project-brief.md](references/project-brief.md) описывает контракт,
[references/brief-template.md](references/brief-template.md) — образец
объёмы, прецеденты и модель угроз конвейер **не знает** — он читает их в брифе
проекта: [references/project-brief.md](references/project-brief.md) описывает
контракт, [references/brief-template.md](references/brief-template.md) — образец
заполнения.
Разреши путь к брифу один раз, в начале прогона: путь из задания →
`docs/review-brief.md``.claude/review-brief.md`. Дальше передавай готовым.
**Брифа нет — прогон идёт в деградированном режиме**: `critical` по основанию
«нарушен инвариант проекта» никем не присваивается, числа объёма не
используются, и в границы покрытия уезжает строка «брифа проекта нет». Это дыра
покрытия, а не нейтральное умолчание.
**Брифа нет по всем трём путям — заведи его, а не понижай прогон.** Вызови Skill
**`av-dev-pipeline:project-brief`**: он соберёт бриф из `CLAUDE.md`, архитектуры,
файла задач и конвенций, покажет человеку и вернёт путь. Это механика, а не
развилка: спрашивать разрешения не нужно, и остановка прогона тут не
предусмотрена. Заведение стоит одного шага один раз на проект — деградированный
режим платит на каждой задаче.
**Деградированный режим — исход, а не умолчание.** Он включается ровно тогда,
когда бриф завести не удалось (репозиторий на чтение, человек прямо запретил,
инварианты вывести неоткуда): `critical` по основанию «нарушен инвариант
проекта» никем не присваивается, числа объёма не используются, и в границы
покрытия уезжает строка «брифа проекта нет, завести не удалось: <причина>».
Причина обязательна — без неё строка неотличима от «мы просто не стали».
## Что получает каждый проход
Задание любому проходу состоит из шести вещей, и первые две без брифа
бессмысленны:
Задание любому проходу состоит из шести вещей, и первая — главная: без брифа
проход теряет предмет проверки и уходит в деградированный режим.
- **бриф** — путь;
- **бриф** — путь (разрешён или заведён на старте, см. выше);
- **контракт находок** — путь к
[references/finding-contract.md](references/finding-contract.md) (в
установленном плагине — `${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/`);
@@ -170,14 +203,14 @@ description: Конвейер ревью изменения — детермин
Почему умолчание именно такое:
- **Замеры.** Проходы `adversary` и `ops` доказывают находки числами: время
удержания блокировки, пик кучи, рост файлов журнала, длительность транзакции.
Два меряющих прохода на одной машине соревнуются за диск, CPU и за саму СУБД и
выдают числа, которые не воспроизведутся. Это не гипотеза: находки, ради
которых правило записано, опираются ровно на такие замеры (5.019 с удержания
блокировки при таймауте 5000 мс, пик 768 МиБ на теле 40 МиБ, 7 МБ/с роста
журнала, 1492 тика из 5502). Число, снятое под конкурентную нагрузку от
соседнего прохода, — это находка с испорченным оракулом, а её опровержение
стоит дороже всего выигрыша от параллельности.
удержания блокировки против её таймаута, пик кучи против размера тела, темп
роста файлов журнала, длительность транзакции. Два меряющих прохода на одной
машине соревнуются за диск, CPU и за саму СУБД и выдают числа, которые не
воспроизведутся. Это не гипотеза: правило выведено из находок, целиком
державшихся на таких замерах, — у каждого проекта они свои и лежат в разделе
`## Прецеденты` его брифа. Число, снятое под конкурентную нагрузку от соседнего
прохода, — это находка с испорченным оракулом, а её опровержение стоит дороже
всего выигрыша от параллельности.
- **Машина одна.** Рядом идёт задача, поднят сервис, гоняется гейт или дорогая
проверка проекта.
- **Ранний выход** возможен только при последовательном прогоне (см. ниже).
@@ -205,9 +238,9 @@ description: Конвейер ревью изменения — детермин
нулевой стадии** — а не «доезжает» остатком по старому коду;
- незапущенные проходы идут в границы покрытия строкой «не запускался: прогон
остановлен на <проход> из-за <находка>», поимённо;
- триаж запускается только на полном прогоне. Отчёт триажа по половине проходов
ровно тот случай, который уже стоил семи находок: он выглядит полным, потому
что агрегирует всё, что ему подали.
- триаж запускается только на полном прогоне. Отчёт триажа по половине проходов
выглядит полным, потому что агрегирует всё, что ему подали, — это тот же
молчащий пропуск, что и в разделе «Профили».
Ранний выход по находке, которая чинится в пределах существующей формы
(`Действие: инлайн`), **не делается**: дешевле дособрать все находки и починить
@@ -246,8 +279,9 @@ description: Конвейер ревью изменения — детермин
- `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не
из proposal, сообщения коммита или описания задачи. Сверка двунаправленная;
направление `code → spec` важнее.
- `review-code` — критерий взят из файла конвенций проекта (раздел `## Карта`
брифа), и только та его часть, которая **не выражается правилом**:
- `review-code` — критерий взят из конвенций проекта: файла или каталога файлов,
путь — раздел `## Карта` брифа. Берётся только та их часть, которая **не
выражается правилом**:
механизируемое уже проверила стадия 0. Что именно механизировано, тот же раздел
брифа перечисляет — повторять это проходом вредно.
@@ -322,7 +356,8 @@ Recall обоих равен длине их источника — это и е
## Профиль `design` — до кода
Запускается на шаге ревью спек (шаг 4 скилла `task-pipeline`), когда change уже
Запускается на шаге ревью спек (шаг 4 скилла `av-dev-pipeline:task-pipeline`),
когда change уже
имеет `proposal.md` и дельта-спеки, но кода ещё нет. Состав:
1. `review-specs` в режиме «дизайн ДО кода»;
@@ -359,9 +394,11 @@ Recall обоих равен длине их источника — это и е
держит вопросы (это знает вызвавший пайплайн, а не конвейер). Оркестратор не
останавливается: он урезает изменение до остатка и доводит его.
- Находка не для этого мерджа, но реальная (отложенный `major`, развилка,
решённая «потом») — не теряется: заводится задачей средствами проекта, с
оракулом и провенансом в теле. Мелочь класса `nit` — пачкой, а не записью на
находку.
решённая «потом»), — не теряется, но **и не заводится здесь**. Конвейер отдаёт
её **списком урожая** в отчёте: формулировка, оракул, провенанс (какой проход,
какой change). Заведение задач принадлежит тому, кто ведёт задачи проекта, —
у него свой формат, своя нарезка и свои правила дублей. Мелочь класса `nit`
идёт в урожай одной пачкой, а не записью на находку.
- `Promote candidates` — по процедуре [references/promote.md](references/promote.md):
находка → конвенция → правило линтера → **удаление из конвенций и из брифа**.
Третий шаг обязателен.
@@ -405,6 +442,7 @@ Recall обоих равен длине их источника — это и е
## Ссылки
- Skill `av-dev-pipeline:project-brief` — заведение и обновление брифа.
- [references/project-brief.md](references/project-brief.md) — контракт брифа проекта.
- [references/brief-template.md](references/brief-template.md) — шаблон брифа.
- [references/finding-contract.md](references/finding-contract.md) — контракт находок.