Два независимых сабагента на av-dev-pm и av-dev-pipeline. Две находки нашли оба. Главная — моя же перестановка закрытия за коммит сломала reopen и батч. close печатал «дорога назад из git», а reopen искал коммит удаления, которого в новом порядке ещё нет: шаг 11 последний, учёт остаётся незакоммиченным. Проверено прогоном — отказ кодом 2 на свежезакрытой задаче. Тем же грязным деревом ломались rebase и worktree remove в батче: каждая закрывшая задачу ветка уехала бы в провалившиеся. Починено с обеих сторон: reopen берёт текст из HEAD, если коммита удаления нет, а шаг 11 коммитит учёт вторым коммитом. Вторая — канонический пример docs/.pm.json убивал tasks.py. Четыре документа показывали ключ tasks.sections, которого скрипт не знает: неизвестный ключ это код 3 на любой команде. Проект, заведённый по канону дословно, остался бы без работы с задачами, а docs.py при этом печатал «канон соблюдён». Секции живут в заголовках индекса и второго дома не получают. Остальные восемнадцать: init писал конфиг в упразднённый .tasks.json; looks_like_tasks не видел переименованный индекс; урожай спринта терял автотег после sprint close; ответ на вопрос по инструкции оставлял задачу незабираемой; adopt требовал недостижимого зелёного; путь отчёта триажа не переживал archive; review-specs не имел режима для стыка после слияния; три остатка «шаг 9а» несли предкоммитную позицию закрытия; sprint.md отрицал сам себя в пункте «Сделана». Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
361 lines
33 KiB
Markdown
361 lines
33 KiB
Markdown
---
|
||
name: task-batch
|
||
description: Проводит несколько задач разом — планирует порядок и пересечения, гонит каждую задачу отдельным сабагентом в своём git worktree через task-pipeline, интегрирует по одной ветке через rebase + fast-forward (линейная история), проверяет полноту ревью каждой ветки и в конце сверяет стыки, возникшие от слияния. Набор задач приходит извне. Использовать, когда просят сделать несколько задач сразу.
|
||
---
|
||
|
||
# Батч задач
|
||
|
||
Оркестратор **набора** задач. Планирует порядок, раскидывает задачи по
|
||
изолированным worktree, каждую проводит через полный цикл
|
||
`av-dev-pipeline:task-pipeline`, затем сводит в основную ветку линейной историей
|
||
и делает финальную сверку. Тонкая обёртка над пайплайном задачи — не
|
||
переизобретай её шаги, вызывай как есть.
|
||
|
||
Работай **максимально автономно**, по тому же принципу, что и одиночный пайплайн:
|
||
вопрос, который решать не тебе, записывается и не останавливает поток; спрашиваем
|
||
только про **необратимое** (деплой, выкладка наружу, удаление или перезапись
|
||
рабочих данных). Механику — планирование, worktree, rebase, интеграцию, чистку —
|
||
делаем без спроса.
|
||
|
||
## Предпосылки
|
||
|
||
- **OpenSpec и скиллы `opsx:*`** — на них стоит цикл внутри каждого сабагента и
|
||
проход `review-specs` финальной сверки. Проекта без OpenSpec это касается так
|
||
же, как одиночного пайплайна (см. его раздел «Предпосылки»).
|
||
- **Скиллы зовутся с пространством имён**: `av-dev-pipeline:task-pipeline`,
|
||
`av-dev-pipeline:review-pipeline`, `av-dev-pm:tasks`. Короткое имя
|
||
может разрешиться в устаревшую проектную копию, и это произойдёт молча — в
|
||
charter'е сабагента пиши полное имя, он твоего контекста не видит.
|
||
- **Проектные копии этих скиллов и агентов при установке плагина удаляются.**
|
||
|
||
Перед стартом прочитай `CLAUDE.md` проекта: оттуда берутся **имя основной
|
||
ветки** (оно подставляется в каждую команду git ниже), команда и семантика
|
||
гейта, инварианты и что запускать запрещено. Раскладка нумерованных артефактов —
|
||
`docs/database.md` и `docs/.pm.json` (ключ `migrations`).
|
||
|
||
**Документов канона нет — проект к нему не приведён.** Скажи это строкой и
|
||
предложи `av-dev-pm:canon` **до первой волны**: иначе каждая задача батча
|
||
заплатит поразрядной деградацией ревью, а имя основной ветки придётся
|
||
угадывать.
|
||
|
||
## Границы
|
||
|
||
- **Набор задач приходит извне.** Батч его не формирует: не выбирает из беклога,
|
||
не приоритизирует, не решает, что важнее. Набор не задан — попроси его у
|
||
вызывающего и остановись.
|
||
- **Батч не владеет спринтом и целями.** Он сообщает исход по каждой задаче в тех
|
||
же трёх словах, что и `task-pipeline`: сделана / не доведена / оказалась крупнее
|
||
задачи.
|
||
- **Задачи закрывает пайплайн внутри каждого сабагента**, шагом 11 — после
|
||
коммита работы и **отдельным коммитом учёта**, вызовом Skill `av-dev-pm:tasks`.
|
||
Батч сам записей учёта не трогает: он не знает, чем кончилась приёмка, и
|
||
дублировать закрытие ему незачем. Но грязное дерево после сабагента — **его**
|
||
проблема: на нём откажут и `rebase`, и `worktree remove` (см. шаг 6). Урожай ревью батч
|
||
отдаёт списком, а задачи из него заводит тот, кто ведёт задачи проекта.
|
||
|
||
## Ключевое отличие от одиночного пайплайна
|
||
|
||
`task-pipeline` коммитит **в текущую ветку**, и при ручном запуске это основная
|
||
ветка. Здесь так нельзя для параллельных задач, поэтому батч — **осознанное
|
||
исключение**: временные ветки и worktree заводятся лишь как средство изоляции, а
|
||
конечное состояние — та же линейная история основной ветки через rebase +
|
||
fast-forward. Ветки после вливания удаляются.
|
||
|
||
## Модель исполнения
|
||
|
||
- Каждая задача = **один автономный сабагент** (`general-purpose`, чтобы иметь
|
||
доступ к Skill и Agent для вложенных чекпоинтов ревью), работающий **только в
|
||
своём worktree** и прогоняющий `task-pipeline` целиком на этой задаче.
|
||
- Оркестратор кода задач не пишет: он планирует, заводит worktree, запускает
|
||
сабагентов, проверяет полноту их ревью, интегрирует ветки и делает финальную
|
||
сверку.
|
||
- Стиль правок внутри — заточка под проект и конвенции, right-size, без
|
||
золочения.
|
||
|
||
## Шаги
|
||
|
||
### 1. Прочитать набор
|
||
|
||
Набор задан списком (слаги, файлы, описания) — прочитай файл каждой задачи и
|
||
связанные спеки и черновики. Задачи-идеи включаются, но помни: сабагент проведёт
|
||
их сперва через `opsx:explore`, это тяжелее и чаще упирается в вопрос.
|
||
|
||
### 2. Спланировать порядок и пересечения (автономно)
|
||
|
||
Для каждой задачи определи:
|
||
|
||
- **затронутые capability** — по её описанию и по каталогу актуальных спек
|
||
(`openspec/specs/`);
|
||
- **жёсткие зависимости**: задача B строится на результате A → A строго раньше B;
|
||
- **замеряющая задача** — та, чьё ревью будет доказывать находки **числами**, и
|
||
потому она гонится в волне **одна** (обоснование — ниже, в шаге 4). Решается
|
||
здесь, на планировании, а не во время прогона: состав волны определяется
|
||
сейчас, а профиль ревью сабагент выберет только внутри задачи, и ключевать
|
||
волну на ещё не сделанный выбор нельзя. Триггеры — по фактам о задаче, каждый
|
||
сам по себе достаточен:
|
||
- трогает схему хранилища, миграцию, формат на диске или объём хранимого;
|
||
- трогает конкурентность: транзакции, блокировки, фоновые циклы, общее
|
||
состояние;
|
||
- трогает размер тела, буфер, память, сжатие, ретеншен, темп потока;
|
||
- её тема названа в `docs/research/` или в журнале `docs/review.md` как место,
|
||
где уже мерили или уже ломалось.
|
||
|
||
Ни один триггер не сработал — задача не замеряющая, даже если её ревью
|
||
окажется `deep`. `deep` про глубину проверки, замеряющая — про соревнование за
|
||
железо; это разные вопросы, и совпадают они не всегда;
|
||
- **нумерованные артефакты — номера раздаёт оркестратор заранее.** Если проект
|
||
нумерует миграции (путь — `docs/.pm.json`, ключ `migrations`), посмотри последний
|
||
номер и **раздай номера всем задачам, которые, вероятно, их добавят**, до
|
||
запуска. Номер уходит в charter сабагента, и он берёт назначенный, а не
|
||
«следующий свободный».
|
||
|
||
**Это отдельная механика от правила волны, и она ему не служит** — их раньше
|
||
путали, и они тянули в разные стороны. Правило волны отвечает на вопрос «кто с
|
||
кем гонится одновременно», предраздача — на вопрос «какой номер берёт задача».
|
||
Раздача нужна там, где **две задачи одной под-пачки** добавляют нумерованный
|
||
артефакт: каждая считает «следующий свободный» по основной ветке, которая ещё
|
||
не видела соседку, и обе берут один номер. Миграции под это почти не попадают —
|
||
миграция и так триггер замеряющей задачи, а замеряющая идёт одна; но
|
||
нумерованные артефакты бывают не только миграциями. Поэтому номера раздаются
|
||
**всем** задачам с таким артефактом, независимо от того, в какой волне они
|
||
окажутся: раздача ничего не стоит, а её отсутствие ловится только конфликтом на
|
||
интеграции. Между волнами проблемы нет — ветка следующей волны берётся от
|
||
вершины, уже включающей предыдущие;
|
||
- **жёстко сериализуем** (не гоняем одновременно) настоящие пересечения:
|
||
- **одна capability на несколько задач** — две задачи, правящие одну спеку (тем
|
||
более одно и то же `### Requirement`), дают не текстовый, а **семантический**
|
||
конфликт при архивации; сериализуем по смыслу, а не только по файлам;
|
||
- пересечение по одним и тем же исходникам;
|
||
- **мягкие конфликты** сериализовать не надо: файлы-перечни, где каждая задача
|
||
правит **свою** строку (индексы, оглавления, списки записей), и спеки разных
|
||
capability — разные строки и файлы, сливаются сами.
|
||
|
||
Собери план: **волны** параллельно-безопасных задач плюс сериализованный хвост
|
||
конфликтоопасных, с учётом зависимостей; замеряющие задачи стоят в плане
|
||
отдельными волнами по одной. Покажи план короткой репликой — назвав, какие
|
||
задачи признаны замеряющими и по какому триггеру, — и иди дальше.
|
||
|
||
### 3. Свежая база
|
||
|
||
Убедись, что рабочее дерево чистое и основная ветка свежая. Зафиксируй базовый
|
||
коммит. Новые ветки бери от свежей вершины; ветки следующей волны — от вершины,
|
||
уже включающей результат предыдущих волн.
|
||
|
||
### 4. Прогнать волны
|
||
|
||
**Потолок параллелизма — 2–3 задачи одновременно.** Каждая задача тянет полный
|
||
цикл пайплайна с вложенным ревью и гейтом, поэтому больше трёх разом душат
|
||
машину и провоцируют гонки. Волну шире трёх бей на под-пачки по ≤3 и **гони
|
||
под-пачки последовательно**: следующая стартует, когда предыдущая вернула отчёты.
|
||
Иначе потолок обходится тривиально — шесть задач, запущенных «двумя под-пачками»
|
||
в одном сообщении, это шесть задач разом.
|
||
|
||
**Волна из одной задачи — не вырожденный случай, а обязательный.** Задача,
|
||
признанная на шаге 2 **замеряющей**, гонится в волне одна: соседний прогон на той
|
||
же машине портит числа, а находка с испорченным оракулом хуже отсутствующей — она
|
||
выглядит доказанной. Если замеряющая задача всё же пошла в общей волне, её отчёт
|
||
обязан нести строку в границах покрытия: замеры сняты под соседней нагрузкой.
|
||
|
||
Для каждой задачи в под-пачке:
|
||
|
||
1. Заведи worktree и ветку от текущей вершины:
|
||
`git worktree add <path> -b task/<slug> <основная ветка>`. Путь — во временном
|
||
каталоге проекта (`./tmp`), не в системном `/tmp`.
|
||
2. Запусти **по одному сабагенту на задачу, все в одном сообщении**,
|
||
`subagent_type: general-purpose`. Charter сабагента:
|
||
- работай **строго в своём worktree** `<path>`; в другие каталоги и в основную
|
||
ветку не лезь;
|
||
- прогони Skill **`av-dev-pipeline:task-pipeline`** ровно на этой задаче,
|
||
полный цикл SDD с обоими чекпоинтами ревью;
|
||
- если задаче назначен **номер артефакта** — используй строго его;
|
||
- **профиль ревью выбирается по факту изменения.** Батч не повод понижать
|
||
профиль: «нас много и мы спешим» — это ровно тот стимул, из-за которого
|
||
проходы пропускают;
|
||
- **режим прогона проходов — последовательный.** Твой worktree не один на
|
||
машине;
|
||
- **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из
|
||
агента) — не пропускай ревью и не понижай профиль: проведи его **инлайн** по
|
||
тем же charter'ам `av-dev-pipeline`, сохранив обязательное — гейт до
|
||
опиниативных проходов, состав по профилю, триаж последним. И **скажи в
|
||
отчёте прямым текстом, что ревью шло инлайн**: инлайновый проход видит
|
||
контекст автора и потому декоррелирован слабее — это меняет доверие к
|
||
результату, а не только способ запуска;
|
||
- **вернуть отчёт**, в котором обязательно: исход задачи одним из трёх слов;
|
||
**объявленный профиль ревью и режим прогона**; что сделано; какие вопросы
|
||
записаны и куда; изменённые файлы; добавлялся ли нумерованный артефакт и с
|
||
каким номером; затронутые capability; состояние гейта; **перечень
|
||
запущенных проходов ревью поимённо с исходом каждого**; **путь к
|
||
сохранённому отчёту триажа** (`openspec/changes/<id>/review/`, после
|
||
архивации — `openspec/changes/archive/<id>/review/`); шло ли ревью
|
||
инлайн; границы покрытия.
|
||
|
||
Сабагент, упершийся в вопрос, **не останавливает батч**: он записывает вопрос,
|
||
режет задачу до остатка и доводит остаток — либо, если остатка нет, возвращает
|
||
исход «не доведена». Оркестратор собирает такие вопросы и выносит их в финальный
|
||
доклад пачкой.
|
||
|
||
### 5. Проверить полноту ревью — до интеграции
|
||
|
||
**Ветка, чей отчёт не называет профиль и проходы поимённо, не вливается.**
|
||
Пропуск прохода не отличим от прохода без находок, и на уровне батча это ещё
|
||
опаснее: отчётов много, каждый выглядит полным, а сверять их некому, кроме тебя.
|
||
|
||
Сверка идёт в три шага, и порядок важен:
|
||
|
||
1. **Возьми объявленный профиль** из отчёта задачи — он затем и заказан в
|
||
обязательных полях шага 4. Профиля в отчёте нет — перечень проходов сверять
|
||
не с чем; это само по себе основание не вливать, пока сабагент не назовёт
|
||
профиль и не обоснует его по факту изменения.
|
||
2. **Сверяй с независимым артефактом, а не с прозой отчёта.** Перечень проходов
|
||
бери из **сохранённого отчёта триажа** (`openspec/changes/<id>/review/` или
|
||
`openspec/changes/archive/<id>/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/<slug>`
|
||
checkout'нута в нём, и `git rebase <основная> task/<slug>` из главного worktree
|
||
**падает**: `fatal: 'task/<slug>' is already used by worktree at …`. Поэтому
|
||
rebase делается **внутри worktree задачи**, а ff-слияние — из главного.
|
||
|
||
Для каждой готовой ветки `task/<slug>`:
|
||
|
||
- `git -C <path> rebase <основная>` — перенос ветки задачи на текущую вершину,
|
||
выполняется в её собственном worktree;
|
||
- резолв конфликтов (их почти нет — конфликтоопасное сериализовано, номера
|
||
розданы заранее). Неавтоматический конфликт — **не форсируй**: прерви
|
||
(`git -C <path> rebase --abort`), оставь ветку и worktree как есть, вынеси это
|
||
в доклад как нераспознанное пересечение;
|
||
- **дерево сабагента обязано быть чистым.** `git -C <path> status --porcelain`
|
||
до `rebase`: непусто — значит сабагент не довёл шаг 11 до коммита учёта (или
|
||
оставил мусор). Не форсируй и не коммить за него: назови задачу в докладе
|
||
недоведённой и оставь ветку с worktree. Молчаливый `rebase` на грязном дереве
|
||
всё равно откажет, но с сообщением про unstaged changes — а причина другая;
|
||
- **ненулевой код `rebase` относится к этой ветке и только к ней.** Прерванный
|
||
rebase в чужом worktree не трогает ни главное дерево, ни остальные ветки:
|
||
проверь `git -C <path> status` и `git status` — обе чистые. Уводить весь батч
|
||
в провалившиеся из-за одного ненулевого кода запрещено: это ложная причина,
|
||
из-за которой зелёные задачи не доедут до основной ветки. Провалилась одна —
|
||
провалилась одна;
|
||
- из главного worktree (он стоит на основной ветке — проверь
|
||
`git rev-parse --abbrev-ref HEAD`): `git merge --ff-only task/<slug>`. Ветку в
|
||
главном дереве **не переключай** — `git checkout task/<slug>` тоже упрётся в
|
||
занятость;
|
||
- после каждой интеграции — **гейт на основной ветке**. Красное — **откати эту
|
||
интеграцию** (`git reset --hard` на прошлую вершину), ветку с worktree сохрани,
|
||
задачу перечисли в докладе. Основная ветка **никогда** не остаётся
|
||
полузелёной;
|
||
- только после зелёного: `git worktree remove <path>` и
|
||
`git branch -d task/<slug>` — в этом порядке, иначе ветка снова занята.
|
||
|
||
**Политика частичного провала.** Упавшая задача (исход «не доведена», красные
|
||
тесты в её worktree, конфликт при rebase, невлитая из-за находок дозапуска)
|
||
**не блокирует остальные**: интегрируем все зелёные, упавшую оставляем в её
|
||
worktree и ветке нетронутой — ничего не удаляем, — и перечисляем в докладе с
|
||
причиной, отчётом и путём к worktree. Причина называется **настоящая**: «конфликт
|
||
rebase в файле X», а не «нераспознанное пересечение» на всякий случай.
|
||
|
||
### 7. Финальный гейт
|
||
|
||
На основной ветке после всех интеграций — гейт целиком. Зелёное обязательно; пока
|
||
красное, шаг 8 не начинается.
|
||
|
||
### 8. Финальная сверка — только то, чего не видел никто
|
||
|
||
Каждая задача уже прошла полный конвейер в своём worktree. Повторять его на
|
||
интегрированном диффе бессмысленно: те же проходы на тех же файлах дадут те же
|
||
находки и удорожат триаж. Здесь проверяется **только то, что появилось от
|
||
слияния**:
|
||
|
||
- запусти **по одному `review-specs` на каждую затронутую capability**,
|
||
последовательно. Параллельно — только если человек попросил явно и назвал
|
||
набор: правило и оба его условия живут в
|
||
`av-dev-pipeline:review-pipeline`, раздел «Режим запуска», и здесь не
|
||
ослабляются. «Замеров не делают» основанием не является;
|
||
- **режим у этих проходов особый, и его надо назвать в задании.** Живого change
|
||
здесь нет — все заархивированы, дельта-спек не существует. Источник требований
|
||
— **актуальные** `openspec/specs/<capability>/spec.md`, а предмет — стык:
|
||
требование, которое одна задача выполнила, а соседняя незаметно отменила; два
|
||
архивных change, по-разному описавшие одно поведение. Скажи проходу это прямо,
|
||
иначе он пойдёт искать дельты и не найдёт ничего;
|
||
- если задачи пересекались по файлам, добавь один `review-architecture` на
|
||
интегрированный дифф с вопросом «не появился ли второй способ делать то, что
|
||
уже делается» — именно он возникает, когда две задачи независимо решали
|
||
похожее;
|
||
- **заверши триажем.** Он единственный, кто агрегирует, и без него у находок нет
|
||
ни оракула, ни пометки `инлайн`/`развилка` — а следующий абзац на неё
|
||
опирается. Прогон из двух проходов без триажа — это сырые находки, выданные за
|
||
разобранные.
|
||
|
||
Замечания отрабатывай как одиночный пайплайн: `инлайн` чини сам, `развилка` —
|
||
вопросом в запись; после правок — снова гейт.
|
||
|
||
### 9. Прибраться и доложить
|
||
|
||
- Убери worktree и ветки **только успешно влитых** задач, в конце
|
||
`git worktree prune`. Worktree и ветки **провалившихся** не трогай — они нужны
|
||
для ручного дожатия.
|
||
- **Записей учёта батч не трогает** — их правит пайплайн внутри сабагента на
|
||
шаге 11. Батч сообщает исход по каждой задаче; если какой-то сабагент дошёл до
|
||
коммита, но закрытия не сделал (плагина нет, вызов не разрешился), скажи это
|
||
строкой — иначе задача останется открытой молча.
|
||
- Доложи кратко:
|
||
- **исход по каждой задаче** одним из трёх слов, с хешем коммита;
|
||
- план волн и порядок интеграции, с пометкой, какие задачи шли по одной как
|
||
замеряющие;
|
||
- вопросы, записанные сабагентами, пачкой;
|
||
- что дозапускалось на шаге 5 и почему; шло ли где-то ревью инлайн;
|
||
- итог финальной сверки и ссылки на архивные change;
|
||
- **`Урожай`** — отложенные находки всех задач одним списком, с провенансом.
|
||
Задачи из него заводит тот, кто ведёт задачи проекта, а не батч;
|
||
- **отдельно — провалившиеся** задачи с настоящей причиной и путём к
|
||
оставленному worktree;
|
||
- **границы покрытия сводной строкой**, включая задачи, чьи замеры снимались в
|
||
общей волне, и ветки, где ревью шло инлайн.
|
||
|
||
## Тонкости
|
||
|
||
- **Изоляция параллельных тестов.** Прежде чем гнать несколько прогонов разом,
|
||
убедись, что тесты не делят фиксированный порт или файл БД (обычно берут
|
||
временный каталог и эфемерный порт — тогда ок). Делят — гони такие задачи
|
||
последовательно.
|
||
- Поведенческая верификация внутри сабагента поднимает изменение вживую: следи,
|
||
чтобы соседние worktree не дрались за порты и рабочие каталоги. Если проект
|
||
умеет поднимать только один экземпляр — такие задачи в одну волну не ставь.
|
||
- Ревью выполненного — **до** интеграции; это забота
|
||
`av-dev-pipeline:task-pipeline` внутри каждого сабагента, дублировать не надо.
|
||
- `openspec validate --strict` тоже внутри пайплайна задачи — не пропускай его
|
||
своими правками на интеграции.
|
||
- Крупная переработка, предложенная ревью внутри задачи, — развилка: не вливай
|
||
молча, вынеси в доклад.
|
||
- Держи вызывающего в цикле короткими репликами на переходах фаз (план → волны →
|
||
интеграция → финальная сверка), но не проси подтверждать механику.
|