diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 21296f5..f158892 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -18,7 +18,7 @@
{
"name": "av-dev-pipeline",
"source": "./av-dev-pipeline",
- "description": "Проведение задачи через цикл SDD и конвейер ревью с обязательным триажем, плюс прогон нескольких задач разом. Требует OpenSpec. Задача принимается и обычным текстом; плагины av-dev-docs и av-dev-tasks опциональны — первый даёт документы канона для проходов ревью, второй учёт задач, без них прогон деградирует поразрядно и говорит об этом."
+ "description": "Проведение задачи через цикл SDD и конвейер ревью с обязательным триажем. Требует OpenSpec. Задача принимается и обычным текстом; плагины av-dev-docs и av-dev-tasks опциональны — первый даёт документы канона для проходов ревью, второй учёт задач, без них прогон деградирует поразрядно и говорит об этом."
},
{
"name": "av-dev-git",
diff --git a/README.md b/README.md
index 134d41b..a989a22 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,6 @@
инструмента). Каталог принадлежит конвейеру, а не канону: без конвейера он
проекту не нужен, и `docs.py` о нём молчит;
- `task-pipeline` — задача через полный цикл SDD, от постановки до коммита;
- - `task-batch` — несколько задач разом, каждая в своём worktree;
- `review-pipeline` — конвейер ревью **по темам**: документ проекта либо
заводит тему проверки, либо питает чужую тему источником, либо процессный и в
ревью не читается вовсе. Разметка идёт **один раз на задачу**, сразу после
@@ -55,9 +54,7 @@
flowchart TB
subgraph pipe["av-dev-pipeline — исполнение, требует OpenSpec"]
direction LR
- batch["task-batch"] --> tp["task-pipeline"]
- tp --> rp["review-pipeline
10 агентов-проходов"]
- batch --> rp
+ tp["task-pipeline"] --> rp["review-pipeline
10 агентов-проходов"]
osp["openspec
заводит и проверяет openspec/"]
end
subgraph docsp["av-dev-docs — документация, владеет docs/"]
@@ -160,7 +157,7 @@ claude plugin install av-dev-git@av-dev-skills --scope project
```
**При установке в проект, где лежали проектные копии** скиллов и агентов
-(`.claude/skills/` — голые `task-pipeline`, `review-pipeline`, `task-batch`
+(`.claude/skills/` — голые `task-pipeline`, `review-pipeline`
и с префиксом проекта `<проект>-task-pipeline`,
`.claude/agents/<проект>-review-*.md`) — снеси их. Две копии одного скилла
расходятся, и побеждает та, что короче названа.
diff --git a/REMAINING.md b/REMAINING.md
index 38ed191..16a69ab 100644
--- a/REMAINING.md
+++ b/REMAINING.md
@@ -57,7 +57,7 @@ severity. Пробы готовы и синтетических не нужно
установке каждого плагина в одиночку.
- **Проектные копии в healthlog и jellybit.** Два `.claude/skills/` и одиннадцать
`.claude/agents/` старого поколения. У jellybit хуже: его скиллы названы
- `task-pipeline`, `review-pipeline`, `task-batch` — **ровно как в плагине**.
+ `task-pipeline`, `review-pipeline` — **ровно как в плагине**.
Claude Code не переопределяет их, а держит обе пары, так что короткое имя может
увести в устаревшую копию, и молча.
diff --git a/TODO.md b/TODO.md
index 9523083..4397f9e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -56,7 +56,7 @@
- [ ] то же, что у healthlog: плагины, проектные копии, `adopt`, каталог задач,
гейт
- [ ] проектные копии здесь опаснее: скиллы названы `task-pipeline`,
- `review-pipeline`, `task-batch` — **ровно как в плагине**, и короткое имя
+ `review-pipeline` — **ровно как в плагине**, и короткое имя
может увести в устаревшую копию молча (REMAINING)
## 2. Учёт работ без спринтов
diff --git a/av-dev-docs/agents/doc-code-drift.md b/av-dev-docs/agents/doc-code-drift.md
index 68616a5..54b87db 100644
--- a/av-dev-docs/agents/doc-code-drift.md
+++ b/av-dev-docs/agents/doc-code-drift.md
@@ -50,7 +50,7 @@ color: green
проверить, — это **не находка, а строка в границах покрытия**.
1. **Имя основной ветки** (`CLAUDE.md`). От неё считается база диффа
- (`git merge-base HEAD <ветка>`), в неё вливает батч, от неё ветвятся задачи.
+ (`git merge-base HEAD <ветка>`), в неё коммитит работу конвейер.
Проверка: `git symbolic-ref refs/remotes/origin/HEAD` либо перечень веток.
Угадывание между `master` и `main` ломает интеграцию целиком, и это самая
дешёвая находка из всех.
diff --git a/av-dev-docs/skills/canon/references/canon.md b/av-dev-docs/skills/canon/references/canon.md
index 794fc14..3e124ed 100644
--- a/av-dev-docs/skills/canon/references/canon.md
+++ b/av-dev-docs/skills/canon/references/canon.md
@@ -415,7 +415,7 @@ kebab-case.** Причина не эстетическая: имя файла с
Плюс то, что нужно git-операциям и проходам и не выводится ниоткуда:
- **имя основной ветки** — от неё считается база диффа
- (`git merge-base HEAD <ветка>`), в неё вливает батч, от неё ветвятся задачи.
+ (`git merge-base HEAD <ветка>`), в неё коммитит работу конвейер.
Угадывание между `master` и `main` ломает интеграцию целиком;
- **что запускать запрещено, с путями** — рабочая БД, боевой каталог данных,
внешние сервисы. Запретом с путями, а не «будь осторожен»;
diff --git a/av-dev-pipeline/.claude-plugin/plugin.json b/av-dev-pipeline/.claude-plugin/plugin.json
index c228604..21c9b2b 100644
--- a/av-dev-pipeline/.claude-plugin/plugin.json
+++ b/av-dev-pipeline/.claude-plugin/plugin.json
@@ -1,6 +1,6 @@
{
"name": "av-dev-pipeline",
- "description": "Проведение задачи через полный цикл Spec Driven Development и конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом, независимой реализацией и обязательным триажем; плюс прогон нескольких задач разом по одной в изолированном worktree. Требует OpenSpec и сам его заводит скиллом openspec. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.",
+ "description": "Проведение задачи через полный цикл Spec Driven Development и конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом, независимой реализацией и обязательным триажем. Требует OpenSpec и сам его заводит скиллом openspec. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.",
"author": {
"name": "Anton Vakhrushev",
"email": "anwinged@gmail.com"
diff --git a/av-dev-pipeline/agents/review-specs.md b/av-dev-pipeline/agents/review-specs.md
index 9d9c6cf..a62fb01 100644
--- a/av-dev-pipeline/agents/review-specs.md
+++ b/av-dev-pipeline/agents/review-specs.md
@@ -1,6 +1,6 @@
---
name: review-specs
-description: "Сверка изменения с дельта-спеками в обе стороны — spec→code (каждое требование реализовано и подтверждено тестом) и, что важнее, code→spec (поведение, которое код имеет, а спека не заказывала: тихие ветки, самодеятельные дефолты, проглоченные ошибки, отброшенные поля, ретраи «на всякий случай»). Плюс границы спеки — что она не определяет и что пришлось домыслить. Работает в трёх режимах: дизайн/спеки ДО кода, код против спек ПОСЛЕ apply и стык после слияния нескольких задач, когда change уже заархивированы. Только чтение."
+description: "Сверка изменения с дельта-спеками в обе стороны — spec→code (каждое требование реализовано и подтверждено тестом) и, что важнее, code→spec (поведение, которое код имеет, а спека не заказывала: тихие ветки, самодеятельные дефолты, проглоченные ошибки, отброшенные поля, ретраи «на всякий случай»). Плюс границы спеки — что она не определяет и что пришлось домыслить. Работает в двух режимах: дизайн/спеки ДО кода и код против спек ПОСЛЕ apply. Только чтение."
tools: Read, Grep, Glob, Bash
model: opus
color: yellow
@@ -63,11 +63,9 @@ Development на OpenSpec). Оптика — требования, а не ст
намерение, а спека нормирует. Расхождение между proposal и дельтой — само по себе
находка.
-**Исключение — режим 3 (ниже): живого change нет.** Тогда источник требований —
-**актуальные** `openspec/specs//spec.md`, а дельты поднимаются из
-архива (`openspec/changes/archive//specs/`) как свидетельство о намерении
-каждой слитой задачи. Задание обязано назвать этот режим явно; не названо —
-работаешь по режиму 1 или 2 и говоришь в границах покрытия, что change не нашёл.
+**Живого change нет — ты не запускаешься.** Оба режима стоят на дельта-спеке; без
+неё сверять нечего, и это строка отказа, а не повод взять источником актуальные
+спеки: они описывают, что система делает вообще, а не что заказало это изменение.
Дополнительно поднимаешь **с метки `medium`**: `design.md` и `tasks.md`
change, затронутые актуальные спеки. Инварианты из `CLAUDE.md` — при любой метке. Если тема ещё не перенесена в спеки и живёт только в
@@ -144,27 +142,6 @@ change, затронутые актуальные спеки. Инвариант
скажи об этом прямо, с последствием. Такая находка всегда `Действие: развилка`:
менять спеку — решение человека.
-## Режим 3 — стык после слияния нескольких задач
-
-Зовётся финальной сверкой `task-batch`: несколько задач влиты в основную ветку,
-их change **уже заархивированы**, живой дельта-спеки не существует. Предмет —
-**только то, что появилось от слияния**, а не capability целиком заново: каждая
-задача уже проверена в своём worktree, и повторение даст те же находки дороже.
-
-Ищешь ровно три вещи:
-
-- **отменённое требование** — одна задача его выполнила, соседняя незаметно
- сняла; в актуальной спеке требование есть, в интегрированном коде его больше
- нет;
-- **два описания одного поведения** — два архивных change по-разному нормировали
- одно и то же, и актуальная спека собрала из них противоречие;
-- **осиротевшее поведение** — код, пришедший от слияния (разрешение конфликта,
- правка при rebase), которого не заказывал ни один из change.
-
-База — интегрированный дифф основной ветки против точки, с которой батч начался.
-В границах покрытия скажи прямо: **capability целиком в этом режиме не
-сверялась**, проверялись стыки.
-
## Чего этот проход принципиально не может поймать
- Качество формы решения: код может точно соответствовать спеке и быть плохим.
diff --git a/av-dev-pipeline/agents/review-triage.md b/av-dev-pipeline/agents/review-triage.md
index a12c556..5753c2f 100644
--- a/av-dev-pipeline/agents/review-triage.md
+++ b/av-dev-pipeline/agents/review-triage.md
@@ -29,12 +29,10 @@ color: yellow
и метка с обоснованием. Он твой главный инструмент сверки: ты единственный, кто
видит и то, что размечено, и то, что пришло.
-**Плана нет — ты не запускаешься.** Сверка размеченного с пришедшим — твоя
-единственная защита от молчащего пропуска, и без плана она не выполняется вовсе.
-Отчёт, собранный без неё, выглядит полным ровно настолько же, насколько и
-неполный. Исключение одно и объявленное: финальная сверка стыка в
-`av-dev-pipeline:task-batch` — там разметчика нет по построению, и план тебе
-собирает сам батч, коротким списком запущенного.
+**Плана нет — ты не запускаешься, и исключений нет.** Сверка размеченного с
+пришедшим — твоя единственная защита от молчащего пропуска, и без плана она не
+выполняется вовсе. Отчёт, собранный без неё, выглядит полным ровно настолько же,
+насколько и неполный.
Из документов проекта тебе нужны:
diff --git a/av-dev-pipeline/skills/review-pipeline/SKILL.md b/av-dev-pipeline/skills/review-pipeline/SKILL.md
index 6fa2645..48dfca5 100644
--- a/av-dev-pipeline/skills/review-pipeline/SKILL.md
+++ b/av-dev-pipeline/skills/review-pipeline/SKILL.md
@@ -1,6 +1,6 @@
---
name: review-pipeline
-description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после propose: агент review-scope выводит размер и сложность, из их максимума — метка, и раздаёт темы проходам обеих стадий. Метка правит и ревью дизайна (small — только specs; medium — плюс rubric; large — плюс architecture), и ревью кода (small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе). Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона av-dev-docs. Вызывается из task-pipeline (чекпоинты ревью) и из task-batch (финальная сверка)."
+description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после propose: агент review-scope выводит размер и сложность, из их максимума — метка, и раздаёт темы проходам обеих стадий. Метка правит и ревью дизайна (small — только specs; medium — плюс rubric; large — плюс architecture), и ревью кода (small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе). Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона av-dev-docs. Вызывается из скилла resolve — двумя чекпоинтами: ревью дизайна до кода и ревью кода после apply."
---
# Конвейер ревью
@@ -58,7 +58,7 @@ description: "Конвейер ревью изменения, устроенны
- **Документы канона** — см. следующий раздел.
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
проекте уже лежат свои `.claude/skills/review-pipeline`,
- `.claude/skills/task-pipeline`, `.claude/skills/task-batch` или
+ `.claude/skills/task-pipeline`, `.claude/skills/resolve` или
`.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится
в устаревшую проектную копию, молча и без признаков подмены.
@@ -94,8 +94,8 @@ description: "Конвейер ревью изменения, устроенны
Своих скиллов это касается ровно так же: `av-dev-pipeline:review-pipeline`,
-`av-dev-pipeline:task-pipeline`, `av-dev-pipeline:task-batch` — подменяется
-короткое имя, а не чужое.
+`av-dev-pipeline:resolve`, `av-dev-pipeline:openspec` — подменяется короткое имя,
+а не чужое.
## Темы, источники и процессные документы
@@ -560,8 +560,7 @@ flowchart TD
ничего не портит, он только дольше, и домысливать тут нечего;
2. **машина занята, и знает об этом вызывающий.** Рядом идёт другая задача,
поднят сервис, гоняется дорогая проверка проекта. Сам конвейер занятости
- машины не видит — её обязан назвать тот, кто запускает; так и делает
- `av-dev-pipeline:task-batch`, когда ведёт задачи параллельно;
+ машины не видит — её обязан назвать тот, кто запускает;
3. **разбор самого конвейера** — когда выясняется, почему проход чего-то не
нашёл, порядок и изоляция важнее скорости.
@@ -956,8 +955,8 @@ flowchart TD
Он единственное, по чему потом видно, что было найдено и что из этого не
заведено: нулевой урожай при непустом отчёте виден сразу.
**Вместе с изменением он и переезжает:** после `opsx:archive` его адрес —
- `openspec/changes/archive//review/`. Кто ищет отчёт после архивации (батч
- на финальной сверке, приёмщик на сессии), смотрит **оба** пути; «отчёта нет»
+ `openspec/changes/archive//review/`. Кто ищет отчёт после архивации
+ (приёмщик на сессии, разбор дефекта), смотрит **оба** пути; «отчёта нет»
объявляется, только когда пуст и архивный, иначе самый дорогой сценарий
«состав ревью неизвестен, гоняем заново» срабатывает на каждой доведённой
задаче.
diff --git a/av-dev-pipeline/skills/task-batch/SKILL.md b/av-dev-pipeline/skills/task-batch/SKILL.md
deleted file mode 100644
index b035f55..0000000
--- a/av-dev-pipeline/skills/task-batch/SKILL.md
+++ /dev/null
@@ -1,518 +0,0 @@
----
-name: task-batch
-description: Проводит несколько задач разом — планирует порядок и пересечения, гонит каждую задачу отдельным сабагентом в своём git worktree через task-pipeline (по умолчанию по одной задаче за раз; параллельно по графу зависимостей — по явной просьбе), интегрирует по одной ветке через rebase + fast-forward (линейная история), проверяет полноту ревью каждой ветки и в конце сверяет стыки, возникшие от слияния. Набор задач приходит извне. Использовать, когда просят сделать несколько задач сразу.
----
-
-# Батч задач
-
-Оркестратор **набора** задач. Планирует порядок, раскидывает задачи по
-изолированным worktree, каждую проводит через полный цикл
-`av-dev-pipeline:task-pipeline`, затем сводит в основную ветку линейной историей
-и делает финальную сверку. Тонкая обёртка над пайплайном задачи — не
-переизобретай её шаги, вызывай как есть.
-
-**По умолчанию задачи идут по одной**, в порядке зависимостей. Параллельно — по
-явной просьбе, и тогда параллельность **по графу зависимостей**: одновременно
-гонится только то, между чем нет ни зависимости, ни пересечения. Правило и его
-цена — в шаге 4.
-
-Работай **максимально автономно**, по тому же принципу, что и одиночный пайплайн:
-вопрос, который решать не тебе, записывается и не останавливает поток; спрашиваем
-только про **необратимое** (деплой, выкладка наружу, удаление или перезапись
-рабочих данных). Механику — планирование, worktree, rebase, интеграцию, чистку —
-делаем без спроса.
-
-## Предпосылки
-
-- **OpenSpec и скиллы `opsx:*`** — на них стоит цикл внутри каждого сабагента и
- проход `review-specs` финальной сверки. Проекта без OpenSpec это касается так
- же, как одиночного пайплайна (см. его раздел «Предпосылки»).
-- **Проектные копии этих скиллов и агентов при установке плагина удаляются.**
-
-### Обращение к соседним плагинам
-
-**Копия.** Дом — `shared/plugin-boundary.md` в репозитории плагинов. Правится
-дом, а не этот файл.
-
-
-
-Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на
-месте.
-
-**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`,
-`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может
-разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет
-видно ни в докладе, ни в поведении.
-
-**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт
-только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо
-откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он
-прочитает его сам.
-
-**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови
-строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя,
-пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже.
-
-**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня
-установленных плагинов проект не ведёт — он разошёлся бы с действительностью
-молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` —
-канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер.
-
-
-
-**У батча правило строже одним пунктом: полное имя обязательно и в charter'е
-сабагента.** Сабагент твоего контекста не видит, короткое имя разрешает у себя, и
-подмена на устаревшую проектную копию случится там, куда ты уже не смотришь.
-
-Перед стартом прочитай `CLAUDE.md` проекта: оттуда берутся **имя основной
-ветки** (оно подставляется в каждую команду git ниже), команда и семантика
-гейта, инварианты и что запускать запрещено. Раскладка нумерованных артефактов —
-`docs/database.md` и `docs/.pm.json` (ключ `migrations`).
-
-**Документов канона нет — проект к нему не приведён.** Скажи это строкой и
-предложи `av-dev-docs:canon` **до первой задачи**: иначе каждая задача батча
-заплатит поразрядной деградацией ревью, а имя основной ветки придётся
-угадывать.
-
-## Границы
-
-- **Набор задач приходит извне.** Батч его не формирует: не выбирает из беклога,
- не приоритизирует, не решает, что важнее. Набор не задан — попроси его у
- вызывающего и остановись.
-- **Батч не владеет спринтом и целями.** Он сообщает исход по каждой задаче в тех
- же трёх словах, что и `task-pipeline`: сделана / не доведена / оказалась крупнее
- задачи.
-- **Задачи закрывает пайплайн внутри каждого сабагента**, шагом 12 — после
- коммита работы и **отдельным коммитом учёта**, вызовом Skill `av-dev-tasks:tasks`.
- Батч сам записей учёта не трогает: он не знает, чем кончилась приёмка, и
- дублировать закрытие ему незачем. Но грязное дерево после сабагента — **его**
- проблема: на нём откажут и `rebase`, и `worktree remove` (см. шаг 6). Урожай ревью батч
- отдаёт списком, а задачи из него заводит тот, кто ведёт задачи проекта.
-
-## Ключевое отличие от одиночного пайплайна
-
-`task-pipeline` коммитит **в текущую ветку**, и при ручном запуске это основная
-ветка. Здесь так нельзя, поэтому батч — **осознанное исключение**: временные
-ветки и worktree заводятся лишь как средство изоляции, а конечное состояние — та
-же линейная история основной ветки через rebase + fast-forward. Ветки после
-вливания удаляются.
-
-Изоляция нужна **в обоих режимах, а не только в параллельном**: батч не вливает
-ветку, пока не проверил полноту её ревью (шаг 5), и упавшая задача обязана
-остаться в своём worktree для ручного дожатия (шаг 6), не оставив следа в
-основной ветке. В параллельном режиме к этому добавляется вторая причина —
-задачи не должны видеть недоделанную работу друг друга.
-
-## Модель исполнения
-
-- Каждая задача = **один автономный сабагент** (`general-purpose`, чтобы иметь
- доступ к Skill и Agent для вложенных чекпоинтов ревью), работающий **только в
- своём worktree** и прогоняющий `task-pipeline` целиком на этой задаче.
-- Оркестратор кода задач не пишет: он планирует, заводит worktree, запускает
- сабагентов, проверяет полноту их ревью, интегрирует ветки и делает финальную
- сверку.
-- Стиль правок внутри — заточка под проект и конвенции, right-size, без
- золочения.
-
-## Шаги
-
-### 1. Прочитать набор
-
-Набор задан списком (слаги, файлы, описания) — прочитай файл каждой задачи и
-связанные спеки и черновики. Сырьё (в терминах `av-dev-tasks` — запись типа
-`research` с пустым разделом «Вопрос») включается, но помни: сабагент проведёт
-его сперва через `opsx:explore`, это тяжелее и чаще упирается в вопрос.
-
-### 2. Спланировать порядок и пересечения (автономно)
-
-Для каждой задачи определи:
-
-- **затронутые capability** — по её описанию и по каталогу актуальных спек
- (`openspec/specs/`);
-- **жёсткие зависимости**: задача B строится на результате A → A строго раньше B;
-- **замеряющая задача** — та, чьё ревью будет доказывать находки **числами**. В
- последовательном прогоне это ничего не меняет: она и так идёт одна. В
- параллельном она гонится в волне **одна** (обоснование — ниже, в шаге 4).
- Помечается здесь, на планировании, а не во время прогона, и **независимо от
- режима**: состав волны определяется сейчас, режим может смениться просьбой уже
- после плана, а метка ревью назовёт разметчик уже внутри пайплайна задачи,
- после `propose`, — ключевать волну на ещё не сделанный выбор нельзя. Триггеры — по фактам о задаче, каждый
- сам по себе достаточен:
- - трогает схему хранилища, миграцию, формат на диске или объём хранимого;
- - трогает конкурентность: транзакции, блокировки, фоновые циклы, общее
- состояние;
- - трогает размер тела, буфер, память, сжатие, ретеншен, темп потока;
- - её тема названа в журнале `docs/review.md` как место, где уже ломалось.
-
- Ни один триггер не сработал — задача не замеряющая, даже если её ревью
- окажется `large`. Метка про глубину проверки, замеряющая — про соревнование за
- железо; это разные вопросы, и совпадают они не всегда. Обратное тоже бывает и
- тоже законно: помеченная задача, чьё ревью пошло меткой `small` или
- `medium`, машину не займёт вовсе — меряющие проходы живут только в `large`.
- Пометка от этого не снимается: она ставится **до** разметки, и перестраховка
- здесь стоит одной волны, а ошибка — испорченных чисел;
-- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
- нумерует миграции (путь — `docs/.pm.json`, ключ `migrations`), посмотри последний
- номер и **раздай номера всем задачам, которые, вероятно, их добавят**, до
- запуска. Номер уходит в charter сабагента, и он берёт назначенный, а не
- «следующий свободный».
-
- **Это отдельная механика от правила волны, и она ему не служит** — их раньше
- путали, и они тянули в разные стороны. Правило волны отвечает на вопрос «кто с
- кем гонится одновременно», предраздача — на вопрос «какой номер берёт задача».
- Раздача нужна там, где **две задачи одной под-пачки** добавляют нумерованный
- артефакт: каждая считает «следующий свободный» по основной ветке, которая ещё
- не видела соседку, и обе берут один номер. Миграции под это почти не попадают —
- миграция и так триггер замеряющей задачи, а замеряющая идёт одна; но
- нумерованные артефакты бывают не только миграциями. Поэтому номера раздаются
- **всем** задачам с таким артефактом, независимо от того, в какой волне они
- окажутся: раздача ничего не стоит, а её отсутствие ловится только конфликтом на
- интеграции. Между волнами проблемы нет — ветка следующей волны берётся от
- вершины, уже включающей предыдущие; в последовательном прогоне проблемы нет по
- той же причине, но номера всё равно раздай: режим может смениться просьбой, а
- раздача бесплатна;
-- **жёстко сериализуем** (не гоняем одновременно) настоящие пересечения:
- - **одна capability на несколько задач** — две задачи, правящие одну спеку (тем
- более одно и то же `### Requirement`), дают не текстовый, а **семантический**
- конфликт при архивации; сериализуем по смыслу, а не только по файлам;
- - пересечение по одним и тем же исходникам;
-- **мягкие конфликты** сериализовать не надо: файлы-перечни, где каждая задача
- правит **свою** строку (индексы, оглавления, списки записей), и спеки разных
- capability — разные строки и файлы, сливаются сами.
-
-Собери план как **граф зависимостей**, а не как плоский список: рёбра — жёсткие
-зависимости и сериализуемые пересечения. Дальше по режиму:
-
-- **последовательно (умолчание)** — линеаризуй граф в один порядок:
- топологический, а там, где он оставляет свободу, — раньше то, от чего зависит
- больше задач, и раньше то, что правит общие для набора места. Волн нет,
- замеряющие задачи ничем не отличаются от прочих;
-- **параллельно (по просьбе)** — нарежь граф на **волны**: в одну волну попадают
- только задачи, между которыми нет ребра; замеряющие стоят отдельными волнами по
- одной.
-
-Рёбра у графа двух видов, и путать их не надо: **зависимость** направлена (B без
-результата A не делается), **пересечение** — нет (кто первый, неважно, лишь бы не
-разом). Тот же словарь у графа проходов ревью — см. «Порядок прогона» в
-`av-dev-pipeline:review-pipeline`.
-
-```mermaid
-flowchart TD
- A["A: схема хранилища
(замеряющая)"]
- B["B: эндпоинт поверх A"]
- C["C: формат лога"]
- D["D: правит ту же capability, что C"]
-
- A -->|зависимость| B
- C -. пересечение — одна capability .- D
-```
-
-Этот граф даёт: **последовательно** — `A → B → C → D` (или `A → C → B → D`, обе
-линеаризации законны); **параллельно** — волна 1 `A` одна (замеряющая), волна 2
-`B` и `C`, волна 3 `D`.
-
-Схемы в этом скилле — **пример и сводка**, правила ставит текст: при расхождении
-прав он. (В `av-dev-pipeline:review-pipeline` наоборот — там граф прогона и есть
-алгоритм, и старший он.)
-
-Покажи план короткой репликой — режим, порядок или состав волн, какие задачи
-признаны замеряющими и по какому триггеру, — и иди дальше.
-
-### 3. Свежая база
-
-Убедись, что рабочее дерево чистое и основная ветка свежая. Зафиксируй базовый
-коммит. Новые ветки бери от свежей вершины; ветку следующей задачи (в
-параллельном режиме — ветки следующей волны) — от вершины, уже включающей
-результат предыдущих.
-
-### 4. Провести задачи
-
-**Умолчание — по одной задаче за раз, в порядке из шага 2.** Следующая стартует,
-когда предыдущая вернула отчёт и (если она зелёная) влилась. Обосновывать это не
-надо — обосновывается отступление. Причина умолчания в том, что задача батча
-дороже прохода ревью: каждая тянет полный цикл пайплайна с гейтом, поднятием
-сервиса и вложенным ревью, и две такие на одной машине дерутся за порты, рабочие
-каталоги, СУБД и само железо. Последовательный прогон к тому же оставляет ревью
-внутри задачи его собственное умолчание — **параллельные проходы**: машина
-свободна, и выигрыш берётся там, где он ничего не стоит.
-
-**Параллельно — по явной просьбе, и параллельность идёт по графу зависимостей.**
-Одновременно гонится только то, между чем на шаге 2 не нашлось ребра: ни жёсткой
-зависимости, ни общей capability, ни общих исходников. «Гони параллельно» не
-означает «гони всё разом» — граф остаётся в силе, просьба лишь разрешает
-использовать его ширину.
-
-В параллельном режиме действуют два ограничения:
-
-- **потолок — 2–3 задачи одновременно.** Больше трёх разом душат машину и
- провоцируют гонки. Волну шире трёх бей на под-пачки по ≤3 и **гони под-пачки
- последовательно**: следующая стартует, когда предыдущая вернула отчёты. Иначе
- потолок обходится тривиально — шесть задач, запущенных «двумя под-пачками» в
- одном сообщении, это шесть задач разом;
-- **волна из одной задачи обязательна для замеряющей.** Задача, признанная на
- шаге 2 **замеряющей**, гонится одна: соседний прогон на той же машине портит
- числа, а находка с испорченным оракулом хуже отсутствующей — она выглядит
- доказанной. Если замеряющая задача всё же пошла в общей волне, её отчёт обязан
- нести строку в границах покрытия: замеры сняты под соседней нагрузкой.
-
-Для каждой задачи (в параллельном режиме — для каждой задачи под-пачки):
-
-1. Заведи worktree и ветку от текущей вершины:
- `git worktree add -b task/ <основная ветка>`. Путь — во временном
- каталоге проекта (`./tmp`), не в системном `/tmp`.
-2. Запусти сабагента, `subagent_type: general-purpose`: в последовательном режиме
- — одного и дождись отчёта; в параллельном — **по одному на задачу под-пачки,
- всех в одном сообщении**. Charter сабагента:
- - работай **строго в своём worktree** ``; в другие каталоги и в основную
- ветку не лезь;
- - прогони Skill **`av-dev-pipeline:task-pipeline`** ровно на этой задаче,
- полный цикл SDD с обоими чекпоинтами ревью;
- - если задаче назначен **номер артефакта** — используй строго его;
- - **метка ревью выбирает разметчик конвейера, а не ты и не сабагент.** Он
- идёт внутри пайплайна задачи, шагом 4, сразу после `propose`, и его план
- обслуживает оба чекпоинта. Метка в вызов не передаётся вовсе. Батч не
- повод её понижать: «нас много и
- мы спешим» — ровно тот стимул, из-за которого проходы пропускают, и он снят
- тем, что регулятор не в руках у автора;
- - **режим прогона проходов ревью — от режима батча**, и его называет charter,
- а не сабагент: батч идёт по одной задаче → режим умолчательный, **`по
- графу`** (машина свободна); батч идёт волнами → **`линейно`**, твой worktree
- не один на машине, и этой причиной ты обязан объяснить режим в отчёте.
- Внутренние рёбра графа — цепочку проходов, держащих машину — конвейер
- соблюдает сам, в любом режиме;
- - **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из
- агента) — не пропускай ревью и не понижай метка: проведи его **инлайн** по
- тем же charter'ам `av-dev-pipeline`, сохранив обязательное — разметку первой
- (план с темами и меткой), гейт до опиниативных проходов, состав по плану,
- триаж последним. И **скажи в отчёте прямым текстом, что ревью шло инлайн**:
- инлайновый проход видит контекст автора и потому разведён с ним слабее — а
- инлайновая разметка вдобавок означает, что метка выбрал автор, и это
- отдельная строка;
- - **вернуть отчёт**, в котором обязательно: исход задачи одним из трёх слов;
- **план прогона: метка с обоснованием, темы и их глубины**, и режим; что сделано; какие вопросы
- записаны и куда; изменённые файлы; добавлялся ли нумерованный артефакт и с
- каким номером; затронутые capability; состояние гейта; **перечень
- тем с исходом по каждой**; **путь к
- сохранённому отчёту триажа** (`openspec/changes//review/`, после
- архивации — `openspec/changes/archive//review/`); шло ли ревью
- инлайн; границы покрытия.
-
-**Шаги 5 и 6 отрабатываются на вернувшейся задаче до старта следующей** — в
-параллельном режиме на вернувшейся волне до старта следующей. Иначе ветка
-следующей возьмётся от вершины, не видевшей предыдущую работу, и весь смысл
-порядка из шага 2 теряется.
-
-Сабагент, упершийся в вопрос, **не останавливает батч**: он записывает вопрос,
-режет задачу до остатка и доводит остаток — либо, если остатка нет, возвращает
-исход «не доведена». Оркестратор собирает такие вопросы и выносит их в финальный
-доклад пачкой.
-
-### 5. Проверить полноту ревью — до интеграции
-
-**Ветка, чей отчёт не называет план прогона, не вливается.** Пропуск не отличим
-от прохода без находок, и на уровне батча это ещё опаснее: отчётов много, каждый
-выглядит полным, а сверять их некому, кроме тебя.
-
-Сверка идёт в три шага, и порядок важен:
-
-1. **Возьми план прогона** из отчёта задачи — таблицу «тема → дом → глубина → кто
- закрывает» с меткой и обоснованием; он затем и заказан в обязательных полях
- шага 4. Плана в отчёте нет — сверять не с чем; это само по себе основание не
- вливать, пока сабагент не покажет план разметки задачи.
-2. **Сверяй с независимым артефактом, а не с прозой отчёта.** Перечень проходов
- бери из **сохранённого отчёта триажа** (`openspec/changes//review/` или
- `openspec/changes/archive//review/` — задача доведена, change заархивирован) —
- пайплайн обязан его туда положить. Проза сабагента написана тем же, кто мог
- проход и пропустить: она подтверждает сама себя. Отчёта триажа на месте нет —
- считай, что состав неизвестен, и дозапускай ревью целиком.
-3. **Сверь план с исходом**: против каждой темы плана обязан стоять отчёт либо
- названная причина его отсутствия. Раскладка «тема → кто закрывает с этой меткой» — в скилле `av-dev-pipeline:review-pipeline`.
-
-Расхождение — не повод отменять задачу: дозапусти недостающие проходы **на
-ветке**, в её worktree, через `av-dev-pipeline:review-pipeline`, и только потом
-интегрируй.
-
-**Передай в дозапуск тот же план.** Триаж требует его обязательным входом — без
-плана он не может сверить, все ли размеченные темы вернули отчёт, а эта сверка и
-есть то, ради чего дозапуск затевается. Плана не осталось (сабагент не сохранил
-его в отчёте) — пусть повторит разметку задачи: это самый дешёвый проход
-конвейера, и он дешевле, чем прогон, который нечем сверить.
-
-**Находки дозапуска — такие же находки, и зелёный гейт их не отменяет.** Правило
-интеграции «вливаем только зелёные» смотрит на гейт, а дозапущенный `critical`
-гейт не красит: он был бы пропущен молча, если это не сказать прямо. Поэтому:
-
-- `critical` или `major` из дозапуска — **вливание этой ветки останавливается**.
- Помеченное `инлайн` чинится в её worktree, после починки — гейт, затем
- интеграция. Помеченное `развилка` — вопрос в запись, задача режется до остатка
- ровно так же, как это сделал бы пайплайн внутри;
-- остатка нет — ветка не вливается и уходит в доклад как провалившаяся, со своим
- worktree;
-- `minor` и `nit` из дозапуска — в урожай доклада, вливанию не мешают.
-
-Отчёт дозапуска приложи к отчёту задачи и назови в докладе (шаг 9), почему он
-понадобился: систематический пропуск одного и того же прохода — находка о самом
-конвейере, а не о задаче.
-
-### 6. Интегрировать — rebase + fast-forward, по одной ветке
-
-Сводим ветки **строго последовательно** (линейная история), в порядке
-зависимостей. Вливаем **только зелёные**.
-
-**Ветка задачи занята её worktree, и это определяет форму команд.** Пока worktree
-жив (а удаляется он последним, после зелёного гейта), ветка `task/`
-checkout'нута в нём, и `git rebase <основная> task/` из главного worktree
-**падает**: `fatal: 'task/' is already used by worktree at …`. Поэтому
-rebase делается **внутри worktree задачи**, а ff-слияние — из главного.
-
-Для каждой готовой ветки `task/`:
-
-- `git -C rebase <основная>` — перенос ветки задачи на текущую вершину,
- выполняется в её собственном worktree;
-- резолв конфликтов (их почти нет — конфликтоопасное сериализовано, номера
- розданы заранее). Неавтоматический конфликт — **не форсируй**: прерви
- (`git -C rebase --abort`), оставь ветку и worktree как есть, вынеси это
- в доклад как нераспознанное пересечение;
-- **дерево сабагента обязано быть чистым.** `git -C status --porcelain`
- до `rebase`: непусто — значит сабагент не довёл шаг 12 до коммита учёта (или
- оставил мусор). Не форсируй и не коммить за него: назови задачу в докладе
- недоведённой и оставь ветку с worktree. Молчаливый `rebase` на грязном дереве
- всё равно откажет, но с сообщением про unstaged changes — а причина другая;
-- **ненулевой код `rebase` относится к этой ветке и только к ней.** Прерванный
- rebase в чужом worktree не трогает ни главное дерево, ни остальные ветки:
- проверь `git -C status` и `git status` — обе чистые. Уводить весь батч
- в провалившиеся из-за одного ненулевого кода запрещено: это ложная причина,
- из-за которой зелёные задачи не доедут до основной ветки. Провалилась одна —
- провалилась одна;
-- из главного worktree (он стоит на основной ветке — проверь
- `git rev-parse --abbrev-ref HEAD`): `git merge --ff-only task/`. Ветку в
- главном дереве **не переключай** — `git checkout task/` тоже упрётся в
- занятость;
-- после каждой интеграции — **гейт на основной ветке**. Красное — **откати эту
- интеграцию** (`git reset --hard` на прошлую вершину), ветку с worktree сохрани,
- задачу перечисли в докладе. Основная ветка **никогда** не остаётся
- полузелёной;
-- только после зелёного: `git worktree remove ` и
- `git branch -d task/` — в этом порядке, иначе ветка снова занята.
-
-**Политика частичного провала.** Упавшая задача (исход «не доведена», красные
-тесты в её worktree, конфликт при rebase, невлитая из-за находок дозапуска)
-**не блокирует остальные**: интегрируем все зелёные, упавшую оставляем в её
-worktree и ветке нетронутой — ничего не удаляем, — и перечисляем в докладе с
-причиной, отчётом и путём к worktree. Причина называется **настоящая**: «конфликт
-rebase в файле X», а не «нераспознанное пересечение» на всякий случай.
-
-### 7. Финальный гейт
-
-На основной ветке после всех интеграций — гейт целиком. Зелёное обязательно; пока
-красное, шаг 8 не начинается.
-
-### 8. Финальная сверка — только то, чего не видел никто
-
-Каждая задача уже прошла полный конвейер в своём worktree. Повторять его на
-интегрированном диффе бессмысленно: те же проходы на тех же файлах дадут те же
-находки и удорожат триаж. Здесь проверяется **только то, что появилось от
-слияния**:
-
-- запусти **по одному `review-specs` на каждую затронутую capability**, все
- разом — граф здесь плоский: машину эти проходы не держат, ребра между ними нет,
- а сама машина к этому моменту свободна (все сабагенты вернулись). Линейно —
- только по причине из раздела «Порядок прогона»
- `av-dev-pipeline:review-pipeline`, и причину назови;
-- **задание у этих проходов особое, и это надо сказать прямо.** Живого change
- здесь нет — все заархивированы, дельта-спек не существует. Источник требований
- — **актуальные** `openspec/specs//spec.md`, а предмет — стык:
- требование, которое одна задача выполнила, а соседняя незаметно отменила; два
- архивных change, по-разному описавшие одно поведение. Скажи проходу это прямо,
- иначе он пойдёт искать дельты и не найдёт ничего;
-- если задачи пересекались по файлам, добавь один `review-architecture` на
- интегрированный дифф с вопросом «не появился ли второй способ делать то, что
- уже делается» — именно он возникает, когда две задачи независимо решали
- похожее;
-- **заверши триажем.** Он единственный, кто агрегирует, и без него у находок нет
- ни оракула, ни пометки `инлайн`/`развилка` — а следующий абзац на неё
- опирается. Прогон из двух проходов без триажа — это сырые находки, выданные за
- разобранные;
-- **план триажу собери сам, здесь, — разметчика на этой сверке нет.** Триаж
- требует план обязательным входом: он сверяет размеченное с пришедшим, и без
- плана эта сверка не выполняется вовсе. Разметка задачи сюда не годится — она
- описывала одну задачу, а сверка идёт по интегрированной ветке. План здесь
- короткий и составляется по факту запуска:
-
- ```
- метка: не применяется — сверка стыка, а не ревью изменения
- тема дом глубина закрывает
- requirements openspec/specs// разбор specs (стык)
- requirements openspec/specs// разбор specs (стык)
- architecture docs/architecture.md разбор architecture
- + источник docs/passport.md
- ```
-
- Темы, которых в этом списке нет (`autotests`, `conventions`, `security`,
- `operations`, свои темы проекта), назови строкой «не проверяется на сверке
- стыка: закрыто прогонами отдельных задач». Это не формальность — без такой
- строки отчёт сверки читается как полное ревью ветки.
-
-Граф этой сверки — веер в один сток, и он такой же, как у обычного прогона:
-
-```mermaid
-flowchart TD
- merged["основная ветка после всех интеграций
(финальный гейт зелёный)"]
- s1["review-specs: capability 1
режим «стык после слияния»"]
- s2["review-specs: capability 2
режим «стык после слияния»"]
- arch["review-architecture на интегрированном диффе
(если задачи пересекались по файлам)"]
- tri["review-triage — сток"]
-
- merged --> s1 --> tri
- merged --> s2 --> tri
- merged --> arch --> tri
-```
-
-Замечания отрабатывай как одиночный пайплайн: `инлайн` чини сам, `развилка` —
-вопросом в запись; после правок — снова гейт.
-
-### 9. Прибраться и доложить
-
-- Убери worktree и ветки **только успешно влитых** задач, в конце
- `git worktree prune`. Worktree и ветки **провалившихся** не трогай — они нужны
- для ручного дожатия.
-- **Записей учёта батч не трогает** — их правит пайплайн внутри сабагента на
- шаге 12. Батч сообщает исход по каждой задаче; если какой-то сабагент дошёл до
- коммита, но закрытия не сделал (плагина нет, вызов не разрешился), скажи это
- строкой — иначе задача останется открытой молча.
-- Доложи кратко:
- - **исход по каждой задаче** одним из трёх слов, с хешем коммита;
- - **режим прогона** — по одной или волнами, и если волнами, то по чьей просьбе;
- порядок задач или состав волн, порядок интеграции, с пометкой, какие задачи
- шли по одной как замеряющие;
- - вопросы, записанные сабагентами, пачкой;
- - что дозапускалось на шаге 5 и почему; шло ли где-то ревью инлайн;
- - итог финальной сверки и ссылки на архивные change;
- - **`Урожай`** — отложенные находки всех задач одним списком, с провенансом.
- Задачи из него заводит тот, кто ведёт задачи проекта, а не батч;
- - **отдельно — провалившиеся** задачи с настоящей причиной и путём к
- оставленному worktree;
- - **границы покрытия сводной строкой**, включая задачи, чьи замеры снимались в
- общей волне, и ветки, где ревью шло инлайн.
-
-## Тонкости
-
-- **Изоляция параллельных тестов — цена параллельного режима, и проверяется она
- до первой волны.** Прежде чем гнать несколько прогонов разом, убедись, что
- тесты не делят фиксированный порт или файл БД (обычно берут временный каталог и
- эфемерный порт — тогда ок). Делят — такие задачи гони по одной, даже если
- просили параллельно, и скажи об этом строкой: просьба про параллельность, а не
- про сломанные тесты. В умолчательном режиме вопрос не встаёт вовсе — это одна
- из причин, по которым умолчание такое.
-- Поведенческая верификация внутри сабагента поднимает изменение вживую: в
- параллельном режиме следи, чтобы соседние worktree не дрались за порты и
- рабочие каталоги. Если проект умеет поднимать только один экземпляр — такие
- задачи в одну волну не ставь.
-- Ревью выполненного — **до** интеграции; это забота
- `av-dev-pipeline:task-pipeline` внутри каждого сабагента, дублировать не надо.
-- `openspec validate --strict` тоже внутри пайплайна задачи — не пропускай его
- своими правками на интеграции.
-- Крупная переработка, предложенная ревью внутри задачи, — развилка: не вливай
- молча, вынеси в доклад.
-- Держи вызывающего в цикле короткими репликами на переходах фаз (план → прогон
- задач → интеграция → финальная сверка), но не проси подтверждать механику.