From 57714c3549cb44e2c443a78fbdfe7003c55601ba Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Mon, 3 Aug 2026 20:22:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B4=D0=BE=D0=B2=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D1=8C=D1=8E=20=E2=80=94=20=D0=B3=D1=80=D0=B0=D1=84,=20?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D0=B0=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=B4=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Номер стадии не означал зависимости: между стадиями 1–4 ни один проход не читает вывод другого, и очередь между ними была платой ни за что. А правило про замеры держалось на двух именах и рассыпалось бы в день, когда мерить начнёт третий проход. Рёбер три вида, и они разной природы: зависимость (гейт → опиниативные, все проходы → триаж), конфликт за ресурс (ненаправленный) и барьер стоимости. Стадии остаются единицей состава, порядок задаёт граф: уходит всё, у чего входящие рёбра закрыты. Сериализует ресурс, а не имена: пометка «держит машину» — gate, adversary, ops, triage; остальные читают и рассуждают. Проект вправе пометить свой проход, снять пометку с перечисленных — нет. Ранний выход заменён барьером стоимости и стоит там, где выход зарабатывал: перед reimpl и architecture, то есть только в deep. Отдельным абзацем — что ребро значит порядок и никогда не данные: графовый словарь провоцирует обратное прочтение, а проход, увидевший чужие находки, соглашается с ними. Исключение одно и оно же сток. Диаграммы — mermaid, прогнаны через mermaid-cli. Режим прогона теперь «по графу» / «линейно»; task-batch и task-pipeline подтянуты под общий словарь, adversary и ops знают о пометке из своих charter'ов. DECISIONS 15. Co-Authored-By: Claude Opus 5 (1M context) --- DECISIONS.md | 59 +++++ av-dev-pipeline/agents/review-adversary.md | 6 + av-dev-pipeline/agents/review-ops.md | 6 + .../skills/review-pipeline/SKILL.md | 249 ++++++++++++------ av-dev-pipeline/skills/task-batch/SKILL.md | 53 +++- av-dev-pipeline/skills/task-pipeline/SKILL.md | 16 +- 6 files changed, 296 insertions(+), 93 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index df28858..9f7f38b 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -994,3 +994,62 @@ HTML-комментарии, невидимые в отрендеренном ma фиксированный порт или файл БД, и проект, умеющий поднимать один экземпляр, — основание гнать по одной даже после просьбы, сказанное строкой: просьба была про параллельность, а не про сломанные тесты. + +## 15. Порядок проходов ревью — граф зависимостей (2026-08-03) + +### Что было + +Решение 14 перевернуло умолчание, но оставило порядок в прежней форме: «стадии +идут по порядку номеров, параллельность — только внутри стадии». Номер стадии при +этом ничего не означает: между стадиями 1–4 ни один проход не читает вывод +другого, так что очередь между ними была платой ни за что. А правило про замеры +держалось на **двух именах** — `adversary` и `ops`, — и рассыпалось бы в тот +день, когда мерить начнёт третий проход или проект добавит свой. + +### Решено + +**XX. Порядок задаёт граф; стадии остаются единицей состава.** Профиль +по-прежнему набирается стадиями, но запускается всё, у чего закрыты входящие +рёбра. Рёбер три вида, и смешивать их нельзя: **зависимость** (гейт → все +опиниативные, все проходы → триаж), **конфликт за ресурс** (ненаправленный, между +теми, кто держит машину), **барьер стоимости** (только `deep`). + +**YY. Сериализует ресурс, а не имена.** Пометка «держит машину» — таблицей в +скилле: `gate`, `adversary`, `ops`, `triage`; читают и рассуждают — `specs`, +`code`, `reimpl`, `architecture`, `rubric`. Проект вправе пометить свой проход в +`docs/review.md`; снимать пометку с перечисленных нельзя. Правило теперь +самораспространяется: начнёт проход мерить — попадёт в цепочку по факту, а не по +поправке. + +**ZZ. Ранний выход заменён барьером стоимости.** Он стоит там, где ранний выход +зарабатывал: перед `reimpl` (пишет реализацию целиком) и `architecture`. В +`quick`/`standard` барьера нет — стадий 3–4 там не бывает; в `design` нет по +другой причине — предметом там и является форма, защищать нечего. + +**AAA. Ребро — это порядок, никогда не данные.** В обычном графе задач ребро +тянет за собой вывод предшественника; здесь это запрещено: проход, увидевший +чужие находки, соглашается с ними, и декорреляция — вся ценность конвейера — +обнуляется. Сказано в самом правиле, потому что графовый словарь провоцирует +ровно эту ошибку. Исключение одно и оно же сток: триаж. + +**BBB. Диаграммы в скиллах — `mermaid`.** Граф, описанный прозой, читается как +инструкция и теряет форму; диаграмма показывает её целиком. Четыре штуки: общий +граф прогона, граф профиля `design`, пример графа задач батча, веер финальной +сверки. + +### Что из этого следует + +59. **Триаж — сток по определению, а не «стадия 5».** Отсюда без отдельного + обоснования следует правило, которое раньше приходилось защищать: на неполном + графе триаж не запускается, потому что агрегировал бы половину и выглядел бы + полным. +60. **Словарь рёбер общий у ревью и батча.** «Жёсткая зависимость» и + «сериализуемое пересечение» в `task-batch` — те же два вида рёбер; + формулировки сведены, и в обоих скиллах стоит ссылка на другой. +61. **Значения режима стали `по графу` и `линейно`.** Прежние «параллельно» и + «последовательно» описывали способ запуска, а не структуру; линеаризация + осталась отступлением с тремя причинами (оператор, занятая машина, разбор + самого конвейера). +62. **Проход, держащий машину, знает об этом из своего charter'а.** `adversary` и + `ops` получили по абзацу: цепочка гарантирует им чистое железо, значит их + число — оракул, и шум в нём объясняется замером, а не соседом. diff --git a/av-dev-pipeline/agents/review-adversary.md b/av-dev-pipeline/agents/review-adversary.md index 61b301b..f2b5bd0 100644 --- a/av-dev-pipeline/agents/review-adversary.md +++ b/av-dev-pipeline/agents/review-adversary.md @@ -16,6 +16,12 @@ color: red `${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md` (точный путь конвейер передаёт в задании). +**Ты помечен «держит машину»** — за тем, чтобы построенный путь можно было +**прогнать**, а не описать. Конвейер ставит тебя в цепочку с другими такими +проходами: пока ты работаешь, никто рядом не меряет и не поднимает сервис. Значит, +падающий тест, которым ты доказываешь путь, воспроизводим — и ссылка на него +законный оракул. + ## Модель угроз — из `docs/security.md`, и не расширяй её самовольно **Первая строка `docs/security.md` — периметр,** и она задаёт смысл всему diff --git a/av-dev-pipeline/agents/review-ops.md b/av-dev-pipeline/agents/review-ops.md index d586570..745016c 100644 --- a/av-dev-pipeline/agents/review-ops.md +++ b/av-dev-pipeline/agents/review-ops.md @@ -14,6 +14,12 @@ color: yellow `${CLAUDE_PLUGIN_ROOT}/skills/review-pipeline/references/finding-contract.md` (точный путь конвейер передаёт в задании). +**Ты помечен «держит машину».** Конвейер за это ставит тебя в цепочку с другими +такими проходами — одновременно с тобой никто не меряет. Значит, снятое тобою +число и есть оракул, а не «примерно»: если оно шумит, причина в самом замере, и +её надо назвать, а не списать на соседа. Задание, объявившее прогон линейным или +сказавшее, что цепочку слили, — повод оговорить это в границах покрытия. + ## Что такое «прод» здесь — из документов проекта **`docs/architecture.md`, раздел эксплуатации:** где это работает и что рядом; diff --git a/av-dev-pipeline/skills/review-pipeline/SKILL.md b/av-dev-pipeline/skills/review-pipeline/SKILL.md index 6657068..2d7f2ba 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: Конвейер ревью изменения — детерминированный гейт, сверка с дельта-спеками в обе стороны, враждебные постановки и эксплуатационный постмортем, независимая реализация по триггеру, архитектура и обязательный триаж. Порядок прогона — граф зависимостей, а не очередь: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, дорогие generative-проходы стоят за барьером стоимости, триаж — единственный сток. Линейный прогон — по слову оператора или на занятой машине. Проектная специфика приходит из документов канона av-dev-pm. Вызывается из task-pipeline (чекпоинты ревью), из task-batch (финальная сверка) и отдельно — профилем design на предложении ДО кода. --- # Конвейер ревью @@ -95,7 +95,7 @@ description: Конвейер ревью изменения — детермин - **сужение**, если оно есть: конкретный узел, конкретная capability. Чего проход **не** получает ни в каком режиме — выводов других проходов. См. -«Режим запуска». +«Порядок прогона». ## Модель по проходу @@ -176,81 +176,139 @@ description: Конвейер ревью изменения — детермин Профиль объявляется в отчёте. Понижение профиля — решение оркестратора, и оно попадает в границы покрытия строкой «профиль понижен до X, потому что …». -## Режим запуска: параллельно или последовательно +## Порядок прогона — граф, а не очередь -Профиль отвечает «какие проходы», режим — «как их запускать». Стадии всегда идут -по порядку номеров; выбор касается только проходов **внутри** стадии. +Профиль отвечает «какие проходы», порядок — «что кого ждёт». Стадии остаются +единицей **состава** (профиль набирается стадиями, см. таблицу выше), но порядок +задают **не их номера**: между стадиями 1–4 настоящих зависимостей нет — ни один +проход не читает вывод другого, — и очередь между ними была бы платой ни за что. -| Режим | Как | Когда | +Рёбер три вида, и они разной природы. Путать их нельзя: первое про +**осмысленность** (на красном гейте опиниативный проход не о чем), второе про +**железо**, третье про **деньги**. + +| Ребро | Смысл | Между кем | |---|---|---| -| **параллельно** (умолчание) | проходы стадии — одним сообщением | всегда, пока не сработала особая причина | -| **последовательно** | по одному, следующий стартует после отчёта предыдущего | по слову оператора **или** по одной из особых причин ниже | +| **зависимость** | B не стартует, пока A не закончил, потому что без A задание B не определено | гейт → все опиниативные; все проходы → триаж | +| **конфликт за ресурс** | A и B не держат машину одновременно; кто из них первый — неважно, направления у ребра нет | проходы, помеченные «держит машину» | +| **барьер стоимости** | дорогое не запускается, пока дешёвое не сказало, что форма изменения выживет | только `deep` | -**Умолчание — параллельно, и его не надо обосновывать.** Обосновывается -отступление. Проходы независимы по построению: ни один не видит выводов другого -(см. ниже), у всех общий вход и разные критерии. Очередь между ними не добавляет -ничего, кроме ожидания, — а ожидание на каждом чекпоинте ревью платится каждой -задачей. +```mermaid +flowchart TD + gate["gate
(стадия 0, держит машину)"] + specs["specs"] + code["code"] + adversary["adversary
(держит машину)"] + ops["ops
(держит машину)"] + barrier{{"форма изменения выживает?"}} + reimpl["reimpl
(по триггеру)"] + architecture["architecture"] + triage["triage — единственный сток"] -**Последовательно гоним в трёх случаях, и каждый называется в отчёте:** + gate -->|зелёный| specs + gate -->|зелёный| code + gate -->|зелёный| adversary + gate -->|зелёный| ops + adversary -. один ресурс — машина .- ops + specs --> barrier + code --> barrier + adversary --> barrier + ops --> barrier + barrier -->|"deep"| reimpl + barrier -->|"deep"| architecture + barrier -->|"quick, standard: барьера нет"| triage + reimpl --> triage + architecture --> triage +``` -1. **сказал оператор** — «гони последовательно». Набор при этом называть не - обязательно: последовательный прогон ничего не портит, он только дольше, и - домысливать тут нечего; -2. **проходы меряют.** `adversary` и `ops` доказывают находки числами: время - удержания блокировки против её таймаута, пик кучи против размера тела, темп - роста файлов журнала, длительность транзакции. Два меряющих прохода на одной - машине соревнуются за диск, CPU и за саму СУБД и выдают числа, которые не - воспроизведутся. Это не гипотеза: правило выведено из находок, целиком - державшихся на таких замерах, — у каждого проекта они свои и лежат в журнале - `docs/review.md`. Число, снятое под конкурентную нагрузку от соседнего - прохода, — это находка с испорченным оракулом, а её опровержение стоит дороже - всего выигрыша от параллельности. **Эта пара идёт по очереди всегда** — это - правило стадии 2, а не решение прогона (см. её раздел); -3. **машина занята, и знает об этом вызывающий.** Рядом идёт другая задача, - поднят сервис, гоняется гейт или дорогая проверка проекта. Сам конвейер - занятости машины не видит — её обязан назвать тот, кто запускает; так и - делает `av-dev-pipeline:task-batch`, когда ведёт задачи параллельно. +Читается граф так: **всё, у чего входящие рёбра закрыты, уходит одним +сообщением**. В `standard` после зелёного гейта это три узла разом — `specs`, +`code` и первый из меряющей пары, — а второй меряющий идёт следом за первым. В +`quick` — `specs` и `code` разом, и сразу триаж. -Отдельная причина, не связанная со стоимостью, — **разбор самого конвейера**: -когда выясняется, почему проход чего-то не нашёл, порядок и изоляция важнее -скорости. +**Ребро значит «A закончил раньше, чем B стартовал», и ничего больше.** В обычном +графе задач ребро тянет за собой данные — здесь нет, и это не деталь реализации. +Проход **не видит** находок других проходов, в каком бы порядке их ни запустили. +Вся ценность конвейера держится на декорреляции: под всеми ролями одна модель с +одними априорными, и стоит показать ей чужой вывод — она согласится. Согласие +нескольких проходов и так не повышает `confidence` (см. «Честный предел»); +согласие **наведённое** ещё и маскируется под независимое подтверждение. +Единственный, кто получает чужие выводы, — триаж, и это его работа. -Если меряющие проходы всё же пошли разом — а это бывает только по прямому слову -оператора, — в границы покрытия идёт строка: какие проходы шли одновременно и -что замеры этого прогона как оракул слабее. +### Кто держит машину -**Чего режим не меняет — и это не подлежит обсуждению.** Проход **не видит** -находок других проходов ни в каком режиме. «Последовательно» значит «по -очереди», а не «следующий читает предыдущего». Вся ценность конвейера держится -на декорреляции: под всеми ролями одна модель с одними априорными, и стоит -показать ей чужой вывод — она согласится. Согласие нескольких проходов и так не -повышает `confidence` (см. «Честный предел»); согласие **наведённое** ещё и -маскируется под независимое подтверждение. Единственный, кто видит всё, — триаж, -и это его работа. +Ресурс один и неделимый: **машина** — тесты, поднятый сервис, СУБД, порты, диск. +Проходы, заявившие его, сериализуются между собой в любом профиле и на любой +стадии; порядок внутри цепочки произволен. -**Ранний выход — по границе стадии.** Стадии идут по порядку в любом режиме, -поэтому остановиться между ними можно всегда; последовательный режим добавляет к -этому возможность остановиться **внутри** стадии — это его побочная выгода, а не -повод его выбирать. Допустимо остановить прогон, не докатив остаток, ровно в -одном случае: находка требует **переделки формы** изменения, и -остальные проходы будут смотреть на код, которого через час не станет. Тогда: +| Проход | Держит машину | Почему | +|---|---|---| +| `gate` | да | запускает инструменты проекта — но он источник графа и один по построению | +| `adversary` | да | находка есть **построенный путь**: он пишет падающий тест и гоняет его | +| `ops` | да | доказывает числами: время удержания блокировки, пик кучи, темп роста журнала | +| `triage` | да | проверяет оракул `critical`/`major` запуском — но он сток и тоже один | +| `specs`, `code`, `reimpl`, `architecture`, `rubric` | нет | читают и рассуждают; `reimpl` пишет свою реализацию в черновик, но не исполняет её | -- прогон останавливается, находка чинится, конвейер запускается **заново с - нулевой стадии** — а не «доезжает» остатком по старому коду; -- незапущенные проходы идут в границы покрытия строкой «не запускался: прогон - остановлен на <проход или стадия> из-за <находка>», поимённо; -- триаж запускается только на полном прогоне. Отчёт триажа по половине проходов - выглядит полным, потому что агрегирует всё, что ему подали, — это тот же - молчащий пропуск, что и в разделе «Профили». +**Правило про ресурс, а не про имена.** Раньше здесь стояло именованное +исключение «`adversary` и `ops`»; оно рассыпается, как только проход начнёт +мерить или в проекте появится свой. Два прохода на одной машине соревнуются за +диск, CPU и за саму СУБД и выдают числа, которые не воспроизведутся, — а число, +снятое под конкурентную нагрузку, это находка с испорченным оракулом. Её +опровержение стоит дороже всего выигрыша от параллельности, и она хуже +отсутствующей: выглядит доказанной. Правило выведено из находок, целиком +державшихся на таких замерах; у каждого проекта они свои и лежат в журнале +`docs/review.md`. -Ранний выход по находке, которая чинится в пределах существующей формы -(`Действие: инлайн`), **не делается**: дешевле дособрать все находки и починить -пачкой, чем гонять конвейер дважды. +Проект вправе пометить «держит машину» и другой проход — в `docs/review.md`, +разделе настройки конвейера. Снимать пометку с перечисленных нельзя. -Режим объявляется в отчёте наравне с профилем. Параллельный — одним словом. -**Последовательный — с причиной** (какой именно из трёх) и с составом, если по -очереди шла только часть проходов. +### Барьер стоимости — вместо раннего выхода + +Барьер существует ровно там, где ранний выход зарабатывал: `reimpl` пишет +реализацию целиком и потому самый дорогой проход конвейера, `architecture` +смотрит вход шире диффа. Если дешёвая часть нашла, что **форму изменения** надо +переделывать, оба будут читать код, которого через час не станет. + +- **прошло без находок «переделать форму»** — барьер открыт, дорогие проходы + уходят разом; +- **есть такая находка** — прогон останавливается, находка чинится, конвейер + запускается **заново с нулевой стадии**, а не «доезжает» остатком по старому + коду. Незапущенные проходы идут в границы покрытия строкой «не запускался: + прогон остановлен на <проход> из-за <находка>», поимённо. Триаж на половине + прогона не запускается: его отчёт выглядит полным, потому что агрегирует всё, + что ему подали, — это тот же молчащий пропуск, что и в разделе «Профили»; +- **находка чинится в пределах существующей формы** (`Действие: инлайн`) — + барьер не срабатывает: дешевле дособрать все находки и починить пачкой, чем + гонять конвейер дважды. + +В `quick` и `standard` барьера нет — за ним нечего защищать: стадий 3–4 в этих +профилях не бывает, и граф там плоский от гейта до триажа. Находка «переделать +форму» ловится в них триажем, а прогон после починки повторяется целиком: платить +за это нечем, дорогих проходов в этих профилях нет. В `design` его тоже +нет, и по другой причине: там предметом и является форма, а все три прохода +читают одно предложение — защищать нечего, у графа этого профиля своя форма (см. +его раздел). + +### Линеаризация — когда графа мало + +Граф можно вытянуть в одну цепочку. Это отступление, и оно называется в отчёте: + +1. **сказал оператор** — «гони линейно». Набора называть не надо: линейный прогон + ничего не портит, он только дольше, и домысливать тут нечего; +2. **машина занята, и знает об этом вызывающий.** Рядом идёт другая задача, + поднят сервис, гоняется дорогая проверка проекта. Сам конвейер занятости + машины не видит — её обязан назвать тот, кто запускает; так и делает + `av-dev-pipeline:task-batch`, когда ведёт задачи параллельно; +3. **разбор самого конвейера** — когда выясняется, почему проход чего-то не + нашёл, порядок и изоляция важнее скорости. + +Обратное отступление — **слить цепочку ресурса** (пустить меряющие проходы +разом) — бывает только по прямому слову оператора, и тогда в границы покрытия +идёт строка: какие проходы шли одновременно и что замеры этого прогона как +оракул слабее. + +Режим объявляется в отчёте наравне с профилем: **`по графу`** — одним словом, +**`линейно`** — с причиной (какой именно из трёх). ## Стадия 0 — Gate (обязательна во всех профилях) @@ -276,8 +334,8 @@ description: Конвейер ревью изменения — детермин ## Стадия 1 — Conformance (обязательна во всех профилях) Два applicative-прохода: оба применяют **записанный** критерий, оба дешёвые. -Замеров они не делают и не мешают друг другу ничем — это канонический случай -умолчания: оба уходят одним сообщением. +Машину не держат ни один, ребра между ними нет — уходят одним сообщением сразу +после зелёного гейта, вместе со стадией 2, если она в профиле. - `review-specs` — критерий взят из **дельта-спек предлагаемого изменения**, а не из proposal, сообщения коммита или описания задачи. Сверка двунаправленная; @@ -297,13 +355,14 @@ Recall обоих равен длине их источника — это и е - `review-adversary` — находка есть **построенный путь**, а не свойство; - `review-ops` — постмортем от симптома у владельца сервиса к строке кода. -**Эта пара — именованное исключение из умолчания: она идёт по очереди всегда.** -Оба доказывают находки замером, и оба меряют одно и то же железо. Запущенные -разом, они портят числа друг другу, а испорченный оракул хуже отсутствующего: -находка выглядит доказанной. Очередь здесь не обосновывается — она правило -стадии, и на общее «гони параллельно» не отменяется. Если оператор прямо велел -гнать разом **и эту пару** — выполняй, но скажи в границах покрытия, что числа -этого прогона сняты под соседней нагрузкой. +**Оба помечены «держит машину», поэтому между ними ребро конфликта: они идут +цепочкой, а не разом** (правило и его причина — в «Порядок прогона», раздел «Кто +держит машину»). Направления у ребра нет: кто первый — неважно. Со стадией 1 они +конфликта не имеют и стартуют одновременно с ней; ждать её незачем. + +Цепочка не отменяется общим «гони по графу» — она и есть часть графа. Отменяет +её только прямое слово оператора про эту пару, и тогда в границы покрытия идёт +строка, что числа прогона сняты под соседней нагрузкой. **Эта стадия зарабатывает больше всех остальных вместе, и потому стоит в `standard`, а не только в `deep`.** Измерено на пяти задачах подряд: враждебный @@ -321,6 +380,9 @@ Recall обоих равен длине их источника — это и е ## Стадия 3 — Independent reimplementation (`deep`, по триггеру) +Стоит **за барьером стоимости** вместе со стадией 4 — она ради этих двух проходов +и существует. + - `review-reimpl` — пишет свою реализацию, не открывая существующую, затем диффит по решениям. **Запускается по триггеру, а не всегда:** изменение вводит новое правило идентичности, слияния или разбора (проектная формулировка @@ -333,7 +395,11 @@ Recall обоих равен длине их источника — это и е ## Стадия 4 — Global (`deep`, `design`) -Агент `review-architecture`. Получает **вход шире диффа**: дерево пакетов с +Агент `review-architecture`. В `deep` стоит **за барьером стоимости**, в `design` +— в одном ряду с двумя другими проходами. Машину не держит, с `reimpl` конфликта +не имеет: за барьером они уходят разом. + +Получает **вход шире диффа**: дерево пакетов с назначением, граф внутренних зависимостей, инвентарь существующих концепций. Команду, которая это готовит, даёт раздел команд `CLAUDE.md`; нет команды — проход собирает карту сам и говорит об этом в границах покрытия. @@ -348,9 +414,14 @@ Recall обоих равен длине их источника — это и е ## Стадия 5 — Triage (обязательна) -Агент `review-triage`. Единственный, кто агрегирует. Получает сырые выводы всех -проходов, `git diff`, профиль, режим и **список запущенных проходов**; возвращает -финальный отчёт. +Агент `review-triage`. **Единственный сток графа и единственный, кто агрегирует.** +Входящие рёбра — все запущенные проходы: пока хоть один не вернул отчёт, триаж не +стартует. Получает сырые выводы всех проходов, `git diff`, профиль, режим и +**список запущенных проходов**; возвращает финальный отчёт. + +Отсюда же правило, которое иначе выглядит придиркой: **триаж на неполном графе не +запускается**. Прогон, остановленный барьером или ранним выходом, до стока не +доезжает — его отчёт агрегировал бы половину и выглядел бы полным. Без триажа проходы дают порядка сорока замечаний при единицах существенных. Потребитель здесь — оркестратор, который **молча реализует** всё, что прочитал: @@ -377,6 +448,30 @@ Recall обоих равен длине их источника — это и е 4. вопрос автору дизайна: **«предложи три формы решения и назови компромисс каждой»** — если ответ показывает, что рассматривалась одна, это находка. +**Граф этого профиля свой, и он плоский.** Гейта нет — кода ещё нет, запускать +нечего; машину не держит ни один из трёх; сток — не триаж, а шаг 5 пайплайна +задачи, где замечания отрабатываются правкой спек. Триаж здесь не нужен: находок +единицы, и каждая либо правит спеку, либо становится развилкой. + +```mermaid +flowchart TD + proposal["предложение: proposal.md + дельта-спеки"] + specs["specs (режим «дизайн ДО кода»)"] + rubric["rubric, фаза 1 → приёмочные критерии в tasks.md"] + arch["architecture на предложении"] + author["вопрос автору: три формы решения и компромисс каждой"] + fix["шаг 5 пайплайна: правка спек, развилки — вопросом в запись"] + + proposal --> specs + proposal --> rubric + proposal --> arch + proposal --> author + specs --> fix + rubric --> fix + arch --> fix + author --> fix +``` + Смысл профиля: архитектурная находка на готовом коде стоит переписывания и поэтому игнорируется; та же находка на предложении стоит абзаца обсуждения. diff --git a/av-dev-pipeline/skills/task-batch/SKILL.md b/av-dev-pipeline/skills/task-batch/SKILL.md index 88b7350..ec73977 100644 --- a/av-dev-pipeline/skills/task-batch/SKILL.md +++ b/av-dev-pipeline/skills/task-batch/SKILL.md @@ -156,6 +156,26 @@ description: Проводит несколько задач разом — пл только задачи, между которыми нет ребра; замеряющие стоят отдельными волнами по одной. +Рёбра у графа двух видов, и путать их не надо: **зависимость** направлена (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`. + Покажи план короткой репликой — режим, порядок или состав волн, какие задачи признаны замеряющими и по какому триггеру, — и иди дальше. @@ -213,11 +233,11 @@ description: Проводит несколько задач разом — пл профиль: «нас много и мы спешим» — это ровно тот стимул, из-за которого проходы пропускают; - **режим прогона проходов ревью — от режима батча**, и его называет charter, - а не сабагент: батч идёт по одной задаче → режим умолчательный, - **параллельный** (машина свободна); батч идёт волнами → **последовательный**, - твой worktree не один на машине, и этой причиной ты обязан объяснить режим в - отчёте. Меряющую пару `adversary` и `ops` конвейер держит по очереди сам, в - любом режиме; + а не сабагент: батч идёт по одной задаче → режим умолчательный, **`по + графу`** (машина свободна); батч идёт волнами → **`линейно`**, твой worktree + не один на машине, и этой причиной ты обязан объяснить режим в отчёте. + Внутренние рёбра графа — цепочку проходов, держащих машину, и барьер + стоимости — конвейер соблюдает сам, в любом режиме; - **если вложенные сабагенты недоступны** (движок не даёт запускать агентов из агента) — не пропускай ревью и не понижай профиль: проведи его **инлайн** по тем же charter'ам `av-dev-pipeline`, сохранив обязательное — гейт до @@ -345,10 +365,10 @@ rebase в файле X», а не «нераспознанное пересеч находки и удорожат триаж. Здесь проверяется **только то, что появилось от слияния**: -- запусти **по одному `review-specs` на каждую затронутую capability**, - параллельно — как велит умолчание конвейера: замеров эти проходы не делают, - друг другу не мешают, а машина к этому моменту свободна (все сабагенты - вернулись). По очереди — только по особой причине из раздела «Режим запуска» +- запусти **по одному `review-specs` на каждую затронутую capability**, все + разом — граф здесь плоский: машину эти проходы не держат, ребра между ними нет, + а сама машина к этому моменту свободна (все сабагенты вернулись). Линейно — + только по причине из раздела «Порядок прогона» `av-dev-pipeline:review-pipeline`, и причину назови; - **задание у этих проходов особое, и это надо сказать прямо.** Живого change здесь нет — все заархивированы, дельта-спек не существует. Источник требований @@ -365,6 +385,21 @@ rebase в файле X», а не «нераспознанное пересеч опирается. Прогон из двух проходов без триажа — это сырые находки, выданные за разобранные. +Граф этой сверки — веер в один сток, и он такой же, как у обычного прогона: + +```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 +``` + Замечания отрабатывай как одиночный пайплайн: `инлайн` чини сам, `развилка` — вопросом в запись; после правок — снова гейт. diff --git a/av-dev-pipeline/skills/task-pipeline/SKILL.md b/av-dev-pipeline/skills/task-pipeline/SKILL.md index c35c464..3e2d14b 100644 --- a/av-dev-pipeline/skills/task-pipeline/SKILL.md +++ b/av-dev-pipeline/skills/task-pipeline/SKILL.md @@ -229,13 +229,15 @@ description: Автономно проводит одну задачу чере последней. Помни ровно одно — **профиль выбирается по факту изменения, а не по ощущению важности**, и посмотри таблицу перед вызовом. -**Режим по умолчанию параллельный, и обосновывать его не надо.** По очереди гоняем -только по особой причине, и она называется строкой: об этом попросил оператор; -машина занята чем-то ещё (в том числе соседней задачей батча); идёт разбор самого -конвейера. Меряющую пару `adversary` и `ops` конвейер держит по очереди сам, без -твоего участия: оба доказывают находки числами, а два меряющих прохода на одной -машине портят числа друг другу — находка с испорченным оракулом хуже -отсутствующей, потому что выглядит доказанной. +**Режим по умолчанию — `по графу`, и обосновывать его не надо.** Конвейер сам +знает свои рёбра: гейт открывает опиниативные проходы, проходы с пометкой «держит +машину» идут цепочкой (иначе замеры портят друг друга и находка выглядит +доказанной), дорогие generative-проходы ждут барьера стоимости, триаж — сток. +Твоего участия это не требует. + +Просить **`линейно`** нужно только по причине, и она называется строкой: так +сказал оператор; машина занята чем-то ещё (в том числе соседней задачей батча); +идёт разбор самого конвейера. Скилл сам гоняет гейт, нужные проходы и обязательный триаж. Возвращает отчёт с потолком 7 пунктов, разметкой `Действие: инлайн | развилка` и секцией границ