diff --git a/DECISIONS.md b/DECISIONS.md index 334c499..df28858 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -941,3 +941,56 @@ HTML-комментарии, невидимые в отрендеренном ma индекса — переименование не трогает механику, только умолчание и тексты. 55. **Метафора — плохое имя для секции индекса.** Секция читается человеком без контекста, часто из вывода `list`, и второго шанса объяснить себя у неё нет. + +## 14. Умолчания режимов прогона перевёрнуты (2026-08-03) + +### Что было + +Оба скилла держали одно и то же умолчание — «по очереди», — хотя цена очереди у +них разная. `review-pipeline` гнал проходы последовательно и требовал для +параллельности **двух** условий (явная просьба **и** поимённо названный набор). +`task-batch`, наоборот, планировал волны параллельных задач с потолком 2–3 и +считал параллельность нормой прогона. + +Перепутаны оказались уровни. Проход ревью — чтение и рассуждение: он ничего не +поднимает, ни за что не дерётся и по построению не видит выводов соседа. Задача +батча — полный цикл пайплайна: гейт, поднятие сервиса вживую, вложенное ревью, +общие порты и рабочие каталоги. Дешёвое стояло в очереди, дорогое гонялось разом. + +### Решено + +**UU. В ревью умолчание — параллельно.** Стадии по-прежнему идут по порядку, +параллельность касается только проходов внутри стадии. Последовательно гоняем по +трём особым причинам, и каждая называется в отчёте: сказал оператор; проходы +меряют; машина занята — причём занятость видит вызывающий, а не конвейер. Просьба +«гони последовательно» **набора не требует**: очередь ничего не портит, она +только дольше, и домысливать тут нечего — в отличие от прежнего правила, где +неназванный набор блокировал отступление. + +**VV. Меряющая пара — правило стадии, а не решение прогона.** `adversary` и `ops` +идут по очереди всегда: оба доказывают находки числами и оба меряют одно железо, а +испорченный оракул хуже отсутствующего. Общее «гони параллельно» этого не +отменяет; отменяет только прямое слово оператора **про эту пару**, и тогда в +границы покрытия идёт строка про замеры под соседней нагрузкой. + +**WW. В батче умолчание — по одной задаче, параллельность — по графу +зависимостей.** План собирается как граф (рёбра — жёсткие зависимости и +сериализуемые пересечения) и в умолчании линеаризуется в один порядок. Просьба +«гони параллельно» разрешает использовать **ширину графа**, а не гнать всё разом: +потолок 2–3, замеряющая задача — волной по одной. Прежние правила волн сохранены +целиком, они просто перестали быть умолчанием. + +### Что из этого следует + +56. **Режим батча задаёт режим ревью внутри задачи, и его называет charter.** + Батч идёт по одной — машина свободна, сабагент гонит проходы параллельно; + батч идёт волнами — сабагенту предписан последовательный режим с этой самой + причиной. Сабагент своего соседа не видит, поэтому решать это ему нельзя. +57. **Ранний выход из ревью переехал на границу стадии.** Стадии идут по порядку + в любом режиме, так что остановиться между ними можно всегда; остановка + **внутри** стадии осталась побочной выгодой последовательного режима — но не + поводом его выбирать. +58. **Цена параллельного батча проверяется до первой волны.** Тесты, делящие + фиксированный порт или файл БД, и проект, умеющий поднимать один экземпляр, — + основание гнать по одной даже после просьбы, сказанное строкой: просьба была + про параллельность, а не про сломанные тесты. diff --git a/av-dev-pipeline/skills/review-pipeline/SKILL.md b/av-dev-pipeline/skills/review-pipeline/SKILL.md index f8e7944..6657068 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: Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, независимая реализация по триггеру, архитектура и обязательный триаж. Проходы гонятся последовательно; параллельно — только по явной просьбе и с явно названным набором. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода. +description: Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, независимая реализация по триггеру, архитектура и обязательный триаж. Проходы внутри стадии гонятся параллельно; последовательно — по особой причине (меряющая пара, занятая машина) или по слову оператора. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода. --- # Конвейер ревью @@ -183,44 +183,42 @@ description: Конвейер ревью изменения — детермин | Режим | Как | Когда | |---|---|---| -| **последовательно** (умолчание) | по одному, следующий стартует после отчёта предыдущего | всегда, пока не попросили иначе | -| **параллельно** | названные проходы — одним сообщением | только по явной просьбе **и** с явно названным набором | +| **параллельно** (умолчание) | проходы стадии — одним сообщением | всегда, пока не сработала особая причина | +| **последовательно** | по одному, следующий стартует после отчёта предыдущего | по слову оператора **или** по одной из особых причин ниже | -**Умолчание — последовательно, и его не надо обосновывать.** Обосновывается -отступление. +**Умолчание — параллельно, и его не надо обосновывать.** Обосновывается +отступление. Проходы независимы по построению: ни один не видит выводов другого +(см. ниже), у всех общий вход и разные критерии. Очередь между ними не добавляет +ничего, кроме ожидания, — а ожидание на каждом чекпоинте ревью платится каждой +задачей. -**Параллельный режим включается при двух условиях сразу**, и второе так же -обязательно, как первое: +**Последовательно гоним в трёх случаях, и каждый называется в отчёте:** -1. **о нём попросили явно** — «гони параллельно», а не «сделай побыстрее»; -2. **названо, что именно гнать параллельно** — поимённый набор проходов - («`specs` и `code` параллельно») или стадия целиком («стадию 1 параллельно»). +1. **сказал оператор** — «гони последовательно». Набор при этом называть не + обязательно: последовательный прогон ничего не портит, он только дольше, и + домысливать тут нечего; +2. **проходы меряют.** `adversary` и `ops` доказывают находки числами: время + удержания блокировки против её таймаута, пик кучи против размера тела, темп + роста файлов журнала, длительность транзакции. Два меряющих прохода на одной + машине соревнуются за диск, CPU и за саму СУБД и выдают числа, которые не + воспроизведутся. Это не гипотеза: правило выведено из находок, целиком + державшихся на таких замерах, — у каждого проекта они свои и лежат в журнале + `docs/review.md`. Число, снятое под конкурентную нагрузку от соседнего + прохода, — это находка с испорченным оракулом, а её опровержение стоит дороже + всего выигрыша от параллельности. **Эта пара идёт по очереди всегда** — это + правило стадии 2, а не решение прогона (см. её раздел); +3. **машина занята, и знает об этом вызывающий.** Рядом идёт другая задача, + поднят сервис, гоняется гейт или дорогая проверка проекта. Сам конвейер + занятости машины не видит — её обязан назвать тот, кто запускает; так и + делает `av-dev-pipeline:task-batch`, когда ведёт задачи параллельно. -Просьба без набора — **не основание**: гоним последовательно и одной строкой -говорим, что набор не был назван. Это не придирка к формулировке. Параллелить -можно ровно то, что не мешает друг другу, а знание об этом лежит у того, кто -просит: он видит, занята ли машина, и ждёт ли он от прогона замеров. Домысливать -набор за него — значит принять решение, которое он оставил себе. +Отдельная причина, не связанная со стоимостью, — **разбор самого конвейера**: +когда выясняется, почему проход чего-то не нашёл, порядок и изоляция важнее +скорости. -Почему умолчание именно такое: - -- **Замеры.** Проходы `adversary` и `ops` доказывают находки числами: время - удержания блокировки против её таймаута, пик кучи против размера тела, темп - роста файлов журнала, длительность транзакции. Два меряющих прохода на одной - машине соревнуются за диск, CPU и за саму СУБД и выдают числа, которые не - воспроизведутся. Это не гипотеза: правило выведено из находок, целиком - державшихся на таких замерах, — у каждого проекта они свои и лежат в журнале - `docs/review.md`. Число, снятое под конкурентную нагрузку от соседнего - прохода, — это находка с испорченным оракулом, а её опровержение стоит дороже - всего выигрыша от параллельности. -- **Машина одна.** Рядом идёт задача, поднят сервис, гоняется гейт или дорогая - проверка проекта. -- **Ранний выход** возможен только при последовательном прогоне (см. ниже). -- **Разбор самого конвейера.** Когда выясняется, почему проход чего-то не нашёл, - порядок и изоляция важнее скорости. - -Если параллельный режим всё же включён, в границы покрытия идёт строка: какие -проходы шли разом и что замеры, снятые в этом прогоне, как оракул слабее. +Если меряющие проходы всё же пошли разом — а это бывает только по прямому слову +оператора, — в границы покрытия идёт строка: какие проходы шли одновременно и +что замеры этого прогона как оракул слабее. **Чего режим не меняет — и это не подлежит обсуждению.** Проход **не видит** находок других проходов ни в каком режиме. «Последовательно» значит «по @@ -231,15 +229,17 @@ description: Конвейер ревью изменения — детермин маскируется под независимое подтверждение. Единственный, кто видит всё, — триаж, и это его работа. -**Ранний выход** (последовательный режим делает его возможным — это его побочная -выгода, а не повод его выбирать). Допустимо остановить прогон, не докатив -остаток, ровно в одном случае: находка требует **переделки формы** изменения, и +**Ранний выход — по границе стадии.** Стадии идут по порядку в любом режиме, +поэтому остановиться между ними можно всегда; последовательный режим добавляет к +этому возможность остановиться **внутри** стадии — это его побочная выгода, а не +повод его выбирать. Допустимо остановить прогон, не докатив остаток, ровно в +одном случае: находка требует **переделки формы** изменения, и остальные проходы будут смотреть на код, которого через час не станет. Тогда: - прогон останавливается, находка чинится, конвейер запускается **заново с нулевой стадии** — а не «доезжает» остатком по старому коду; - незапущенные проходы идут в границы покрытия строкой «не запускался: прогон - остановлен на <проход> из-за <находка>», поимённо; + остановлен на <проход или стадия> из-за <находка>», поимённо; - триаж запускается только на полном прогоне. Отчёт триажа по половине проходов выглядит полным, потому что агрегирует всё, что ему подали, — это тот же молчащий пропуск, что и в разделе «Профили». @@ -248,8 +248,9 @@ description: Конвейер ревью изменения — детермин (`Действие: инлайн`), **не делается**: дешевле дособрать все находки и починить пачкой, чем гонять конвейер дважды. -Режим объявляется в отчёте наравне с профилем, и если он **параллельный** — с -причиной и составом. Последовательный объявляется одним словом. +Режим объявляется в отчёте наравне с профилем. Параллельный — одним словом. +**Последовательный — с причиной** (какой именно из трёх) и с составом, если по +очереди шла только часть проходов. ## Стадия 0 — Gate (обязательна во всех профилях) @@ -275,8 +276,8 @@ description: Конвейер ревью изменения — детермин ## Стадия 1 — Conformance (обязательна во всех профилях) Два applicative-прохода: оба применяют **записанный** критерий, оба дешёвые. -Замеров они не делают и потому безобиднее прочих, если параллельный режим -попросят с их именами; сами по себе идут по очереди, как и все. +Замеров они не делают и не мешают друг другу ничем — это канонический случай +умолчания: оба уходят одним сообщением. - `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не из proposal, сообщения коммита или описания задачи. Сверка двунаправленная; @@ -296,11 +297,13 @@ Recall обоих равен длине их источника — это и е - `review-adversary` — находка есть **построенный путь**, а не свойство; - `review-ops` — постмортем от симптома у владельца сервиса к строке кода. -**Эту пару параллелить не стоит даже по просьбе — переспроси.** Оба доказывают -находки замером, и оба меряют одно и то же железо. Запущенные разом, они портят -числа друг другу, а испорченный оракул хуже отсутствующего: находка выглядит -доказанной. Если их всё же назвали в параллельном наборе — выполняй, но скажи в -границах покрытия, что числа этого прогона сняты под соседней нагрузкой. +**Эта пара — именованное исключение из умолчания: она идёт по очереди всегда.** +Оба доказывают находки замером, и оба меряют одно и то же железо. Запущенные +разом, они портят числа друг другу, а испорченный оракул хуже отсутствующего: +находка выглядит доказанной. Очередь здесь не обосновывается — она правило +стадии, и на общее «гони параллельно» не отменяется. Если оператор прямо велел +гнать разом **и эту пару** — выполняй, но скажи в границах покрытия, что числа +этого прогона сняты под соседней нагрузкой. **Эта стадия зарабатывает больше всех остальных вместе, и потому стоит в `standard`, а не только в `deep`.** Измерено на пяти задачах подряд: враждебный diff --git a/av-dev-pipeline/skills/review-pipeline/references/review-journal.md b/av-dev-pipeline/skills/review-pipeline/references/review-journal.md index 4f755b4..518f920 100644 --- a/av-dev-pipeline/skills/review-pipeline/references/review-journal.md +++ b/av-dev-pipeline/skills/review-pipeline/references/review-journal.md @@ -98,9 +98,8 @@ - **готовые оракулы** — выборка по пометке `пойман ревью`: находка того же класса подтверждается ссылкой на запись, а не рассуждением; - **основание для правил конвейера** — требование называть запущенные проходы - поимённо, отказ от чисел, производных от размера корпуса, и правило - последовательного прогона выведены из конкретных записей, а не из общих - соображений; + поимённо, отказ от чисел, производных от размера корпуса, и правило очереди для + меряющих проходов выведены из конкретных записей, а не из общих соображений; - **счётчик обратимости решений** — сузили состав проходов и через месяц поймали дефект ровно того класса, который перестали проверять: решение пересматривается фактом, а не спором. diff --git a/av-dev-pipeline/skills/task-batch/SKILL.md b/av-dev-pipeline/skills/task-batch/SKILL.md index 88d86fc..88b7350 100644 --- a/av-dev-pipeline/skills/task-batch/SKILL.md +++ b/av-dev-pipeline/skills/task-batch/SKILL.md @@ -1,6 +1,6 @@ --- name: task-batch -description: Проводит несколько задач разом — планирует порядок и пересечения, гонит каждую задачу отдельным сабагентом в своём git worktree через task-pipeline, интегрирует по одной ветке через rebase + fast-forward (линейная история), проверяет полноту ревью каждой ветки и в конце сверяет стыки, возникшие от слияния. Набор задач приходит извне. Использовать, когда просят сделать несколько задач сразу. +description: Проводит несколько задач разом — планирует порядок и пересечения, гонит каждую задачу отдельным сабагентом в своём git worktree через task-pipeline (по умолчанию по одной задаче за раз; параллельно по графу зависимостей — по явной просьбе), интегрирует по одной ветке через rebase + fast-forward (линейная история), проверяет полноту ревью каждой ветки и в конце сверяет стыки, возникшие от слияния. Набор задач приходит извне. Использовать, когда просят сделать несколько задач сразу. --- # Батч задач @@ -11,6 +11,11 @@ description: Проводит несколько задач разом — пл и делает финальную сверку. Тонкая обёртка над пайплайном задачи — не переизобретай её шаги, вызывай как есть. +**По умолчанию задачи идут по одной**, в порядке зависимостей. Параллельно — по +явной просьбе, и тогда параллельность **по графу зависимостей**: одновременно +гонится только то, между чем нет ни зависимости, ни пересечения. Правило и его +цена — в шаге 4. + Работай **максимально автономно**, по тому же принципу, что и одиночный пайплайн: вопрос, который решать не тебе, записывается и не останавливает поток; спрашиваем только про **необратимое** (деплой, выкладка наружу, удаление или перезапись @@ -34,7 +39,7 @@ description: Проводит несколько задач разом — пл `docs/database.md` и `docs/.pm.json` (ключ `migrations`). **Документов канона нет — проект к нему не приведён.** Скажи это строкой и -предложи `av-dev-pm:canon` **до первой волны**: иначе каждая задача батча +предложи `av-dev-pm:canon` **до первой задачи**: иначе каждая задача батча заплатит поразрядной деградацией ревью, а имя основной ветки придётся угадывать. @@ -56,10 +61,16 @@ description: Проводит несколько задач разом — пл ## Ключевое отличие от одиночного пайплайна `task-pipeline` коммитит **в текущую ветку**, и при ручном запуске это основная -ветка. Здесь так нельзя для параллельных задач, поэтому батч — **осознанное -исключение**: временные ветки и worktree заводятся лишь как средство изоляции, а -конечное состояние — та же линейная история основной ветки через rebase + -fast-forward. Ветки после вливания удаляются. +ветка. Здесь так нельзя, поэтому батч — **осознанное исключение**: временные +ветки и worktree заводятся лишь как средство изоляции, а конечное состояние — та +же линейная история основной ветки через rebase + fast-forward. Ветки после +вливания удаляются. + +Изоляция нужна **в обоих режимах, а не только в параллельном**: батч не вливает +ветку, пока не проверил полноту её ревью (шаг 5), и упавшая задача обязана +остаться в своём worktree для ручного дожатия (шаг 6), не оставив следа в +основной ветке. В параллельном режиме к этому добавляется вторая причина — +задачи не должны видеть недоделанную работу друг друга. ## Модель исполнения @@ -87,10 +98,12 @@ fast-forward. Ветки после вливания удаляются. - **затронутые capability** — по её описанию и по каталогу актуальных спек (`openspec/specs/`); - **жёсткие зависимости**: задача B строится на результате A → A строго раньше B; -- **замеряющая задача** — та, чьё ревью будет доказывать находки **числами**, и - потому она гонится в волне **одна** (обоснование — ниже, в шаге 4). Решается - здесь, на планировании, а не во время прогона: состав волны определяется - сейчас, а профиль ревью сабагент выберет только внутри задачи, и ключевать +- **замеряющая задача** — та, чьё ревью будет доказывать находки **числами**. В + последовательном прогоне это ничего не меняет: она и так идёт одна. В + параллельном она гонится в волне **одна** (обоснование — ниже, в шаге 4). + Помечается здесь, на планировании, а не во время прогона, и **независимо от + режима**: состав волны определяется сейчас, режим может смениться просьбой уже + после плана, а профиль ревью сабагент выберет только внутри задачи — ключевать волну на ещё не сделанный выбор нельзя. Триггеры — по фактам о задаче, каждый сам по себе достаточен: - трогает схему хранилища, миграцию, формат на диске или объём хранимого; @@ -120,7 +133,9 @@ fast-forward. Ветки после вливания удаляются. **всем** задачам с таким артефактом, независимо от того, в какой волне они окажутся: раздача ничего не стоит, а её отсутствие ловится только конфликтом на интеграции. Между волнами проблемы нет — ветка следующей волны берётся от - вершины, уже включающей предыдущие; + вершины, уже включающей предыдущие; в последовательном прогоне проблемы нет по + той же причине, но номера всё равно раздай: режим может смениться просьбой, а + раздача бесплатна; - **жёстко сериализуем** (не гоняем одновременно) настоящие пересечения: - **одна capability на несколько задач** — две задачи, правящие одну спеку (тем более одно и то же `### Requirement`), дают не текстовый, а **семантический** @@ -130,39 +145,65 @@ fast-forward. Ветки после вливания удаляются. правит **свою** строку (индексы, оглавления, списки записей), и спеки разных capability — разные строки и файлы, сливаются сами. -Собери план: **волны** параллельно-безопасных задач плюс сериализованный хвост -конфликтоопасных, с учётом зависимостей; замеряющие задачи стоят в плане -отдельными волнами по одной. Покажи план короткой репликой — назвав, какие -задачи признаны замеряющими и по какому триггеру, — и иди дальше. +Собери план как **граф зависимостей**, а не как плоский список: рёбра — жёсткие +зависимости и сериализуемые пересечения. Дальше по режиму: + +- **последовательно (умолчание)** — линеаризуй граф в один порядок: + топологический, а там, где он оставляет свободу, — раньше то, от чего зависит + больше задач, и раньше то, что правит общие для набора места. Волн нет, + замеряющие задачи ничем не отличаются от прочих; +- **параллельно (по просьбе)** — нарежь граф на **волны**: в одну волну попадают + только задачи, между которыми нет ребра; замеряющие стоят отдельными волнами по + одной. + +Покажи план короткой репликой — режим, порядок или состав волн, какие задачи +признаны замеряющими и по какому триггеру, — и иди дальше. ### 3. Свежая база Убедись, что рабочее дерево чистое и основная ветка свежая. Зафиксируй базовый -коммит. Новые ветки бери от свежей вершины; ветки следующей волны — от вершины, -уже включающей результат предыдущих волн. +коммит. Новые ветки бери от свежей вершины; ветку следующей задачи (в +параллельном режиме — ветки следующей волны) — от вершины, уже включающей +результат предыдущих. -### 4. Прогнать волны +### 4. Провести задачи -**Потолок параллелизма — 2–3 задачи одновременно.** Каждая задача тянет полный -цикл пайплайна с вложенным ревью и гейтом, поэтому больше трёх разом душат -машину и провоцируют гонки. Волну шире трёх бей на под-пачки по ≤3 и **гони -под-пачки последовательно**: следующая стартует, когда предыдущая вернула отчёты. -Иначе потолок обходится тривиально — шесть задач, запущенных «двумя под-пачками» -в одном сообщении, это шесть задач разом. +**Умолчание — по одной задаче за раз, в порядке из шага 2.** Следующая стартует, +когда предыдущая вернула отчёт и (если она зелёная) влилась. Обосновывать это не +надо — обосновывается отступление. Причина умолчания в том, что задача батча +дороже прохода ревью: каждая тянет полный цикл пайплайна с гейтом, поднятием +сервиса и вложенным ревью, и две такие на одной машине дерутся за порты, рабочие +каталоги, СУБД и само железо. Последовательный прогон к тому же оставляет ревью +внутри задачи его собственное умолчание — **параллельные проходы**: машина +свободна, и выигрыш берётся там, где он ничего не стоит. -**Волна из одной задачи — не вырожденный случай, а обязательный.** Задача, -признанная на шаге 2 **замеряющей**, гонится в волне одна: соседний прогон на той -же машине портит числа, а находка с испорченным оракулом хуже отсутствующей — она -выглядит доказанной. Если замеряющая задача всё же пошла в общей волне, её отчёт -обязан нести строку в границах покрытия: замеры сняты под соседней нагрузкой. +**Параллельно — по явной просьбе, и параллельность идёт по графу зависимостей.** +Одновременно гонится только то, между чем на шаге 2 не нашлось ребра: ни жёсткой +зависимости, ни общей capability, ни общих исходников. «Гони параллельно» не +означает «гони всё разом» — граф остаётся в силе, просьба лишь разрешает +использовать его ширину. -Для каждой задачи в под-пачке: +В параллельном режиме действуют два ограничения: + +- **потолок — 2–3 задачи одновременно.** Больше трёх разом душат машину и + провоцируют гонки. Волну шире трёх бей на под-пачки по ≤3 и **гони под-пачки + последовательно**: следующая стартует, когда предыдущая вернула отчёты. Иначе + потолок обходится тривиально — шесть задач, запущенных «двумя под-пачками» в + одном сообщении, это шесть задач разом; +- **волна из одной задачи обязательна для замеряющей.** Задача, признанная на + шаге 2 **замеряющей**, гонится одна: соседний прогон на той же машине портит + числа, а находка с испорченным оракулом хуже отсутствующей — она выглядит + доказанной. Если замеряющая задача всё же пошла в общей волне, её отчёт обязан + нести строку в границах покрытия: замеры сняты под соседней нагрузкой. + +Для каждой задачи (в параллельном режиме — для каждой задачи под-пачки): 1. Заведи worktree и ветку от текущей вершины: `git worktree add -b task/ <основная ветка>`. Путь — во временном каталоге проекта (`./tmp`), не в системном `/tmp`. -2. Запусти **по одному сабагенту на задачу, все в одном сообщении**, - `subagent_type: general-purpose`. Charter сабагента: +2. Запусти сабагента, `subagent_type: general-purpose`: в последовательном режиме + — одного и дождись отчёта; в параллельном — **по одному на задачу под-пачки, + всех в одном сообщении**. Charter сабагента: - работай **строго в своём worktree** ``; в другие каталоги и в основную ветку не лезь; - прогони Skill **`av-dev-pipeline:task-pipeline`** ровно на этой задаче, @@ -171,8 +212,12 @@ fast-forward. Ветки после вливания удаляются. - **профиль ревью выбирается по факту изменения.** Батч не повод понижать профиль: «нас много и мы спешим» — это ровно тот стимул, из-за которого проходы пропускают; - - **режим прогона проходов — последовательный.** Твой worktree не один на - машине; + - **режим прогона проходов ревью — от режима батча**, и его называет charter, + а не сабагент: батч идёт по одной задаче → режим умолчательный, + **параллельный** (машина свободна); батч идёт волнами → **последовательный**, + твой worktree не один на машине, и этой причиной ты обязан объяснить режим в + отчёте. Меряющую пару `adversary` и `ops` конвейер держит по очереди сам, в + любом режиме; - **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из агента) — не пропускай ревью и не понижай профиль: проведи его **инлайн** по тем же charter'ам `av-dev-pipeline`, сохранив обязательное — гейт до @@ -189,6 +234,11 @@ fast-forward. Ветки после вливания удаляются. архивации — `openspec/changes/archive//review/`); шло ли ревью инлайн; границы покрытия. +**Шаги 5 и 6 отрабатываются на вернувшейся задаче до старта следующей** — в +параллельном режиме на вернувшейся волне до старта следующей. Иначе ветка +следующей возьмётся от вершины, не видевшей предыдущую работу, и весь смысл +порядка из шага 2 теряется. + Сабагент, упершийся в вопрос, **не останавливает батч**: он записывает вопрос, режет задачу до остатка и доводит остаток — либо, если остатка нет, возвращает исход «не доведена». Оркестратор собирает такие вопросы и выносит их в финальный @@ -296,11 +346,11 @@ rebase в файле X», а не «нераспознанное пересеч слияния**: - запусти **по одному `review-specs` на каждую затронутую capability**, - последовательно. Параллельно — только если человек попросил явно и назвал - набор: правило и оба его условия живут в - `av-dev-pipeline:review-pipeline`, раздел «Режим запуска», и здесь не - ослабляются. «Замеров не делают» основанием не является; -- **режим у этих проходов особый, и его надо назвать в задании.** Живого change + параллельно — как велит умолчание конвейера: замеров эти проходы не делают, + друг другу не мешают, а машина к этому моменту свободна (все сабагенты + вернулись). По очереди — только по особой причине из раздела «Режим запуска» + `av-dev-pipeline:review-pipeline`, и причину назови; +- **задание у этих проходов особое, и это надо сказать прямо.** Живого change здесь нет — все заархивированы, дельта-спек не существует. Источник требований — **актуальные** `openspec/specs//spec.md`, а предмет — стык: требование, которое одна задача выполнила, а соседняя незаметно отменила; два @@ -329,8 +379,9 @@ rebase в файле X», а не «нераспознанное пересеч строкой — иначе задача останется открытой молча. - Доложи кратко: - **исход по каждой задаче** одним из трёх слов, с хешем коммита; - - план волн и порядок интеграции, с пометкой, какие задачи шли по одной как - замеряющие; + - **режим прогона** — по одной или волнами, и если волнами, то по чьей просьбе; + порядок задач или состав волн, порядок интеграции, с пометкой, какие задачи + шли по одной как замеряющие; - вопросы, записанные сабагентами, пачкой; - что дозапускалось на шаге 5 и почему; шло ли где-то ревью инлайн; - итог финальной сверки и ссылки на архивные change; @@ -343,18 +394,22 @@ rebase в файле X», а не «нераспознанное пересеч ## Тонкости -- **Изоляция параллельных тестов.** Прежде чем гнать несколько прогонов разом, - убедись, что тесты не делят фиксированный порт или файл БД (обычно берут - временный каталог и эфемерный порт — тогда ок). Делят — гони такие задачи - последовательно. -- Поведенческая верификация внутри сабагента поднимает изменение вживую: следи, - чтобы соседние worktree не дрались за порты и рабочие каталоги. Если проект - умеет поднимать только один экземпляр — такие задачи в одну волну не ставь. +- **Изоляция параллельных тестов — цена параллельного режима, и проверяется она + до первой волны.** Прежде чем гнать несколько прогонов разом, убедись, что + тесты не делят фиксированный порт или файл БД (обычно берут временный каталог и + эфемерный порт — тогда ок). Делят — такие задачи гони по одной, даже если + просили параллельно, и скажи об этом строкой: просьба про параллельность, а не + про сломанные тесты. В умолчательном режиме вопрос не встаёт вовсе — это одна + из причин, по которым умолчание такое. +- Поведенческая верификация внутри сабагента поднимает изменение вживую: в + параллельном режиме следи, чтобы соседние worktree не дрались за порты и + рабочие каталоги. Если проект умеет поднимать только один экземпляр — такие + задачи в одну волну не ставь. - Ревью выполненного — **до** интеграции; это забота `av-dev-pipeline:task-pipeline` внутри каждого сабагента, дублировать не надо. - `openspec validate --strict` тоже внутри пайплайна задачи — не пропускай его своими правками на интеграции. - Крупная переработка, предложенная ревью внутри задачи, — развилка: не вливай молча, вынеси в доклад. -- Держи вызывающего в цикле короткими репликами на переходах фаз (план → волны → - интеграция → финальная сверка), но не проси подтверждать механику. +- Держи вызывающего в цикле короткими репликами на переходах фаз (план → прогон + задач → интеграция → финальная сверка), но не проси подтверждать механику. diff --git a/av-dev-pipeline/skills/task-pipeline/SKILL.md b/av-dev-pipeline/skills/task-pipeline/SKILL.md index 66a2c45..c35c464 100644 --- a/av-dev-pipeline/skills/task-pipeline/SKILL.md +++ b/av-dev-pipeline/skills/task-pipeline/SKILL.md @@ -229,12 +229,12 @@ description: Автономно проводит одну задачу чере последней. Помни ровно одно — **профиль выбирается по факту изменения, а не по ощущению важности**, и посмотри таблицу перед вызовом. -**Режим по умолчанию последовательный, и обосновывать его не надо.** Параллельно -гоняем только тогда, когда об этом попросили явно **и назвали набор** — какие -именно проходы или какую стадию. Просьба без набора основанием не считается: -гони последовательно и скажи строкой, что набор не был назван. Причина умолчания -— замеры: `adversary` и `ops` доказывают находки числами, а два меряющих прохода -на одной машине портят числа друг другу; находка с испорченным оракулом хуже +**Режим по умолчанию параллельный, и обосновывать его не надо.** По очереди гоняем +только по особой причине, и она называется строкой: об этом попросил оператор; +машина занята чем-то ещё (в том числе соседней задачей батча); идёт разбор самого +конвейера. Меряющую пару `adversary` и `ops` конвейер держит по очереди сам, без +твоего участия: оба доказывают находки числами, а два меряющих прохода на одной +машине портят числа друг другу — находка с испорченным оракулом хуже отсутствующей, потому что выглядит доказанной. Скилл сам гоняет гейт, нужные проходы и обязательный триаж. Возвращает отчёт с